Filter译为过滤器。 由于 Servlet 规范是开放的,借助于公众与开源社区的力量, Servlet 规范越来越科学,功能也越来越强大。
运行原理:
当客户端向服务器端发送一个请求时,如果有对应的过滤器进行拦截,过滤器可以改变请求的内容、或者重新设置请求协议的相关信息等,然后再将请求发送给服务器端的Servlet进行处理。当Servlet对客户端做出响应时,过滤器同样可以进行拦截,将响应内容进行修改或者重新设置后,再响应给客户端浏览器。在上述过程中,客户端与服务器端并不需要知道过滤器的存在 在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet。具体执行流程如下:
快速入门
1.编写一个类实现Filter过滤接口
2.重写接口中的方法
- package com.bhf.filter;
-
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import java.io.IOException;
-
-
- /**
- * 过滤器的生命周期
- * 创建对象 LoginFilter() 服务器启动时 调用一次
- * 初始化 init 对象创建完成后 调用一次
- * 执行过滤的方法 doFilter 一次请求执行一次
- * 销毁方法 destroy 服务器关闭时 被调用 调用一次
- */
-
- // "/*"表示拦截所有请求,进入doFilter,
- // 执行filterChain.doFilter(servletRequest,servletResponse);放行请求
- @WebFilter("/*")
- public class TestFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-
- //放行
- filterChain.doFilter(servletRequest,servletResponse);
- }
-
- @Override
- public void destroy() {
-
- }
- }
应用的实例
1.解决请求参数的乱码问题
2.非法访问的拦截(当用户未登录时,拦截请求到登录页面)
拦截所有资源: /*
需要被放行的资源: 不需要登录即可访问的资源
1、放行指定页面:不需要登录可以访问的页面(例如:登录页面、注册页面等)
2、放行静态资源: (例如: css. js. image等资源)
3、放行指定操作:不需要登录即可执行的操作(例如:登录操作、注册操作等)
4、登录状态放行(如果存在指定session对象。则为登录状态)
- package com.bhf.filter;
-
- import com.bhf.pojo.User;
-
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @WebFilter("/*")
- public class LoginFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-
-
- HttpServletRequest req = (HttpServletRequest) servletRequest;
- HttpServletResponse resp = (HttpServletResponse) servletResponse;
-
- //处理中文乱码
- req.setCharacterEncoding("utf-8");
- //放行特定页面
- String servletPath = req.getServletPath();
- System.out.println("servletPath"+servletPath);
-
- if("/login.jsp".equals(servletPath)||"/register.jsp".equals(servletPath)){
- filterChain.doFilter(req,resp);
- return;
- }
- //放行特定的请求 /user method=getCode
- String method = req.getParameter("method");
- if("getCode".equals(method)||"login".equals(method)||"register".equals(method)||"checkUserName".equals(method)){
- filterChain.doFilter(req,resp);
- return;
- }
-
- //放行特定静态资源 .css .js .img
- if(servletPath.startsWith("/static")) {
- filterChain.doFilter(req,resp);
- return;
- }
-
-
- //1.判断session中是否有user对象
- User user = (User) req.getSession().getAttribute("user");
-
- //2.判断user是否为null
- if(user==null){
- //没有登录跳转
- req.setAttribute("login_msg","您未登录");
- req.getRequestDispatcher("/login.jsp").forward(req,resp);
- }
-
- filterChain.doFilter(req,resp);
-
-
-
- }
-
- @Override
- public void destroy() {
-
- }
- }
web监听器由servlet规范提供的,它可以监听客户端的请求,服务端的操作,监听的对象包括:
HttpSession
ServletRequest
三个域对象(内置对象),分别对应aplication,session,request
Web监听器概念 Servlet规范中定义的一种特殊类,用于监听ServletContext,HttpSession和ServletRequest等域对象的创建与销毁事件,用于监听域对象的属性发生增、删、改的事件,可以在事件发生前,发生后做一些必要的处理
监听三个对象的创建和销毁
1.application域对象的监听器
- package com.aiit.listener;
-
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
- import javax.servlet.annotation.WebListener;
-
- /**
- * application域对象的监听器
- * 1.监听域对象的创建和销毁
- * ServletContextListener
- */
- @WebListener
- public class ApplicationListener implements ServletContextListener {
- // 一旦有application对象被创建 则该方法会被自动调用
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- System.out.println("application对象被创建");
- }
- // 一旦有application对象被销毁 则该方法会被自动调用
- @Override
- public void contextDestroyed(ServletContextEvent sce) {
- System.out.println("application对象被销毁");
- }
- }
2.session对象的监听器
- package com.aiit.listener;
-
- import javax.servlet.annotation.WebListener;
- import javax.servlet.http.HttpSessionEvent;
- import javax.servlet.http.HttpSessionListener;
-
- /**
- * session对象的创建和销毁的监听
- *
- * session 对象 什么时候被创建
- * 浏览器向服服务器成功发送一次请求 则会话对象被创建 同一次会话只会创建一个会话对象 Cookie
- * session 对象 什么时候被销毁
- * 1. 手动销毁
- * 2. 默认销毁 浏览器在30分钟之内没有向服务器发送请求 则会话对象自动销毁
- */
- @WebListener
- public class SessionListener implements HttpSessionListener {
-
- //会话对象被创建
- @Override
- public void sessionCreated(HttpSessionEvent se) {
- System.out.println("sessionCreated");
- }
- //会话对象被销毁
- @Override
- public void sessionDestroyed(HttpSessionEvent se) {
- System.out.println("sessionDestroyed");
- }
- }
3.request对象的监听器
- package com.aiit.listener;
-
- import javax.servlet.ServletRequestEvent;
- import javax.servlet.ServletRequestListener;
- import javax.servlet.annotation.WebListener;
-
- @WebListener
- public class RequestListener implements ServletRequestListener {
-
- //会话对象被创建
- @Override
- public void requestDestroyed(ServletRequestEvent sre) {
- System.out.println("requestDestroyed");
- }
-
- //会话对象被销毁
- @Override
- public void requestInitialized(ServletRequestEvent sre) {
- System.out.println("requestInitialized");
-
- }
- }
监听三个对象中值的变化
1.监听域对象中值的改变,实现ServletContextAttributeListener接口
- package com.aiit.listener;
-
- import javax.servlet.ServletContextAttributeEvent;
- import javax.servlet.ServletContextAttributeListener;
- import javax.servlet.annotation.WebListener;
-
- /**
- * application域对象的监听器
- *2.监听域对象中值的改变
- * ServletContextAttributeListener
- *
- */
- @WebListener
- public class ApplicationAttributeListener implements ServletContextAttributeListener {
- //application中有值被添加
- @Override
- public void attributeAdded(ServletContextAttributeEvent event) {
- String name = event.getName();
- System.out.println("name = " + name);
- Object value = event.getValue();
- System.out.println("value = " + value);
- System.out.println("application attributeAdded");
- }
- //application中有值被删除
- @Override
- public void attributeRemoved(ServletContextAttributeEvent event) {
- System.out.println("application attributeRemoved");
- }
- //application中有值被替换
- @Override
- public void attributeReplaced(ServletContextAttributeEvent event) {
- System.out.println("application attributeReplaced");
- }
- }
2.监听域对象中值的改变,实现HttpSessionAttributeListener接口
与1相同省略
3.监听域对象中值的改变,实现ServletRequestAttributeListener接口
与1相同省略
使用监听器防止一个账号多段登录
单点登录思路分析 1.用户登录成功后会向session域中添加一个key --> user 2.向session对象中添加值时会被HttpSessionAttributeListener attributeAdded 获取到 3.判断改登录的用户是否已经登录过一次了 -->Maptom session ;jack session 4.用户已经登录则根据用户名在map集合中取出对应的session并销毁 第一次登录的用户就会被剔除 再次请求后台接口是就会被拦截到登录页面 5.将第二次登录的用户相关信息存入map集合 user session
- @WebListener
- public class LoginListener implements HttpSessionAttributeListener {
-
- private Map
sessions = new HashMap(); -
- public void attributeReplaced(HttpSessionBindingEvent arg0) {
-
- }
-
- public void attributeAdded(HttpSessionBindingEvent event) {
- System.out.println("session值被添加");
- //获取添加session的名字
- String name = event.getName();
- System.out.println(name);
- if("username".equals(name)) {//该用户的session 已存在 在map中移出
- String username =(String)event.getValue();
- if(sessions.containsKey(username)) {
- HttpSession httpSession = sessions.get(username);
- //设置session失效
- httpSession.invalidate();
- System.out.println("session被移出");
- }
-
- //将刚生成的session放入 集合
- sessions.put(username, event.getSession());
- }
-
- }
- public void attributeRemoved(HttpSessionBindingEvent event) { }
- public void attributeReplaced(HttpSessionBindingEvent event) { }
-
- }
Web监听器的常用用途
统计在线人数
系统启动时加载初始化信息
实例1
- /**
- * 使用session监听器实现统计在线人数
- * @author USER
- * date 2021年7月13日
- * @version 1.0
- */
- @WebListener
- public class SessionListener implements HttpSessionListener {
-
- public void sessionCreated(HttpSessionEvent arg0) {
- System.out.println("session监听器初始化完毕");
- CountUtil.add();
- arg0.getSession().getServletContext().setAttribute("online", CountUtil.getCount());
- }
-
- public void sessionDestroyed(HttpSessionEvent arg0) {
- System.out.println("session监听器销毁完毕");
- CountUtil.sub();
- arg0.getSession().getServletContext().setAttribute("online", CountUtil.getCount());
- }
-
- }
实例2
- /**
- * Application域生命周期的监听 设置全局的路径
- * @author USER
- * date 2021年7月12日
- * @version 1.0
- */
- @WebListener
- public class ApplicationListener implements ServletContextListener {
-
-
- public void contextDestroyed(ServletContextEvent arg0) {
- System.out.println("上下文销毁化完毕");
-
- }
-
- public void contextInitialized(ServletContextEvent arg0) {
- System.out.println("上下文初始化完毕");
- arg0.getServletContext().setAttribute("bp", arg0.getServletContext().getContextPath());
- }
-
- }