监听器
监听器的特点:
能够监控网站中一些组件的状态,状态发生改变后,自动执行某些代码。
常用的监听器接口:
ServletContextListener 监控网站的启动和停止
应用场景:监听网站启动后,初始化缓存,或加载配置文件(Spring)
ServletContextAttributeListener 监控向application对象添加和删除数据
HttpSessionAttributeListener 监控会话中数据的添加和删除
HttpSessionListener 监控会话的创建和销毁
应用场景:统计在线人数
使用方法:
1)定义类实现某个监听器接口
2)实现其中的方法
3) 注册(两种方式):
1. 添加注解:@WebListener
2.web.xml配置
<listener>
<listener-class>包名+类名</listener-class>
</listener>
具体实现 (1. 监听网站启动和停止):
/**
* 自定义监听器,监听网站启动和停止
* @author Administrator
*
*/
@WebListener
public class MyWebListener implements ServletContextListener{
//网站停止
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("网站停止了,进行资源释放");
}
//网站启动
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("网站启动了,进行初始化");
//初始化人数为0
event.getServletContext().setAttribute("count", 0);
}
}
具体实现 (2. 统计在线人数):
监听器
/**
* 用户人数监听器
* @author Administrator
*
*/
@WebListener
public class UserCountListener implements HttpSessionListener{
//创建会话
@Override
public void sessionCreated(HttpSessionEvent event) {
//给项目的全局数据加1
ServletContext application = event.getSession().getServletContext();
int count = (int) application.getAttribute("count");
count++;
application.setAttribute("count", count);
System.out.println("用户来了,当前人数是:" + count);
}
//销毁会话
@Override
public void sessionDestroyed(HttpSessionEvent event) {
ServletContext application = event.getSession().getServletContext();
int count = (int) application.getAttribute("count");
if(count > 0){
count--;
application.setAttribute("count", count);
}
System.out.println("用户走了,当前人数是:" + count);
}
}
controller层:
@WebServlet("/exit.do")
public class UserExitServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//让当前用户的Session失效
req.getSession().invalidate();
}
}
jsp:
<body>
欢迎,进入网站,当前在线人数是${count} <br>
<a href="exit.do">安全退出</a>
</body>
过滤器
作用:可以过滤网站中的各种资源(Servlet、JSP、HTML、图片、各种文件)
1)执行某些通用的操作
2)可以对某些不符合要求的请求进行拦截
实现过滤器:
1)实现Filter接口
public class MyFilter1 implements Filter{
}
2)实现doFilter方法,init,destory
三个参数:ServletRequest 请求,ServletResponse 响应,FilterChain 过滤器链
FilterChain 是该请求要经过的所有过滤器
放行:过滤器链.doFilter(请求,响应) 通过当前过滤器,到下一个过滤器
拦截:不执行过滤器链.doFilter
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
System.out.println("MyFilter1当前的请求:" + request.getRequestURL());
//放行
chain.doFilter(req, resp);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
3)注册过滤(两种1.配置xml文件,2.注解)
1.配置xml文件
<filter>
<filter-name>filter1</filter-name>
<filter-class>包名+类名</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<!--
配置过滤资源的url
单个资源:/index.jsp
多个资源:/index.jsp,/aa.jsp,/bb.jsp
使用通配符: *.jsp,*.do,*.jpg
所有资源:/*
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
2.注解
@WebFilter("/*")
@WebFilter({"*.jsp","*.do"})
注:多个过滤器执行的顺序:
注解:按过滤器的名称顺序执行
Web.xml : 按过滤器配置顺序执行
注:这里重点配置过滤资源的url
配置过滤资源的url
单个资源:/index.jsp
多个资源:/index.jsp,/aa.jsp,/bb.jsp
使用通配符: *.jsp,*.do,*.jpg
所有资源:/*
例:配置登录的过滤器
过滤器:
@WebFilter("/*")
public class UserLoginFilter implements Filter {
//不拦截的资源
private static final String[] EXCLUSIVE = {"code.do","login.do","login.jsp",
"css","js","jpg"};
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
System.out.println("经过登录过滤器:"+request.getRequestURL());
//判断URL如果是不拦截的就直接放行
for(String url : EXCLUSIVE){
if(request.getRequestURL().toString().endsWith(url)){
chain.doFilter(req, resp);
return;
}
}
//验证Session中是否有User对象,没有就强制登录,有就放行
User user = (User) request.getSession().getAttribute("user");
if(user == null){
System.out.println("登录过滤器拦截:"+request.getRequestURL());
response.sendRedirect("login.jsp");
}else{
System.out.println("登录过滤器放行:"+request.getRequestURL());
chain.doFilter(req, resp);
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
controller层部分代码:
if(user == null){
//将错误信息发送给登录页面,跳转到登录
req.setAttribute("error", "账号或密码错误");
req.getRequestDispatcher("login.jsp").forward(req, resp);
}else{
//保存User对象到Session中
req.getSession().setAttribute("user", user);
//登录成功跳转主页面
resp.sendRedirect("index.do");
}
补充:(设置编码过滤器)
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//设置编码
HttpServletRequest request = (HttpServletRequest) req;
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
System.out.println("设置编码:" + request.getRequestURL());
chain.doFilter(req, resp);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}