使用eclipse将项目发布到tomcat都做了那些事呢?
步骤1: eclipse 会把src中java文件编译成class文件, 放到 WebRoot/WEB-INF/classes 目录下.
步骤2: eclipse将WebRoot 复制粘贴到tomcat/webapps目录下, 并且将 WebRoot 改名为 项目名(如test).
servlet容器: tomcat(java的web服务器)
sun公司要求服务器,创建servlet的同时,再去创建一个servletConfig对象.
ServletConfig包含了一些Servlet的配置信息.再调用servlet的init方法时,将
servletCongfig传给servlet servletConfig的内容是 是自己定义的. 在web.xml中 的servlet标签下书写servletConfig的内容
<servlet>
<servlet-name>DemoServlet</servlet-name>
<servlet-class>cn.itcast.web.DemoServlet</servlet-class>
<init-param>
<param-name>path2</param-name>
<param-value>C:/a.png</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DemoServlet</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>
@Override
public void init(ServletConfig config) throws ServletException {
String initParameter = config.getInitParameter("path2");
System.out.println(initParameter);
//获取所有的初始化参数的名称
Enumeration<String> names = config.getInitParameterNames();
while(names.hasMoreElements()){
System.out.println(names.nextElement());
}
System.out.println(config.getServletContext());
System.out.println(config.getServletName());
}
private String path=null;
@Override
public void init(ServletConfig config) throws ServletException {
path = config.getInitParameter("path");
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//String path="C:/a.png";
FileInputStream in = new FileInputStream(new File(path));
ServletOutputStream out = response.getOutputStream();
int len=-1;
byte[] buf=new byte[1024];
while((len=in.read(buf))!=-1){
out.write(buf, 0, len);
}
in.close();
}
ServletContext接口
场景:
在线人数:xxx万,吸引用户来注册。
当用户进入系统,应该当前在线人数加一——servlet处理
当用户退出系统,应该当前在线人数减一——servlet处理
需求:
有在线人数的数据,必须,可以让两个servlet都可以获取使用。
希望:有这么一个容器(保存数据),这个容器可以被多个servlet同时使用。
这个就是我们ServletContext容器:
总结:
1 容器可以存储数据
2 操作容器set get remove
3 可以被多个Servlet使用共享。
当tomcat启动时,会为每个web应用创建一个唯一的ServletContext对象代表当前Web应用.该对象不仅封装了当前web应用的所有信息,而且实现了多个servlet的数据共享.
在每个项目中可以有多个Servlet程序,每个Servlet程序都是独立的。Servlet中的配置信息可以使用ServletConfig获取,而当前这个项目的配置信息,就必须使用
描述这个项目的ServletContext对象获取。
<context-param>
<param-name>shanghai</param-name>
<param-value>传智播客</param-value>
</context-param>
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取servletContext容器,测试存取删操作
ServletContext context = this.getServletContext();
context.setAttribute("addr", "东莞");
String addr = (String) context.getAttribute("addr");
System.out.println(addr);
context.removeAttribute("addr");
String addr2 = (String) context.getAttribute("addr");
System.out.println(addr2);
//获取web.xml中context-param标签的配置参数(因为ServletContext所以的servlet都可以获取,这些数据是全局配置参数)
Enumeration<String> names = context.getInitParameterNames();
while(names.hasMoreElements()){
String next = names.nextElement();
System.out.println(next+":"+context.getInitParameter(next));
}
//读取当前项目中c3p0配置文件 "/":表示从当前项目查找
// eclipse中的项目,src文件夹下的内容,在发布到服务器之后,保存在WEB-INF/classes文件夹下
//C:\software\apache-tomcat-7.0.81\webapps\Day35_request\WEB-INF\classes\c3p0-config.xml
String realPath = context.getRealPath("/WEB-INF/classes/c3p0-config.xml");
FileInputStream in = new FileInputStream(new File(realPath));
ServletOutputStream out = response.getOutputStream();
int len=-1;
byte[] buf=new byte[1024];
while((len=in.read(buf))!=-1){
out.write(buf, 0, len);
}
in.close();
}
编码处理
1 处理get请求乱码 String string = new String(parameter.getBytes(“iso-8859-1”),”utf-8”);
2 处理post请求乱码 request.setCharacterEncoding(“utf-8”);
//发送响应
//1 在获取打印流之前先设置好编码
//response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<h1>test servlet Ok</h1>");
//writer.write("<h1>访问Servlet程序成功!!!</h1>");
/**
* ServletContext容器可以存取数据,可以被多个servlet共享
* request容器存取数据,可以被多个servlet共享
*
* 研究区别:
* 1 ServletContext 生存时间:从项目启动到项目的停止
* 2 request对象 生存时间:从请求到达服务器开始一直到响应发送给浏览器,request对象就失效。
*
* 具体应用的时候:
* request容器该保存什么样的数据?
* 答:一次请求中需要使用的数据。例如:商品数据存入request容器。
*
* ServletContext容器该保存什么样的数据?
* 答:保存整个项目需要访问的数据。例如:在线人数。
*/
总结:
当一个Web资源收到客户端的请求后,如果希望服务器通知另外一个资源处理.
可以通过 转发对象 RequestDispatcher 对象的forward(request,response)方法,将当前请求传递给其他的Web资源进行处理,这种方式称为请求转发。
BeanUtils的populate方法模拟
public class BeanUtils {
public static void populate(Object o, Map map) {
//当前obj对象,需要封装数据,需要获取当前对象的成员变量
// 由于传入的数据,已经转换成Object类型,无法直接操作成员变量
// 通过反射的方式操作,获取成员变量:
Class clazz = o.getClass();
Field[] fields = clazz.getDeclaredFields();
// 通过反射给成员变量添加数据
try {
for(Field f:fields){
//打开非法访问——取消java语言的访问检查
f.setAccessible(true);
f.set(o, map.get(f.getName()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//需求:
// 1 提供一个map集合,保存了用户的数据。
// 2 将用户的数据从map集合中取出来,
// 3 封装到指定的对象(Person)中。
@Test
public void test1() {
Map map=new HashMap();
map.put("name", "老王");
map.put("age", 18);
Person p=new Person();
//将封装数据,交给其他对象(BeanUtils)去完成
BeanUtils.populate(p,map);
System.out.println(p);
}
response
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//response.setStatus(500);
//response.setHeader("Refresh", "3;url=http://www.jd.com");
//设置重定向
//response.setStatus(302);
//response.setHeader("Location", "http://www.jd.com");
//response.sendRedirect("http://localhost:9090/day09/1.html");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<h1>努力到无能为力 拼搏到感动自己</h1>");
}
应用场景: 浏览器显示的内容, 下载文件等.
response 以流的形式,将内容输出给浏览器
response.getWriter() 获取响应体的字符输出流,输出页面的时候使用
response.getOutputStream() 获取响应体的字节输出流,输出文件(图片,avi等。。。。)的时候使用
通过这两个流可以向浏览器输出 响应体内容.
注意问题:
1 文件数据传输: getOutputStream 手动生成响应内容时 使用 getWriter
2 getOutputStream 和 getWriter 相互排斥,不能同时使用,否则会冲突.
3 tomcat会自动调用response输出流的 close方法和flush方法, 因此不需要我们手动关闭流.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 获取请求参数(知道用户需要下载什么数据)
String parameter = request.getParameter("fileName");
String fileName = new String(parameter.getBytes("iso-8859-1"),"utf-8");
//2 服务器中加载用户需要下载资源
String realPath = getServletContext().getRealPath("/download");
File file = new File(realPath, fileName);
//响应消息头设置:
//Content-Type 设置文件媒体格式 .txt .mp3
response.setContentType(getServletContext().getMimeType(fileName));
String header = request.getHeader("User-Agent");
if(header.contains("Firefox")){
//火狐下载文件名乱码处理:(先判断是否是火狐浏览器)
BASE64Encoder base64Encoder = new BASE64Encoder();
fileName = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";
}else{
//谷歌浏览器(和主流其他浏览器)中文乱码处理:
fileName = URLEncoder.encode(fileName,"utf-8");
}
///Content-Disposition 设置要被下载的文件名
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//3 将数据发送给浏览器
FileInputStream in = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream();
int len=-1;
byte[] b=new byte[1024];
while((len=in.read(b))!=-1){
out.write(b, 0, len);
}
in.close();
}
重定向和转发的区别:
1 转发操作发生在服务器内部,重定向是浏览器执行操作
2 转发地址栏不变,重定向,地址栏变化(记住)
3 转发在一次请求中完成,重定向是两次请求(记住)
4 转发可以在一次请求中共享数据,重定向不行。
问题1 :ServletContext的getContext(),getContextPath(),getRealPath() 以及HttpServletRequst的getContextPath(),getRequestURI() getRequestURL()
getServletPath() 这些方法获得路径有什么区别和联系
答:
ServletContext
getContext() :获取指定路径的项目,它的ServletContext对象,但是,处于安全考虑,如果获取其他的项目ServletContext都会拿到null,所以方法不常用
getContextPath():获取当前项目根路径
getRealPath():获取当前项目中,指定资源的路径
HttpServletRequst:
getContextPath():获取当前项目根路径(同上)
getRequestURI(): 获取请求地址,不包含协议,地址,端口
getRequestURL(): 获取请求地址,包含协议,地址,端口
问题2 :ServletContext 与Servlet的在服务器中存在形式被称为什么? 使用ServletContext会出现并发问题么?如何解决
1 对象 ServletContext tomcat在底层的实现类是org.apache.catalina.core.ApplicationContextFacade,这是一个容器存取数据的
Servlet是处理请求和响应的对象,由我们自己实现
2 ServletContext对象在存取数据的时候使用ConcurrentHashMap,线程安全。
三、servlet: 用于开发动态web资源的技术,如果java程序要向浏览器输出数据,必须完成两个步骤:
1.创建一个java类,实现servlet接口。
2.把java类部署到服务器中。Servlet程序是由web服务器调用的,服务器在收到客户端请求后,首先会检查是否创建了Servlet对象,否(创建Servlet对象,调用
init方法,创建封装请求的HttpServletRequeset对象和响应消息的HttpServletResponse对象,然后调用service方法将请求和响应做为参数传递),是(直接创建封装请求的HttpServletRequeset对象和响应消息的HttpServletResponse对象,然后调用service方法将请求和响应做为参数传递),web应用在停止会重新启动的时候,Servlet会调用destroy方法卸载Servlet。 servlet接口有两个默认实现类,GenericServlet,HttpServlet。HttpServlet能够处理HTTP请求的servlet,比
原有Servlet接口上添加了与HTTP协议的处理方法,所以在编写Servlet时,应继承这个类。HttpServelt在实现Servlet接口时,复写了service方法,会自动判断请
求方式,所以只要复写doGet和doPost方法就好。
四、ServletConfig: 获取Servlet的初始化参数。在Servlet配置文件中,可以用 标签为servlet配置初始化信息,当servlet配置了初始化参数时,web容器在创建servlet实例对象时,会自动将初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。所以
通过ServletConfig对象就可以活的当前servlet的初始化参数信息。
五、ServletContext(域对象):
web容器(服务器)在启动时,会给每个web应用都创建一个ServletContext对象代表当前web应用,
封装了当前web应用的所有信息,而且一个web应用中的所有Servlet共享一个ServletContext对象。
所以Servlet对象之间可以通过ServletContext对象来实现通讯。
Cookie
总结:session容器的获取全部依赖于cookie,服务器自动解析cookie,根据cookie中jsessionid,获取指定的容器对象。
一般情况下,关闭浏览器之后,再次访问,是无法获取到Session中的数据的。
因此在服务器针对当前用户的第一次请求创建的唯一的Session容器对象,而在给这次请求的之后,服务器需要给用户响应数据,在响应的时候,服务器把当前Session容器对象的JSESSIONID以Cookie的形式发送给了浏览器。而这个Cookie并没有设置有效时间,那么这个Cookie就属于临时Cookie,在关闭浏览器之后,再次打开浏览器的时候,上次的Cookie已经消失了,用户虽然拿同一个浏览器访问服务器,可是这时没有JSESSIONID,服务器端的Session容器依然存在,但是没JSESSIONID,服务器内部无法获取到这个session对象把包含了JSESSIONID的Cookie在客户端持久化。
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
System.out.println(session);
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60*60*24);
cookie.setPath("/Day37_Cookie");
response.addCookie(cookie);
}
jsp技术最终还是用java类,执行网页内容,jsp说到底还是一个Servlet
<body>
<!-- html注释 -->
<!--
html注释无法对java代码起作用
java自己的注释,会原封不动翻译到.java文件
-->
<!-- java注释 -->
<% //int i=0;%>
<%-- JSP注释:只能在jsp源文件中才能看到 --%>
<%--
总结:html注释 在html源码中
java注释在java源码中
jsp注释在jsp源码中
问题:什么时候使用哪一种注释?
答:希望在那种源文件中看到注释,就使用相同的技术。
--%>
<%=session %>>
</body>
JSP的内置对象&动作标签介绍
什么是内置对象:在jsp中能直接使用的对象就是jsp的内置对象。(request response session exception)
内置对象在哪里?
Jsp底层实际上还是一个java类,可以在jsp中直接使用的,必然存在在jsp翻译后的java类中
JSP的内置对象9个:
这9个内置对象,已经掌握5个,可以在JSP翻译之后的对应的Java源代码的service方法中找到:
HttpServletRequest request
请求
HttpServletResponse response
响应
HttpSession session session
会话
ServletContext application
表示当前项目对象
ServletConfig config
专门获取当前这个Servlet的配置信息
新接触的:(要学习的部分)
Object page = this
它的表示是当前那个JSP页面对象。
PageContext pageContext
它表示的是当前jsp页面的上下文对象 作用:它的主要功能就是可以获取到JSP页面上的其他八个内置对象
Throwable exception
主要是保存JSP页面上的异常信息的对象
JspWriter out
它相当于我们在Servlet中使用的response.getWriter
问题:为什么数据保存在page容器中,只能在当前jsp页面使用?
Page对象定义在——_JspService()方法中,当方法进栈的时候,对象创建可以存取数据,当方法出栈的时候,page对象也随之消失,所以page中存放的数据只能在当前页面使用。
理解:因为page对象定义在_JSPService方法中,当方法执行完成之后,所有的局部变量都消失,所在page对象中保存的数据,只能在当前的jsp中使用。
Page容器中,应该存什么样的数据?
只在当前页面使用的数据,就应该存在page容器中。
例子:页面使用java代码做循环,比如:i<6,这样的6这个数据,不会再其他页面使用,那么就存入page容器。
总结:web中的四个域对象(容器对象)范围比较从小到大依次为:
Page(当前页面) (当前项目的根路径) < request(一次请求)(商品) < session(一次会话,多次请求)(昵称) < ServletContext(整个项目)在线人数
补充:为什么request比page范围大?
Request.getrequestdispather(“/index.jsp”).forward(request,response);获取转发器之后,可以将存入请求对象的数据转发到index.jsp这个页面上。Request中存贮的数据,可以跨越一个servlet和一个jsp,因为page中存贮数据,只能在当前页面使用。
简单总结:一次请求,不止一个页面,一次会话,不止一次请求。
工作的时候:不用page的方法,使用PageContext对象来操作page。
pageContext使用
作用:
1. 获取其他八个内置对象(9个)
2. 向四个web容器(page request session application )设置数据
3. 向四个web容器(page request session application )获取数据
<%=pageContext.getException() %><br/>
<%=pageContext.getOut() %><br/>
<%=pageContext.getRequest() %><br/>
<%=pageContext.getResponse() %><br/>
<%=pageContext.getServletConfig() %><br/>
<%=pageContext.getServletContext() %><br/>
<%=pageContext.getSession() %><br/>
<%=pageContext.getPage() %><br/>
<%=pageContext.APPLICATION_SCOPE %><br/> 4
<%=pageContext.SESSION_SCOPE %><br/> 3
<%=pageContext.REQUEST_SCOPE %><br/> 2
<%=pageContext.PAGE_SCOPE %> 1
一、JSP的内置对象(也叫隐含对象)是指不需要预先声明就可以在脚本代码和脚本表达式中使用的对象,一共有9个。
按照它们的作用域可以分为四类:
1.作用域为Page(页面执行期):response、pageContext、out、config、page、exception
2.作用域为Request(用户当次请求):request
3.作用域为Session(当次会话):session
二、域对象的作用为:保存数据、获取数据、共享数据
1.page域对象中的数据只能在当前用户请求的JSP页面中使用。只要页面跳转了,page中的数据就不见了。
2.request域对象中的数据有效范围是当前请求周期。在这个周期中可能使用forward方式跳转了多个JSP页面,在这些页面中都可以使用这个变量。
3.seesion域对象中的数据的有效范围是当前会话
4.application域对象中的数据有效范围是整个Web应用。这些数据会一直保存到服务器关闭。
EL表达式
需求:需要一种新的jsp页面使用java代码的方式,方便直接输出内容。
EL全称:Expression Language
作用:代替jsp中脚本表达式的功能,简化对java代码的操作。
EL要学习内容:
获取数据(获取四个容器中数据)
执行运算(EL执行运算)
快速操作常用的javaweb对象(11个内置对象)
EL表达式
在JSP中提供了EL表达式,可以快速的从web容器(page、request、session、ServletContext)中取出数据。
EL表达式的格式:
在域中保存的数据的key值request.setAtttribute(“username”,”zhangsan”)如:
在
域
中
保
存
的
数
据
的
k
e
y
值
r
e
q
u
e
s
t
.
s
e
t
A
t
t
t
r
i
b
u
t
e
(
“
u
s
e
r
n
a
m
e
”
,
”
z
h
a
n
g
s
a
n
”
)
如
:
{requestScope.username}
相当于 request.getAttribute(“username”)
<!-- 演示获取四个容器中的数据 -->
<%
pageContext.setAttribute("name", "林志玲",pageContext.APPLICATION_SCOPE);
pageContext.setAttribute("name", "林志颖",pageContext.SESSION_SCOPE);
pageContext.setAttribute("name", "林正英",pageContext.REQUEST_SCOPE);
pageContext.setAttribute("name", "林心如",pageContext.PAGE_SCOPE);
%>
${pageScope.name}<br/>
${requestScope.name}<br/>
${sessionScope.name}<br/>
${applicationScope.name}<br/>
<hr/>
${name}<br/>
<body>
<%--获取请求参数 --%>
${param}<br>
${paramValues}<br>
${paramValues.hobby[1] }
<hr/>
<%--获取请求头 --%>
${header }<br><br>
${headerValues }<br><br>
<hr/>
<%--
${cookie } cookie数组
${cookie.cookie的名称 } cookie对象
${cookie.JSESSIONID.name } 获取cookie的名称
${cookie.JSESSIONID.value } 获取cookie的值
--%>
${cookie }<br>
${cookie.JSESSIONID.name }<br>
${cookie.JSESSIONID.value }<br>
<hr/>
<%--pageContext获取的是JSP的八个内置对象 不管是EL内置对象的pageContext还是jsp的内置对象pageContext都是获取jsp的其他八个内置对象 --%>
${pageContext.request.contextPath}
<hr/>
${initParam.sh}
</body>
EL的11个内置对象使用
其中大家已经掌握的:
pageScope
requestScope
sessionScope
applicationScope
param
获取用户提交的请求参数
测试代码:
param cookie 它获取到的一个cookie数组,获取所有的cookie数据 测试代码:<
p
a
r
a
m
c
o
o
k
i
e
它
获
取
到
的
一
个
c
o
o
k
i
e
数
组
,
获
取
所
有
的
c
o
o
k
i
e
数
据
测
试
代
码
:
<
{cookie }获取了cookie数组,如果获取数组中的指定cookie,使用点名称的方式获取 –%>
cookie
c
o
o
k
i
e
{cookie.JSESSIONID.name }
${cookie.JSESSIONID.value }
pageContext
它就和JSP内置对象pageContext功能一致(获取其他内置对象:jsp的内置对象)
测试代码:<%– 使用pageContext,获取了 request,调用request对象的方法–%>
${pageContext.request.contextPath}
细节:使用pageContext的getAttribute方法或者findAttribute方法从4个容器中取出数据的时候,如果指定的key不存在会得到null,而使用el表达式取出的时候指定的key不存在,页面上什么都没有
<body>
<%--
test属性值为true 执行标签体中的内容 false:不执行
var属性:保存了test属性执行结果
scope:指定var属性数据保存的容器
--%>
<c:if test="${true }" var="mm" scope="session">
测试if标签 test==false pageScope:${pageScope.mm }| sessionScope:${sessionScope.mm }
</c:if>
<%--
var:${mm }
--%>
</body>
<body>
<%--
set演示保存数据
int i = 0;
var:声明一个变量名称(int i)
value:给var属性声明的变量赋值
set标签保存数据,默认是存在page容器中。
scope:指定数据保存的容器
--%>
<c:set var="root" value="${pageContext.request.contextPath }" scope="session"></c:set>
pageScope:${pageScope.root }<br/>
sessionScope:${sessionScope.root }
<hr/>
<%--
set演示修改数据
target:目标 靶子
--%>
<%
Person p=new Person();
pageContext.setAttribute("p",p);
%>
${p }
<c:set target="${p }" property="name" value="黑马警长"></c:set>
${p }
</body>
JavaBean介绍
JavaBean:它是一个简单的Java类。属性要求是private 这个类中拥有get或set方法即可,但要求这个类必须有一个公开的空参数的构造函数。
特点:
1、一定要有一个无参数的构造函数—public 无参的构造函数
2、属性必须是 private的。
3、为这个私有的属性,提供公有的访问方法getter ,setter。
JavaWeb中的过滤器是什么呢?
Filter接口:功能——对请求和响应进行增强,或者进行拦截。
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("getInitParameter:"+config.getInitParameter("sh"));//获取初始化参数
System.out.println("getFilterName:"+config.getFilterName());//获取过滤器名称
Enumeration<String> names = config.getInitParameterNames();
while(names.hasMoreElements()){
String next = names.nextElement();
System.out.println(next);//获取初始化参数
}
System.out.println("getServletContext:"+config.getServletContext());//获取上下文
}
servlet生命周期:
生:第一次调用servlet程序初始化(执行一次)
死:服务器关闭
Cookie生命周期:
生:new Cookie(“username”,”tom”)
Session:
生:第一次调用getSession方法,默认访问jsp
死:默认30分钟自动死亡,服务器强制关闭,调用session的invalidate()方法
Filter:
创建:在服务器启动的时候
补充(装饰(包装)设计模式口诀):
1. 定义一个类,实现被装饰对象的接口
2. 定义一个成员变量,记住被装饰对象的引用
3. 定义构造方法,传入被装饰对象的实例
4. 改写要修改的方法
5. 不需要改写的方法,调用被装饰对象的原来的方法
public class MyRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
private boolean flag=false;
public MyRequest(HttpServletRequest request) {
super(request);
this.request=request;
}
@Override
public Map<String, String[]> getParameterMap() {
String method = request.getMethod();
if("post".equalsIgnoreCase(method)){
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return super.getParameterMap();
}
}else if("get".equalsIgnoreCase(method)){
//将所有的请求参数获取出来,然后,一个一个地处理乱码
Map<String, String[]> map = request.getParameterMap();
if(flag){
return map;
}
if(map!=null){
for(String key:map.keySet()){
String[] strings = map.get(key);
for(int i=0;i<strings.length;i++){
try {
String string = new String(strings[i].getBytes("iso-8859-1"), "utf-8");
strings[i]=string;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
//如果出异常,希望后边,还没有循环到的数据,继续处理乱码
//结束当前循环,开启下一个循环
continue;
}
}
}
}
flag=true;
return map;
}else{
return super.getParameterMap();
}
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> map = this.getParameterMap();
if(map!=null){
String[] values = map.get(name);
return values;
}
return super.getParameterValues(name);
}
@Override
public String getParameter(String name) {
String[] values = this.getParameterValues(name);
if(values!=null){
return values[0];
}
return super.getParameter(name);
}
}
javaweb监听器介绍
JavaWEB中的监听器主要监听JavaWEB中的request、session、ServletContext对象的各种变化(创建和销毁、保存的数据)。
Javaweb中事件源(request、session、ServletContext)
监听request、ServletContext 、session对象的创建和销毁 (练习)
ServletRequestListener
ServletContextListener
HttpSessionListener
监听request、session、ServletContext 对象存放的数据变化情况(练习)
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
监听session中保存的JavaBean的状态
HttpSessionBindingListener
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("contextInitialized。。。");
// Timer timer=new Timer();
// timer.schedule(new TimerTask() {
// @Override
// public void run() {
// String localeString = new Date().toLocaleString();
// System.out.println(localeString);
// }
// }, 5000, 1000);
//初始化在线人数
ServletContext context = servletContextEvent.getServletContext();
context.setAttribute("onLineNumber", 0);
}
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("sessionCreated。。。");
//创建session的时候在线人数增加1
ServletContext context = httpSessionEvent.getSession().getServletContext();
Integer num = (Integer) context .getAttribute("onLineNumber");
context.setAttribute("onLineNumber", num+1);
}
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("sessionDestroyed。。。");
//创建session的时候在线人数减少1
ServletContext context = httpSessionEvent.getSession().getServletContext();
Integer num = (Integer) context .getAttribute("onLineNumber");
context.setAttribute("onLineNumber", num-1);
}
Session中的bean(JavaBean)监听
需求:当我们给Session中保存一个Java对象(JavaBean)的时候,或者把Java对象从Session中移除的时候会触发专门用来监听Session中对象变化的监听器中的方法。拥有这个方法的对象——HttpSessionBindingListener接口
属性监听和bean监听的区别:
属性监听:是对三个容器中的任何属性(包括对象和不是对象的数据,基本类型数据)的变化,进行监听
Bean监听:它只监听javabean对象往session中保存和session中移出的过程。
注意:当服务器加载项目的时候,会读取web.xml文件中listener标签,那么服务器会自动创建监听器对象,并且自动调用其方法
自动调用其方法,也是通过反射调用(因为他的方法名称和参数是固定的)
监听器的小结:
1. 创建一个类,实现监听器接口
2. 在监听器对象的方法中,书写相关的代码
3. 在web.xml中配置当前监听器。
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String methodName = req.getParameter("methodName");
try {
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this, req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static String getDir(String fileName) {
//根据文件的名称计算文件路径
int hashCode = fileName.hashCode();
/**
* int hashCode 0000 0101 0101 0101 0101 0101 1111 1111
* &0000 0000 0000 0000 0000 0000 0000 1111
* ------------------------------------------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 1111
* 0000 0101 0101 0101 0101 0101 1101 1111
* &0000 0000 0000 0000 0000 0000 0000 1111
* --------------------------------------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 1101
* 每4个位获取一个数字,获取到8个数字,每个数字都作为文件目录
* 每个数字有16个变化——16^8个变化
*
* */
int dir1 = hashCode & 15;
hashCode = hashCode >> 4;
int dir2 = hashCode & 15;
return "/"+dir1+"/"+dir2;
}