监听器
过滤器
监听器
JavaWeb中,监听器是一种组件,能够监听项目的启动和停止,用户会话的创建和销毁,以及各种组件的添加、更新和删除,能够通过监听对象的状态改变,自动做出反应执行响应代码。
应用场景:启动网站后进行初始化、检测用户的数量等。
常用的监听器接口:
ServletContextListener 监听项目的启动和停止
方法:
contextInitialized 项目加载完成
contextDestroyed 项目停止
HttpSessionListener 监听用户会话的创建和销毁
sessionCreated 每一个用户第一次访问时调用
sessionDestroyed 每个用户退出系统后调用
监听器的配置:
方式1 web.xml
方式2 注解
@WebListener
案例:监听网站的启动
/**
* 项目的监听器
* @authorchenheng
*
*/
@WebListener
publicclassWebApplicationListenerimplementsServletContextListener{
//项目启动
@Override
publicvoid contextInitialized(ServletContextEventsce) {
System.out.println("项目启动了!!!!");
//保存一些数据到项目中
sce.getServletContext().setAttribute("money", 999999);
}
//项目停止
@Override
publicvoid contextDestroyed(ServletContextEventsce) {
System.out.println("项目停止了!!!!!");
}
}
案例:监听网站的用户数
/**
* 会话监听器
* @authorchenheng
*
*/
@WebListener
publicclassUserListenerimplementsHttpSessionListener{
//用户会话创建
@Override
publicvoid sessionCreated(HttpSessionEventse) {
//把用户的数量保存到ServletContext(application)中
ServletContextapplication = se.getSession().getServletContext();
//获得用户的总数
Objectcount = application.getAttribute("count");
if(count == null){
//如果是第一个用户,没有总数,添加总数
application.setAttribute("count", 1);
System.out.println("第一个用户");
}else{
//如果不是第一个,就用户数量加1
application.setAttribute("count", (int)count + 1);
System.out.println("新用户来了");
}
}
//用户会话销毁
@Override
publicvoid sessionDestroyed(HttpSessionEventse) {
ServletContextapplication = se.getSession().getServletContext();
Objectcount = application.getAttribute("count");
if(count !=
null&& (int)count> 0){application.setAttribute("count", (int)count - 1);
System.out.println("用户走了");
}
}
}
/**
* 关闭Session的Servlet
*/
@WebServlet("/close.do")
publicclass CloseSessionServlet extendsHttpServlet{
@Override
protectedvoid doGet(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//关闭Session
req.getSession().invalidate();
}
}
JSP页面:
pageEncoding="UTF-8"%>
-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
当前网站在线人数:${count}
过滤器
能够对网站中的各种内容进行过滤(页面、Servlet、图片、文件),可以在网站内容请求和响应时进行一些操作,完成一些通用的功能。
过滤器链
在项目中可以创建多个过滤器,网站内容可能会经过多个过滤器,多个过滤器就形成了过滤器链。
![JavaWeb之监听器和过滤器](http://p2.ttnews.xyz/loading.gif)
实现方法:
1、实现Filter接口
init 初始化
doFilter 进行过滤
参数:
ServletRequest 请求
ServletResponse 响应
FilterChain 过滤器链
//让请求通过,执行下一个过滤器,如果不执行这个方法,请求就被拦截
chain.doFilter(request, response);
destroy 销毁
2、配置
web.xml
解释:*代表所有的网站内容都过这个过滤器,可以指定被过滤的内容,如:
注解:
@WebFilter({"/*"})
@WebFilter({"/test1.jsp","/test2.jsp"})
过滤器执行的顺序:
如果是注解配置的,按名字顺序进行执行
如果是web.xml配置的,按过滤器filter定义的顺序
案例:表单重复提交问题
把表单数据多次提交给服务器
问题:1、加大服务器的负担 2、多次插入重复的数据
可能出现重复提交的情况:
1、提交表单后,用forward跳转到其它页面,刷新页面
2、提交表单后,服务器还没有响应前,多次刷新页面
3、提交表单后,服务器还没有响应前,多次点击提交按钮
4、提交表单后,跳转后点击返回,点击提交
解决方法:
1、进入表单页面前,在过滤器中创建Token(令牌)随机字符串,保存到Session中。
2、在表单中添加一个隐藏域,值是Token字符串,会和表单一起提交服务器
3、提交服务器后,将表单中Token和Session中Token进行比较,如果相同就正常提交表单,否则就是重复提交。
4、如果能够成功提交后,把Session中的Token去掉。
/**
* 生成令牌的过滤器
*/
@WebFilter({"/resubmit.jsp"})
publicclassTokenFilterimplementsFilter{
@Override
publicvoid doFilter(ServletRequestrequest, ServletResponseresponse, FilterChainchain)
throwsIOException, ServletException {
//产生随机字符串
Stringtoken = UUID.randomUUID().toString();
//保存到Session中
HttpServletRequestres = (HttpServletRequest) request;
res.getSession().setAttribute("token", token);
//执行后面的过滤器
chain.doFilter(request, response);
}
@Override
publicvoid init(FilterConfigfilterConfig) throwsServletException {}
@Override
publicvoid destroy() {}
}
/**
* 模拟添加数据的Servlet
*/
@WebServlet("/add.do")
publicclass AddUserServlet extendsHttpServlet{
@Override
protectedvoid doPost(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//判断表单中的token是否和Session中的token一样
Stringtoken1 = (String) req.getSession().getAttribute("token");
Stringtoken2 = req.getParameter("token");
if(!token1.equals(token2)){
//如果不相同,就是重复提交
System.out.println("这是重复提交");
return;
}
Stringname = req.getParameter("name");
Stringage = req.getParameter("age");
//模拟代码,成功插入数据库
System.out.println(name+","+age+"插入到数据库");
//将Session中的token去掉
req.getSession().setAttribute("token", "");
try {
Thread.sleep(1000);
} catch (InterruptedExceptione) {
e.printStackTrace();
}
req.getRequestDispatcher("test.jsp").forward(req, resp);
}
JSP页面:
pageEncoding="UTF-8"%>
-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
总结
本章学习的监听器能够监听项目中各种对象的状态,如项目的启动和停止、用户会话的创建和销毁、会话属性的添加删除等,然后自动调用对应的方法,在实际工作中能完成缓存的提前加载,和项目的相关配置工作。而过滤器能过滤网站中的各种资源,给Servlet和JSP添加一些额外的功能,如:设置编码格式、对用户进行登录验证、解决重复提交问题等。
閱讀更多 跟老司機學Java 的文章