6. 状态管理–cookie
7.状态管理–session
8.Servlet声明周期
9.过滤器,Servlet处理多个请求
10.监听器,Servlet上下文,Servlet线程安全
<6>.状态管理–cookie
(1)什么是状态管理?
将浏览器与web服务器之间多次交互当做一个整体来处理,并且将多次交互所产生的数据(即状态)保存下来。
(2)如何进行状态管理?
a.方式一 将状态保存在浏览器端
通常使用Cookie技术。
b.方式二 将状态保存在服务器端
通常使用Session技术。
(3)Cookie
1)什么是Cookie?
服务器临时存放在浏览器端的少量数据,用于跟踪用户的状态。
当浏览器访问服务器时,服务器会将少量数据以
set-cookie消息头的方式发送给浏览器,浏览器
会将这些数据保存下来。
当浏览器再次访问服务器时,会将这些数据以cookie
消息头的方式发送给服务器。
2)如何添加Cookie?
Cookie c = new Cookie(String name,String value);
注:
name一般称之为cookie名,value称之为cookie值,都必须是字符串。
response.addCookie(c);
3)如何读取Cookie?
Cookie[] request.getCookies();
注:
该方法有可能返回null。
String cookie.getName();
String cookie.getValue();
4)cookie的生存时间
a.默认情况下,浏览器会将cookie保存在内存里面,浏览器只要关闭,cookie会被删除。
b.可以调用setMaxAge方法来设置cookie的生存时间
cookie.setMaxAge(int seconds);
注:
a.单位是秒。
b.当seconds > 0,浏览器会将cookie保存在硬盘上,当超过指定的时间,浏览器会将cookie删除。
c.当seconds < 0,缺省值(浏览器会将cookie保存在内存里面)。
d.当seconds = 0,删除cookie。
比如,要删除一个名称为"username"的cookie,代码如下:
Cookie c = new Cookie("username","");
c.setMaxAge(0);
response.addCookie(c);
5)cookie的编码问题
a.什么是cookie的编码问题?
cookie只能存放合法的ascii字符,如果要存放中文,需要将中文转换成合法的ascii字符的形式。
b.如何处理?
String URLEncoder.encode(String str,String charset);
String URLDecoder.decode(String str,String charset);
建议,在实际开发时,对添加的数据统一使用encode方法来编码。
6)cookie的路径问题
a.什么是cookie的路径问题?
浏览器访问服务器时,会比较请求地址是否与cookie的路径匹配,只有匹配的cookie才会被发送。
b.cookie的默认路径
cookie的默认路径等于添加该cookie的web组件的路径,比如AddCookieServlet(/day06/addCookie) 添加了一个cookie,则该cookie的默认路径是
"/day06"。
c.匹配规则
请求地址要么是等于cookie的路径,要么是cookie的子路径,只有符合该条件的cookie,浏览器才会发送出去。
d.修改路径
cookie.setPath(String path);
注:
path就是路径。
7)cookie的限制
a. cookie可以被用户禁止。
b. cookie不安全。
对于敏感数据,一定要加密。
c. cookie只能保存少量的数据。
大约4k左右
d. cookie的数量也有限制。
大约是几百个
e. cookie只能保存字符串。
练习
写一个Servlet,该Servlet先查看有没有一个名称为"cart"的cookie,如果有,则显示该Cookie的值;如果没有,则添加之。
练习
<7>.状态管理–session
(1)session是什么?
服务器端为了保存状态而创建的一个特殊的对象。
注:
当浏览器访问服务器时,服务器端创建一个特殊的对象(该对象一般称之为session对象,该对象有一个
唯一的id,一般称之为sessionId)。服务器会将sessionId以cookie的方式发送给浏览器。
当浏览器再次访问服务器时,会将sessionId发送过来,服务器端可以依据sessionId找到对应的session
对象。
(2)如何获得session对象?
1)方式一:
HttpSession s =
request.getSession(boolean flag);
注:
a.HttpSession是一个接口。
b.如果flag为true:
先查看请求当中是否有sessionId,如果没有,则创建一个session对象;如果有sessionId,则依据sessionId查找对应的session对象,如果找到了,则返回该对象,找不到,则创建一个新的
session对象。
c.如果flag为false:
先查看请求当中是否有sessionId,如果没有,返回null;如果有sessionId,则依据sessionId查找对应的session对象,如果找到了,则返回该对象,找不到,返回null。
方式二:
HttpSession s = request.getSession();
等价于 request.getSession(true);
(3)常用方法
1)session.setAttribute(String name,Object obj);
注:
以name作为key,以obj作为value,将数据存放到了一个Map对象里面。
2)Object session.getAttribute(String name);
注:
如果绑订值不存在,返回null。
3)session.removeAttribute(String name);
注:
解除绑订。
(4)session超时
a.什么是session超时?
服务器会将空闲时间过长的session对象删除掉。
注:
缺省的超时时间长度一般是30分钟。
b.如何修改超时时间长度?
方式一 修改web.xml配置文件。
<session-config>
<session-timeout>30</session-timeout>
</session-config>
方式二
session.setMaxInactiveInterval(int seconds)
注:
设置两次请求之间的最大间隔时间,如果超过了该时间,则session对象会被删除。
(5)删除session
session.invalidate()
2. 登录
3. session验证
step1.登录成功之后,在session对象上绑订一些数据,
比如:
session.setAttribute("user",user);
step2.当用户访问需要受保护的资源时(即只有登录成功之后才能访问的资源,比如success.jsp),进行session验证,比如:
Object obj = session.getAttribute("user");
if(obj == null){
//没有登录,重定向到登录页面
response.sendRedirect("login.jsp");
return;
}
练习
显示用户上一次访问的时间,如果是第一次访问,则输出“你是第一次访问”。
<8>.Servlet声明周期
1.比较session与cookie
session相对于cookie、优点是更安全、可以保存更多的数据、支持更丰富的数据类型。缺点是需要占用服务器端的内存空间。
2.Servlet的生命周期
(1)什么是servlet的生命周期?
servlet容器如何创建servlet对象、如何对该对象进行初始化处理、如何调用该对象处理请求,以及如何销毁该对象的整个过程。
(2)分成哪几个阶段?
1)实例化
a.什么是实例化?
容器调用servlet构造器,创建servlet对象。
b.什么时候实例化?
情形1: 容器收到请求之后,才会创建。
情形2: 容器启动之后,立即创建。
注: 需要在web.xml文件当中,使用
load-on-startup来配置。
c.容器只会创建一个实例!
2)初始化
a.什么是初始化?
容器在创建好servlet对象之后,会立即调用该对象的init(ServletConfig config)方法。
注:
init方法只会调用一次!
b.GenericServlet已经提供了init方法的实现:
将容器传递过来的ServletConfig对象保存下来,并且提供了一个方法(getServletConfig)来获得该对象。
c.如何实现自已的初始化处理逻辑?
只需要override GenericServlet的init()方法。
d.初始化参数
3)就绪(调用)
a.什么是就绪?
容器收到请求之后,调用servlet对象的service方法来处理。
b.HttpServlet已经提供了service方法的实现:
依据请求类型调用对应的doXXX方法。
注:
比如,get请求会调用doGet方法,post请求会调用doPost方法。
c.开发人员可以override HttpServlet的service方法,也可以override doXXX方法。
4)销毁
a.什么是销毁?
容器在删除servlet对象之前,会调用该对象的destroy方法。
该方法只会执行一次!
b. GenericServlet已经提供了destroy方法的实现:
什么都没有做。
开发人员可以override GenericServlet的destroy方法来实现自已的销毁处理逻辑。
(3)相关的接口与类
a. Servlet接口
init(ServletConfig config)
service(ServletRequest req,ServletResponse res)
destroy()
b. GenericServlet抽象类
实现了Servlet接口(主要是实现init、destroy方法)。
c. HttpServlet抽象类
继承了GenericServlet,实现了service方法。
2.容器处理异常
servlet可以将异常抛出给容器,由容器来处理。
step1.将异常抛出
} catch (Exception e) {
e.printStackTrace();
//将异常抛出给容器,由容器来处理
throw new ServletException(e);
}
step2.配置异常处理页面
<!-- 配置异常处理页面 -->
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/error.jsp</location>
</error-page>
step3.添加异常处理页面
<%@ page pageEncoding="utf-8"
contentType="text/html; charset=utf-8" %>
<html>
<head></head>
<body style="font-size:30px;color:red;">
系统维护中,请稍后
<a href="login.jsp">登录</a>
</body>
</html>
练习:计算一个人的BMI指数
bmi指数 = 体重(公斤) / 身高(米) / 身高(米);
如果 bmi指数 < 19,体重过轻。
如果 bmi指数 > 25,体重过重。
其它 体重正常。
19,25要使用初始化参数来配置。
<init-param>
<param-name>min</param-name>
<param-value>19</param-value>
</init-param>
<9>.过滤器,Servlet处理多个请求
(1)什么是过滤器?
servlet规范当中定义的一种特殊的组件,用于拦截servlet容器的调用过程。
注:
容器收到请求之后,会先调用过滤器,再调用servlet或者其它资源。
(2)如何写一个过滤器?
step1.写一个java类,实现Filter接口。
step2.在doFilter方法里面,实现拦截处理逻辑。
step3.配置过滤器。(web.xml)
(3)过滤器的优先级
当有多个过滤器满足拦截的要求,则容器依据< filter-mapping>配置的先后顺序来执行。
(4)初始化参数
step1.配置初始化参数
<init-param>
<param-name>size</param-name>
<param-value>5</param-value>
</init-param>
step2.调用FilterConfig提供的getInitParameter方法来读取初始化参数
//读取初始化参数
int size = Integer.parseInt(config.getInitParameter("size"));
(5)过滤器的优点(思考)
练习
写一个过滤器,检查评论的字数,如果超过10个字,提示“评论字数过多”。
2.容器如何处理请求资源路径
比如,在浏览器地址栏输入http://ip:port/day09-2/abc.html,浏览器会将"/day09-2/abc.html"作为请求资源路径发送给服务器(容器)。
step1.默认认为访问的是一个servlet,容器会去查找对应的
servlet。
注:
看web.xml文件中<url-pattern>的配置,有没有对应的servlet。
<url-pattern>有三种配置方式:
第一种:精确匹配
比如
<url-pattern>/abc.html</url-pattern>
第二种:通配符匹配
使用 "*"号匹配任意的零个或者多个字符,比如
<url-pattern>/*</url-pattern>
<url-pattern>/demo/*</url-pattern>
第三种:后缀匹配
使用"*."开头,后接一个后缀,比如
<url-pattern>*.do</url-pattern>
会匹配所有以.do结尾的请求。
step2 如果没有找到对应的servlet,容器会查找对应位置的文件。
3.如何让一个servlet处理多种请求?
step1.采用后缀匹配,比如
<servlet-mapping>
<servlet-name>SomeServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
step2.分析请求资源路径,进行相应的处理。
//先获得请求资源路径
String uri = request.getRequestURI();
System.out.println("uri:" + uri);
//为了方便比较,截取请求资源路径的一部分
String path = uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
System.out.println("path:" + path);
if("/login".equals(path)) {
System.out.println("处理登录请求...");
}else if("/list".equals(path)) {
System.out.println("处理用户列表请求...");
}
<10>.监听器,Servlet上下文,Servlet线程安全
(5)过滤器的优点
a.可以在不修改源代码的基础上,为应用添加新的功能。
b.可以将多个组件相同的功能集中写在过滤器里面,方便代码的维护。
1.监听器
(1)什么是监听器?
servlet规范当中定义的一种特殊的组件,用于监听servlet容器产生的事件并进行相应的处理。
注:
主要有两大类事件:
a.生命周期相关的事件:
当容器创建了或者销毁了request,session,servlet上下文时产生的事件。
b.绑订数据相关的事件:
调用了request,session,servlet上下文的setAttribute和removeAttribute方法时产生的事件。
(2)servlet上下文
1)什么是servlet上下文?
容器在启动之后,会为每一个web应用创建唯一的一个符合ServletContext接口要求的对象,该对象会一直存在,除非应用被卸载或者容器关闭。
注:
该对象有两个特点:
a.唯一性:一个web应用对应一个上下文。
b.持久性:上下文会一直存在,除非应用被卸载或者容器关闭。
2)如何获得servlet上下文
GenericServlet,ServletConfig,FilterConfig,HttpSession都提供了一个方法(getServletContext)来
获得该对象。
3)作用1 绑订数据
注:
request,session,servlet上下文都提供了绑订数据相关的方法,区别如下:
a.绑订的数据,生存的时间不一样:
request < session < servlet上下文。
在满足使用条件的情况下,优先使用生命周期短的。
b.绑订的数据,可访问的范围不一样:
绑订到session对象上的数据,只有与之对应的用户能够访问到;绑订到servlet上下文上的数据,所有用户都可以访问。
4)作用2:读取全局的初始化参数
step1.配置全局的初始化参数
<!-- 配置全局的初始化参数 -->
<context-param>
<param-name>company</param-name>
<param-value>IBM</param-value>
</context-param>
step2.调用servlet上下文的方法来读取
String company =
sctx.getInitParameter("company");
(3)如何写一个监听器?
step1.写一个java类,依据监听的事件类型选择实现相应的监听器接口。
注:
比如,要监听session对象的创建和销毁,需要实现HttpSessionListener接口。
step2.在接口方法当中,实现监听处理逻辑。
step3.配置监听器。(web.xml)
统计在线人数
练习
2.servlet的线程安全问题
(1)为什么说servlet会有线程安全问题?
a.容器只会创建一个servlet实例。
b.容器收到一个请求,就会启动一个线程,由该线程来处理对应的请求。
如果有多个线程同时去调用某个servlet实例的方法,就有可能产生线程安全问题,比如,这些线程要修改servlet的某个属性值。
(2)如何解决?
使用synchronized对有可能产生线程安全问题的代码加锁。
注:
加锁会影响性能。
3.servlet小结
(1)servlet基础
1)什么是servlet?
2)如何写一个servlet?
3)servlet是如何运行的?
4)http协议(了解)
(2)servlet核心
1)如何读取请求参数值?
2)表单包含有中文参数值,如何处理?
3)servlet输出中文,如何处理?
4)容器如何处理请求资源路径?
5)如何让一个servlet处理多种请求?
6)转发与重定向
a.什么是重定向?
b.如何重定向?
c.重定向的特点?
d.什么是转发?
e.如何转发?
f.转发的特点?
g.比较转发与重定向
7)线程安全问题
8)servlet的生命周期
a.什么是servlet的生命周期?
b.生命周期分成哪几个阶段?
c.容器会创建几个servlet实例?
d.load-on-startup
e.如何实现自已的初始化处理逻辑?
f.初始化方法会执行几次?
g.doGet/doPost方法的作用?
h.相关的接口与类(Servlet,GenericServlet,
HttpServlet)。
i.ServletConfig。
j.初始化参数的配置。
9)路径问题
10)servlet上下文
a.什么是servlet上下文?
b.有什么特点?
c.如何获得servlet上下文?
d.作用
11)将异常抛给容器来处理
(3)状态管理
1)什么是状态管理?
2)如何进行状态管理?
3)Cookie
a.什么是cookie?
b.如何添加cookie?
c.添加cookie时需要考虑的三个问题:
生存时间
编码问题
路径问题
d.如何读取cookie?
e.cookie有哪些限制?
4)Session
a.什么是session?
b.如何获得session对象?
c.session常用的方法
d.session超时
e.如何删除session?
f.比较session与cookie?
(4)数据库访问
1)什么是dao?
2)如何写一个dao?
(5)过滤器与监听器
(6)典型案例
用户管理
登录(session验证)