Filter类来自于Servlet规范下的接口,在servlet-api.jar包中,它包含三个接口,如下:
package javax.servlet;
import java.io.IOException;
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
}
接口说明:
| 返回值类型 | 方法 | 功能描述 |
|---|---|---|
| void | init (FilterConfig filterConfig) | 该方法用于初始化过滤器。 |
| void | doFilter(ServletRequest request,SeivletResponse response, FilterChain chain) | 该方法完成实际的过滤操作,当客户端请求的 URL 与过滤器映射的 URL 匹配时,容器会先调用该方法对请求进行拦截。 参数 request 和 response 表示请求和响应对象。 参数 chain 代表当前 Filter 链对象,在该方法内部,调用 chain.doFilter() 方法,才能把请求交付给 Filter 链中的下一个 Filter 或者 Web 资源。 |
| void | destroy() | 该方法在销毁 Filter 对象之前被调用,用于释放被 Filter 对象占用的资源。 |

(1)客户端浏览器发送请求访问容器指定的 Web 资源
(2)Servlet 容器接收请求,并针对本次的请求分别创建一个 request 对象和 response 对象
(3)请求到达 Web 资源之前,先读取 web.xml 或 @WebFilter 的配置信息对所有的过滤器进行加载和实例化。先调用 Filter 的 doFilter() 方法,检查 request 对象,对请求进行预处理操作。
(4)在 Filter 的 doFilter() 方法内,调用 FilterChain.doFilter() 方法,将请求传递给下一个过滤器或目标资源。如果不放行,将无法访问Servlet资源以及响应数据给客户端浏览器,界面将显示空白页面。
(5)目标资源生成响应信息返回客户端之前,处理控制权会再次回到 Filter 的 doFilter() 方法,执行 FilterChain.doFilter() 后的语句,检查 response 对象,可进行修改响应头和响应正文。
(6)响应信息返回客户端浏览器
public class filterTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//放行前逻辑
System.out.println("放行前逻辑");
//放行 使用FilterChain接口实现类对象调用doFilter()方法
filterChain.doFilter(servletRequest, servletResponse);
//放行后逻辑
System.out.println("放行后逻辑");
}
@Override
public void destroy() {
}
}
web.xml配置如下:
<filter>
<!--过滤器的名字-->
<filter-name>name</filter-name>
<filter-class>filePath</filter-class>
<init-param>
<!--以下就为参数的名字和相应的值-->
<param-name>paramName1</param-name>
<param-value>value1</param-value>
</init-param>
</filter>
<!--下面就为相关的范围-->
<filter-mapping>
<!--过滤器的名字-->
<filter-name>name</filter-name>
<!--过滤器的范围-->
<url-pattern>/*
REQUEST
参数说明:
| 属性名 | 类型 | 描述 |
|---|---|---|
| filterName | String | 指定过滤器的 name 属性,等价于 |
| urlPatterns | String[] | 指定过滤器的 URL 匹配模式。等价于 |
| value | String[] | 该属性等价于 urlPatterns 属性,但是两者不能同时使用。 |
| servletNames | String[] | 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中 filterName 属性的取值,或者 web.xml 中 |
dispatcherTypes | DispatcherType | 指定过滤器拦截的资源被 Servlet 容器调用的方式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
| initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于 标签。 |
asyncSupported | boolean | 声明过滤器是否支持异步操作模式,等价于 标签。--->非常关键 |
description | String | 指定过滤器的描述信息,等价于 标签。 |
| displayName | String | 指定过滤器的显示名,等价于 标签。 |
在Filter的自定义类增加@WebFilter注解,如下
@WebFilter(filterName = "testFilter",urlPatterns = "/TestServlet",initParams = @WebInitParam(name = "name",value = "ABC123456"),dispatcherTypes = DispatcherType.REQUEST)
public class TestFilter implements Filter {
...
}
实现一个过滤器,通过打印日志查看它的生命周期
Filter过滤器有五种拦截方式:
用注解配置dispatcherTypes属性,如果是web.xml配置,就是配置其< dispatcher> dispatcher>标签
forward方法调用后在响应中的没有提交的内容被自动消除。将请求转发给其他的Servlet后,由被调用的Servlet负责对请求做出响应,而原先Servlet的执行则终止。
定义2个过滤,test2Filter、test3Filter、index.jsp和Test2Servlet
test2Filter如下:
@WebFilter(filterName = "test2Filter",urlPatterns = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
public class Test2Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String name = filterConfig.getInitParameter("name");
System.out.println("TestFilter2:init"+" name值:"+name);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("TestFilter2:doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("TestFilter2:destroy");
}
}
test3Filter如下:
@WebFilter(filterName = "test3Filter",urlPatterns = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
public class Test3Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String name = filterConfig.getInitParameter("name");
System.out.println("TestFilter3:init"+" name值:"+name);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("TestFilter3:doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("TestFilter3:destroy");
}
}
Test2Servlet
@WebServlet("/Test2Servlet")
public class Test2Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Test2Servlet");
req.getRequestDispatcher("/index.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>index</title>
</head>
<body>
hello world
<%
System.out.println("index.jsp页面");
%>
</body>
</html>
测试以下路径,来区分FORWARD和REQUEST差异:
1、访问/index.jsp路径,后台显示
TestFilter3:doFilter
index.jsp页面
2、访问/Test2Servlet路径,后台显示
Test2Servlet
TestFilter2:doFilter
index.jsp页面
如果是定义FORWARD与FORWARD一起,则两种方式都生效
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.FORWARD}
在web.xml定义错误页面配置
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
404.jsp页面如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>404</title>
</head>
<body>
抱歉,404页面找不到
</body>
</html>
过滤器ErrorFilter
@WebFilter(filterName = "errorFilter",urlPatterns = "/*",dispatcherTypes = DispatcherType.ERROR)
public class ErrorFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("ErrorFilter:init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("ErrorFilter:doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("ErrorFilter:destroy");
}
}
测试,访问一个不存在的路径,/231123,页面如下
抱歉,404页面找不到
控制台显示如下:
ErrorFilter:doFilter
include方法使原先的Servlet和转发到的Servlet都可以输出响应信息,即原先的Servlet还可以继续输出响应信息。
新增InCludeServlet、InCludeFilter、include.jsp,
InCludeServlet如下:
@WebServlet("/InCludeServlet")
public class InCludeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.getRequestDispatcher("/index.jsp").include(req,resp);
req.getRequestDispatcher("/include.jsp").include(req,resp);
resp.getWriter().write("你好,inCludeFilter");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
inCludeFilter.java如下:
@WebFilter(filterName = "inCludeFilter",urlPatterns = "/include.jsp",dispatcherTypes = DispatcherType.INCLUDE)
public class InCludeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("InCludeFilter:init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("InCludeFilter:doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("InCludeFilter:destroy");
}
}
include.jsp如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>include页面</title>
</head>
<body>
<h2> hi,include页面</h2>
</body>
</html>
测试,访问 /include.jsp路径,页面显示结果如下:
hello world
hi,include页面
你好,inCludeFilter
控制台结果如下:
index.jsp页面
InCludeFilter:doFilter
说明通过include的调用形式,调用指定路径的DispatcherType.INCLUDE过滤器
如果有多个过滤器,过滤器Filter1和过滤器Filter2,则顺序如下
1、过滤器Filter1
2、过滤器Filter2
3、执行路径资源
4、返回Filter2执行
5、返回Filter1执行
示例代码:
Filter1如下:
@WebFilter(filterName = "Filter1",urlPatterns = "/*")
public class Filter1 implements Filter {
private String filterName;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterName = filterConfig.getFilterName();
System.out.println(filterName +":init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(filterName +":doFilter------------------------------------------");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println(filterName +":执行完成------------------------------------------");
}
@Override
public void destroy() {
System.out.println(filterName +":destroy");
}
}
Filter2如下:
@WebFilter(filterName = "Filter2",urlPatterns = "/*")
public class Filter2 implements Filter {
private String filterName;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterName = filterConfig.getFilterName();
System.out.println(filterName +":init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(filterName +":doFilter------------------------------------------");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println(filterName +":执行完成------------------------------------------");
}
@Override
public void destroy() {
System.out.println(filterName +":destroy");
}
}
测试,访问 /index.jsp,控制台输出如下 :
Filter1:doFilter------------------------------------------
Filter2:doFilter------------------------------------------
index.jsp页面
Filter2:执行完成------------------------------------------
Filter1:执行完成------------------------------------------
优先级按照过滤器的实现类类名(字符串)的自然排序,值小的先排序。
示例:
AFilter和BFilter,则AFilter先执行。
Filter1和Filter2,则Filter1先执行
按在web.xml中配置的顺序,从上到下执行。
优先执行web.xml中配置的Filter。
/**
* 对请求的接口进行日志简单记录
*/
@WebFilter(filterName = "logFilter",urlPatterns = "/*")
public class LogFilter implements Filter {
private String filterName;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterName = filterConfig.getFilterName();
System.out.println(filterName+" init");
}
@Override
public void destroy() {
System.out.println(filterName+" destroy");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response= (HttpServletResponse) servletResponse;
//接口名称
String requestURI = request.getRequestURI();
long startTime=System.currentTimeMillis();//请求开始时间
filterChain.doFilter(servletRequest,servletResponse); //放行
long endTime = System.currentTimeMillis();//请求结束时间
System.out.println("请求地址:"+requestURI+" 耗时:"+(endTime-startTime)+"ms");
}
}
ServletContext > HttpSession > HttpServletRequest
监听器有三种,分为监听生命周期、监听对象属性值变化与监听Session 内的对象
public class MyHttpSessionLister implements HttpSessionListener {
private static final String TAG = "MyHttpSessionLister";
/**
* 当session对象被创建时执行
* @param se
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println(TAG+" :sessionCreated");
}
/**
* 将session对象销毁时执行
* @param se
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println(TAG+" :sessionDestroyed");
}
}
(1)在web.xml中配置listner标签
<listener>
<listener-class>com.example.servletdemo.listner.MyHttpSessionLister</listener-class>
</listener>
(2)在类使用注解@WebListener
@WebListener
public class MyHttpSessionLister implements HttpSessionListener {
......
}
HttpSessionListener用来监听HttpSession对象的创建和销毁,实时监听WEB 程序中的活动会话的数量,常用在网站在线人数的精准统计。
HttpSession session = request.getSession();
session.setMaxInactiveInterval(30);//单位为秒
<web-app>
<session-config>
<!-- 单位分钟-->
<session-timeout>1</session-timeout>
</session-config>
......
</web-app>
<!-- ==================== Default Session Configuration ================= -->
<!-- You can set the default session timeout (in minutes) for all newly -->
<!-- created sessions by modifying the value below.
<session-config>
<!-- 默认为30分钟-->
<session-timeout>30</session-timeout>
</session-config>
1.优先级:Servlet中API设置 > 程序/web.xml设置 > Tomcat/conf/web.xml设置
2.若访问服务器session超时(本次访问与上次访问时间间隔大于session最大的不活动的间隔时间)了,即上次会话结束,但服务器与客户端会产生一个新的会话,之前的session里的属性值全部丢失,产生新的sesssionId
3.客户端与服务器一次有效会话(session没有超时),每次访问sessionId相同,若代码中设置了session.setMaxInactiveInterval()值,那么这个session的最大不活动间隔时间将被修改,并被应用为新值。
4.Session的销毁(代表会话周期的结束):在某个请求周期内调用了Session.invalidate()方法,此请求周期结束后,session被销毁;或者是session超时后自动销毁;或者客户端关掉浏览器
5.对于JSP,如果指定了<%@ page session="false"%>,则在JSP中无法直接访问内置的session变量,同时也不会主动创建session,因为此时JSP未自动执行request.getSession()操作获取session。
@WebListener
public class MyHttpSessionLister implements HttpSessionListener {
private static final String TAG = "MyHttpSessionLister";
/**
* 一个浏览器第一次访问网站的时候,J2EE应用服务器会新建一个HttpSession对象 ,并触发 HttpSession创建事件 ,
* 如果注册了HttpSessionListener事件监听器,则会调用HttpSessionListener事件监听器的 sessionCreated方法。
* @param se
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println(TAG+" :session对象被创建");
}
/**
* 当这个浏览器访问结束超时的时候,J2EE应用服务器会销毁相应的HttpSession对象,触发 HttpSession销毁事件,
* 同时调用所注册HttpSessionListener事件监听器的sessionDestroyed方法
*
* 以下两种情况下就会发生sessionDestoryed(会话销毁)事件:
* 1.执行session.invalidate()方法时 会调用sessionListener的sessionDestroyed方法
* 2.如果用户长时间没有访问服务器,超过了会话最大超时时间 ,服务器就会自动销毁超时的session。会调用sessionListener的sessionDestroyed方法
* @param se
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println(TAG+" :session对象被销毁");
}
}
问题
访问HTML是否创建Session :不会
访问JSP是否创建Session :会
访问Servlet是否创建Session :不会
说明:session是jsp的内建对象,所当我们在jsp里面用session的时候不需要创建,但是session不是servlet的内建对象,你在servlet用session的时候需要创建一个session
ServletRequestListener是用户响应监听器,用于对Request请求进行监听(创建、销毁)
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
private static final String TAG = "MyHttpSessionLister=>";
@Override
public void requestDestroyed(ServletRequestEvent arg0) {
System.out.println(TAG+"requestDestroyed=>"+"当前访问次数:" + arg0.getServletContext().getAttribute("count"));
}
@Override
public void requestInitialized(ServletRequestEvent arg0) {
Object count = arg0.getServletContext().getAttribute("count");
Integer his_count = 0;
if (count != null) {
his_count = Integer.valueOf(count.toString());
System.out.println(TAG+"requestInitialized=>" +"历史访问次数::" + count+" 当前访问次数:" + arg0.getServletContext().getAttribute("count"));
}
his_count++;
arg0.getServletContext().setAttribute("count",his_count );
}
}
在Servlet API中有一个ServletContextListener接口,它能够监听ServletContext对象的生命周期,实际上就是监听Web应用的生命周期。
当Servlet容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由 ServletContextListener 来处理。在 ServletContextListener 接口中定义了处理ServletContextEvent事件的contextInitialized和contextDestroyed两个方法。
contextInitialized(ServletContextEvent sce)
当Servlet容器启动Web应用时调用该方法。在调用完该方法之后,容器再对Filter初始化,并且对那些在Web应用启动时就需要被初始化的Servlet进行初始化
contextDestroyed(ServletContextEvent sce)
当Servlet容器终止Web应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet和Filter过滤器。
@WebListener
public class MyServletContextListener implements ServletContextListener {
private static final String TAG = "MyServletContextListene";
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println(TAG+" :ServletContext对象已创建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println(TAG+" :ServletContext对象已销毁");
}
}
通过使用ServletContextListener与HttpSessionListener监听器实现网站在线人数的统计
HttpSessionAttributeLister它响应的是HttpSession范围属性的添加、删除和替换,包括以下3个接口:
@WebListener
public class MyHttpSessionAttributeLister implements HttpSessionAttributeListener {
private static final String TAG = "MyHttpSessionAttributeLister";
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println(TAG+"=>attributeAdded");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println(TAG+"=>attributeRemoved");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println(TAG+"=>attributeReplaced");
}
}
ServletContextListener监听器成功监听到了ServletContext域对象(application)中的属性值的变化情况
当调用如下操作时,就会自动执行监听
ServletContext servletContext = req.getServletContext();
servletContext.setAttribute("username","abcd"); //添加或者替换
servletContext .removeAttribute("username"); //移除
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
private static final String TAG = "MyServletContextAttributeListener";
//当程序把一个属性存入ServletContext时触发该方法
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println(TAG+"=>attributeAdded");
}
//当程序把一个属性替换ServletContext内的属性时触发该方法
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
System.out.println(TAG+"=>attributeRemoved");
}
//当程序把一个属性从ServletContext删除时触发该方法
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
System.out.println(TAG+"=>attributeReplaced");
}
}
Web服务器收到一个http请求,会针对每个请求创建一个HttpServletRequest和HttpServletResponse对象
ServletRequestAttributeListeners是对HttpServletRequest范围属性的添加、删除或替换监听
//添加或者替换httpServletRequest属性值
httpServletRequest.setAttribute("username","abcd");
//移除httpServletRequest属性值
httpServletRequest.removeAttribute("username");
@WebListener
public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
private static final String TAG = "MyServletRequestAttributeListener";
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println(TAG+"=>attributeAdded");
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
System.out.println(TAG+"=>attributeAdded");
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
System.out.println(TAG+"=>attributeAdded");
}
}
Java 中对于Http协议的管理接口,如果一个类(对象)实现了该接口,那么当这个对象在被绑定,或者从Session中删除时,Servlet会通知这个对象,当接受到通知之后,则可以进行一些初始化或者清除。 如果一个对象实现了HttpSessionBindingListener接口,当这个对象被绑定到Session中或者从session中被删除时,Servlet容器会通知这个对象,而这个对象在接收到通知后,可以做一些初始化或清除状态的操作,HttpSessionBindingListener接口提供了以下接口方法:
public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
private static final String TAG = "MyHttpSessionBindingListener";
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println(TAG+"=>valueBound");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println(TAG+"=>valueUnbound");
}
}
将执行sess
HttpSession session = req.getSession();
MyHttpSessionBindingListener myHttpSessionBindingListener = new MyHttpSessionBindingListener();
//触发valueBound方法
session.setAttribute("abc",myHttpSessionBindingListener);
//触发valueUnbound方法
session.removeAttribute("abc");
当一个会话开始时,Servlet容器会为会话创建一个HttpSession对象。Servlet容器在某些情况下会把这些HttpSession对象从内存中转移到永久性存储设备中(钝化),并在需要访问HttpSession信息时再把它们加载到内存中(活化)。该过程被称为会话的持久化
持久化的好处:
以下情况会被持久化:
以下情况会被活化:
HttpSessionActivationListener是监听特殊javaBean在session作用域钝化或活化,它实现了以下两个方法:
public class UserSession implements HttpSessionActivationListener, Serializable {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private static final String TAG = "UserSession";
/**
* 将Session内存中的对象持久化(序列化)到磁盘
* @param se
*/
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
UserSession user= (UserSession) se.getSession().getAttribute("user");
SimpleDateFormat df= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println(TAG+"=>sessionWillPassivate =>将Session内存中的对象持久化(序列化)到磁盘="+user.getUsername()+":"+user.getPassword()+"=>"+df.format(new Date()));
}
/**
* 将磁盘上的对象再次恢复到session内存中
* @param se
*/
@Override
public void sessionDidActivate(HttpSessionEvent se) {
UserSession user= (UserSession) se.getSession().getAttribute("user");
SimpleDateFormat df= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println(TAG+"=>sessionDidActivate=>将磁盘上的对象再次恢复到session内存中="+user.getUsername()+":"+user.getPassword()+"=>"+df.format(new Date()));
}
}
@WebServlet("/UserSessionActivationServlet")
public class UserSessionActivationServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//HttpSession属性的设置
HttpSession session = req.getSession();
UserSession user = new UserSession();
user.setUsername("a");
user.setPassword("123456");
session.setAttribute("user",user);
resp.setContentType("text/html;charset=utf-8");
SimpleDateFormat df= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
resp.getWriter().write("添加Usersession=>"+df.format(new Date()));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
@WebServlet("/UserSessionActivationGetServlet")
public class UserSessionActivationGetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//HttpSession属性的设置
HttpSession session = req.getSession();
resp.setContentType("text/html;charset=utf-8");
UserSession user = (UserSession) session.getAttribute("user");
resp.getWriter().write("User session =>"+user.getUsername()+":"+user.getPassword());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- maxIdleSwqp:session中的对象多久不使用就钝化,单位:分钟 -->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwqp="1" >
<!-- directory:钝化文件的位置 -->
<Store className="org.apache.catalina.session.FileStore" directory="F:\test\servletdemo" />
</Manager>
</Context>