JavaWeb中,监听器是一种组件,能够监听项目的启动和停止,用户会话的创建和销毁,以及各种组件的添加、更新和删除,能够通过监听对象的状态改变,自动做出反应执行响应代码。
应用场景:启动网站后进行初始化、检测用户的数量等。
常用的监听器接口:
ServletContextListener 监听项目的启动和停止
方法:
contextInitialized 项目加载完成
contextDestroyed 项目停止
HttpSessionListener 监听用户会话的创建和销毁
sessionCreated 每一个用户第一次访问时调用
sessionDestroyed 每个用户退出系统后调用
监听器的配置:
方式1 web.xml
listener
listener-class包名+类名/listener-class
/listener
方式2 注解
@WebListener
案例:监听网站的启动
/**
* 项目的监听器
* @author chenheng
*
*/
@WebListener
public class WebApplicationListenerimplements ServletContextListener{
//项目启动
@Override
public voidcontextInitialized(ServletContextEvent sce) {
System.out.println(项目启动了!!!!);
//保存一些数据到项目中
sce.getServletContext().setAttribute(money, 999999);
}
//项目停止
@Override
public voidcontextDestroyed(ServletContextEvent sce) {
System.out.println(项目停止了!!!!!);
}
}
案例:监听网站的用户数
/**
* 会话监听器
* @author chenheng
*
*/
@WebListener
public class UserListenerimplements HttpSessionListener{
//用户会话创建
@Override
public voidsessionCreated(HttpSessionEvent se) {
//把用户的数量保存到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
public voidsessionDestroyed(HttpSessionEvent se) {
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)
public classCloseSessionServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequestreq, HttpServletResponse resp) throws ServletException, IOException {
//关闭Session
req.getSession().invalidate();
}
}
JSP页面:
%@ page language=
pageEncoding=
!DOCTYPE html PUBLIC-//W3C//DTD HTML 4.01 Transitional//ENhttp://www.w3.org/TR/html4/loose.dtd
html
head
meta http-equiv=
title测试/title
/head
body
当前网站在线人数:${count}br
a href=
/body
/html
过滤器
能够对网站中的各种内容进行过滤(页面、Servlet、图片、文件),可以在网站内容请求和响应时进行一些操作,完成一些通用的功能。
过滤器链
在项目中可以创建多个过滤器,网站内容可能会经过多个过滤器,多个过滤器就形成了过滤器链。
实现方法:
1、实现Filter接口
init 初始化
doFilter 进行过滤
参数:
ServletRequest 请求
ServletResponse 响应
FilterChain 过滤器链
//让请求通过,执行下一个过滤器,如果不执行这个方法,请求就被拦截
chain.doFilter(request, response);
destroy 销毁
2、配置
web.xml
!-- 配置过滤器 --
filter
filter-nameFilter1/filter-name
filter-classcom.qianfeng.filters.Filter1/filter-class
/filter
filter-mapping
filter-nameFilter1/filter-name
url-pattern/*/url-pattern
/filter-mapping
解释:*代表所有的网站内容都过这个过滤器,可以指定被过滤的内容,如:
url-pattern/test1.jsp/url-pattern
url-pattern/test2.jsp/url-pattern
注解:
@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})
public class TokenFilterimplements Filter{
@Override
public voiddoFilter(ServletRequest request, ServletResponse response, FilterChainchain)
throws IOException, ServletException {
//产生随机字符串
Stringtoken = UUID.randomUUID().toString();
//保存到Session中
HttpServletRequestres = (HttpServletRequest) request;
res.getSession().setAttribute(token, token);
//执行后面的过滤器
chain.doFilter(request, response);
}
@Override
public void init(FilterConfigfilterConfig) throws ServletException{}
@Override
public voiddestroy() {}
}
/**
* 模拟添加数据的Servlet
*/
@WebServlet(/add.do)
public classAddUserServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequestreq, HttpServletResponse resp) throws ServletException, 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 (InterruptedException e) {
e.printStackTrace();
}
req.getRequestDispatcher(test.jsp).forward(req, resp);
}
JSP页面:
%@ page language=
pageEncoding=
!DOCTYPE html PUBLIC-//W3C//DTD HTML 4.01 Transitional//ENhttp://www.w3.org/TR/html4/loose.dtd
html
head
meta http-equiv=
titleInsert title here/title
/head
body
form action=
input type=
input type=
input type=
!-- 将token放到隐藏域中 --
input type=
/form
/body
/html
总结
本章学习的监听器能够监听项目中各种对象的状态,如项目的启动和停止、用户会话的创建和销毁、会话属性的添加删除等,然后自动调用对应的方法,在实际工作中能完成缓存的提前加载,和项目的相关配置工作。而过滤器能过滤网站中的各种资源,给Servlet和JSP添加一些额外的功能,如:设置编码格式、对用户进行登录验证、解决重复提交问题等。