过滤器的实现及其原理责任链设计模式

Filter过滤器

过滤器的应用

DeptServlet,EmpServlet,OrderServlet三个业务类的业务方法执行之前都需要编写判断用户是否登录和解决的中文乱码的代码,代码没有得到重复利用

Filter是过滤器可以用来编写请求的过滤规则和多个Servlet都会执行的公共代码,Filter中的业务代码既可以在目标Servlet程序执行之前也可以在其之后执行

  • Filter的生命周期和Servlet对象生命周期一致,先实例化(一次即单例)–>执行初始化方法(一次)–>处理请求方法(每次请求都会调用)–>销毁方法(一次)
  • Filter默认情况下在服务器启动阶段就会实例化 , Servlet默认在用户发起对应请求的时候才会实例化
  • Filter的优先级天生的就比Servlet优先级高,若Filter和Servlet都可以处理/a.do请求,那么一定是先执行Filter然后再执行Servlet

在这里插入图片描述

/*** 处理部门相关的业务类*/
@WebServlet({"/dept/list", "/dept/detail", "/dept/delete", "/dept/save", "/dept/modify"})
public class DeptServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 低版本的Tomcat还需要解决post请求乱码问题request.setCharacterEncoding("UTF-8");// 响应中文乱码问题response.setContentType("text/html;charset=UTF-8");// 获取当前session,这个session是不需要新建的,获取不到就返回nullHttpSession session = request.getSession(false);if(session != null && session.getAttribute("username") != null){String servletPath = request.getServletPath();if("/dept/list".equals(servletPath)){doList(request, response);}else if("/dept/detail".equals(servletPath)){doDetail(request, response);}else if("/dept/delete".equals(servletPath)){doDel(request, response);}else if("/dept/save".equals(servletPath)){doSave(request, response);}else if("/dept/modify".equals(servletPath)){doModify(request, response);}}else{// 获取不到session或session中没有存储用户的信息就跳转到登录页面response.sendRedirect(request.getContextPath() + "/index.jsp"); }}
}
/*** 处理员工相关的业务类*/
public class EmpServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 解决post请求乱码问题request.setCharacterEncoding("UTF-8");// 响应中文乱码问题response.setContentType("text/html;charset=UTF-8");HttpSession session = request.getSession(false);if(session != null && session.getAttribute("username") != null){String servletPath = request.getServletPath();//...}else{response.sendRedirect(request.getContextPath() + "/index.jsp");}}
}
/*** 处理订单相关的业务类*/
public class OrderServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 解决post请求乱码问题request.setCharacterEncoding("UTF-8");// 解决响应中文乱码问题response.setContentType("text/html;charset=UTF-8");HttpSession session = request.getSession(false);if(session != null && session.getAttribute("username") != null){String servletPath = request.getServletPath();//...}else{response.sendRedirect(request.getContextPath() + "/index.jsp");}}
}

责任链设计模式

传统模式方法调用时在编译阶段已经完全确定了方法的调用顺序,如果想改变方法的调用顺序必须修改源代码,显然违背了OCP原则

public class Test {public static void main(String[] args) {System.out.println("main begin");m1();System.out.println("main over");}private static void m1() {System.out.println("m1 begin");m2();System.out.println("m1 over");}private static void m2() {System.out.println("m2 begin");m3();System.out.println("m2 over");}private static void m3() {System.out.println("目标正在执行中。。。。");}
}

责任链设计模式: 由于方法的调用顺序在程序编译阶段无法确定,需要根据实际情况在程序运行阶段动态的组合方法的调用顺序,实现代码的灵活性

  • Filter使用了责任链设计模式,将Filter的调用顺序配置到了web.xml文件中,想要调整Filter的执行顺序只需要修改配置文件中filter-mapping标签的顺序
<filter><filter-name>filter</filter-name><filter-class>com.bjpowernode.javaweb.servlet.Filter2</filter-class>
</filter>
<filter-mapping><filter-name>filter</filter-name><url-pattern>*.do</url-pattern>
</filter-mapping>

实现过滤器

第一步:编写一个类实现jarkata.servlet.Filter接口,由于接口中的方法都有默认的方法体,我们可以根据需求实现方法

方法名功能
init(FilterConfig filterConfig)在Filter对象第一次被创建之后调用,并且只调用一次
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)编写过滤规则和公共代码的方法,只要用户发送一次请求就执行一次 , 发送N次请求执行N次
destroy()在Filter对象被释放/销毁之前调用,并且只调用一次

第二步: 执行FilterChain类的doFilter方法放行,过滤器只有放行了请求,目标Servlet才有机会执行到

方法名功能
doFilter(request, response)执行下一个过滤器,如果下面没有过滤器了才执行最终处理对应请求路径的Servlet
public class Filter implements Filter {public Filter1(){System.out.println("无参数构造方法执行");}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("init方法执行。");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 在请求的时候添加过滤规则System.out.println("Filter1 doFilter方法开始执行");// 执行下一个过滤器,如果下一个不是过滤器则执行目标程序Servletchain.doFilter(request, response);// 在响应的时候添加过滤规则System.out.println("Filter1 doFilter方法执行结束");}@Overridepublic void destroy() {System.out.println("destroy方法执行");}
}

第三步: 编写目标Servlet处理用户的请求

@WebServlet("/a.do")
public class AServlet  extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {System.out.println("AServlet中的doGet方法执行了");}
}@WebServlet("/b.do")
public class BServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {System.out.println("BServlet中的doGet方法执行了");}
}

第四步: 配置Filter拦截的请求路径和执行顺序(Filter执行时遵循栈的数据结构),配置过滤器拦截的请求路径时可以使用通配符*

  • 在web.xml文件中配置(常用): Filter的执行顺序取决于filter-mapping标签的配置位置,越靠上优先级越高,和filter标签的位置无关
  • 在@WebFilter注解中配置(修改过滤器执行顺序不方便): Filter的执行顺序取决于Filter的类名(按字典序排序) , 比如在FilterA和FilterB中先执行FilterA
匹配方式举例
精确匹配/a.do、/b.do、/dept/save
模糊匹配*/*表示拦截所有路径
后缀匹配*,不能以/开始*.do表示拦截所有以.do结尾的路径
前缀匹配*,以/开始/dept/*表示拦截/dept/路径及其子路径
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><filter><filter-name>filter</filter-name><filter-class>com.bjpowernode.javaweb.servlet.Filter</filter-class></filter><filter-mapping><filter-name>filter</filter-name><!--<url-pattern>a.do</url-pattern><url-pattern>b.do</url-pattern>--><url-pattern>*.do</url-pattern></filter-mapping>
</web-app>
//@WebFilter({"/a.do", "/b.do"})
@WebFilter({"*.do"})
public class Filter implements Filter {public Filter1(){System.out.println("无参数构造方法执行");}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("init方法执行。");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 在请求的时候添加过滤规则System.out.println("Filter1 doFilter方法开始执行");// 执行下一个过滤器,如果下一个不是过滤器则执行目标程序Servletchain.doFilter(request, response);// 在响应的时候添加过滤规则System.out.println("Filter1 doFilter方法执行结束");}@Overridepublic void destroy() {System.out.println("destroy方法执行");}
}

使用过滤器改造oa项目

第一步: 编写一个过滤器LoginCheckFilter同时指定不需要拦截的路径

  • 当用户访问index.jsp首页,用户已经登录了(session中有用户信息),用户想要登录或退出,用户访问项目根目录即欢迎页的请求不能拦截
public class LoginCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {//强制类型转化HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse) resp;// 获取请求路径String servletPath = request.getServletPath();HttpSession session = request.getSession(false);if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||"/user/login".equals(servletPath) || "/user/exit".equals(servletPath)|| (session != null && session.getAttribute("user") != null)){// 继续往下走chain.doFilter(request, response);}else{response.sendRedirect(request.getContextPath() + "/index.jsp");}}
}

第二步: 在web.xml中注册过滤器,/*表示拦截所有的路径

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><!--登录检查的过滤器,过滤所有的路径--><filter><filter-name>loginFilter</filter-name><filter-class>com.bjpowernode.oa.web.filter.LoginCheckFilter</filter-class></filter><filter-mapping><filter-name>loginFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
</web-app>

第三步: 业务类相关的Servlet就不需要再编写代码判断用户是否登录,如果请求能到目标Servlet说明用户一定是登录过了,目标Servlet只需要转发请求即可

@WebServlet({"/dept/list", "/dept/detail", "/dept/delete", "/dept/save", "/dept/modify"})
public class DeptServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String servletPath = request.getServletPath();if("/dept/list".equals(servletPath)){doList(request, response);}else if("/dept/detail".equals(servletPath)){doDetail(request, response);}else if("/dept/delete".equals(servletPath)){doDel(request, response);}else if("/dept/save".equals(servletPath)){doSave(request, response);}else if("/dept/modify".equals(servletPath)){doModify(request, response);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/130900.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这个方法用得好,工作车间效率翻倍!

工作车间是各种制造和生产过程的核心&#xff0c;依赖于可靠的电力分配系统以维持正常运营。然而&#xff0c;电力分配柜的状态监控通常被低估&#xff0c;而它对工作车间的安全性、效率和可靠性产生了深远的影响。 因此&#xff0c;配电柜监控变得至关重要&#xff0c;它可以提…

怎样选择一套适合自己的跨境商城源码?

一、选择适合自己的跨境商城源码的关键因素 在选择适合自己的跨境商城源码之前&#xff0c;您首先需要考虑几个关键因素。这些因素将决定您的商城的性能、功能和可定制性。以下是您应该重点考虑的因素&#xff1a; 1. 可扩展性 选择一套具有良好可扩展性的商城源码至关重要。一…

京东商品列表数据接口,关键词搜索京东商品数据接口

在网页抓取方面&#xff0c;可以使用 Python、Java 等编程语言编写程序&#xff0c;通过模拟 HTTP 请求&#xff0c;获取京东网站上的商品页面。在数据提取方面&#xff0c;可以使用正则表达式、XPath 等方式从 HTML 代码中提取出有用的信息。值得注意的是&#xff0c;京东网站…

STM32使用HAL库驱动DS3231

1、STM32通讯口配置 启动IIC&#xff0c;默认配置即可。 2、头文件 #ifndef __DS3231_H #define __DS3231_H#include "main.h"#define DS3231_COM_PORT hi2c1 /*通讯端口*//**************************** defines *******************************/ #define DS3231…

RK3568平台开发系列讲解(驱动篇)RK3568 PWM详解

🚀返回专栏总目录 文章目录 一、什么是PWM二、RK3568 PWM2.1、PWM 通道与引脚2.2、PWM 简介2.3、PWM 设备节点沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 PWM 是很常用到功能,我们可以通过 PWM 来控制电机速度,也可以使用 PWM 来控制 LCD 的背光亮度。 一、什…

IntelliJ IDEA 2023.1 版本可以安装了

Maven 的导入时间更加快了。 收到的有邮件提醒安装。 安装后的版本&#xff0c;其实就是升级下&#xff0c;并没有什么主要改变。 IntelliJ IDEA 2023.1 版本可以安装了 - 软件技术 - OSSEZMaven 的导入时间更加快了。 收到的有邮件提醒安装。 安装后的版本&#xff0c;其实就是…

【力扣2011】执行操作后的变量值

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述二、题目分析 一、题目描述 题目链接&#xff1a;执行操作后的变量值 存在一种仅支持 4 种操作和 1 个变量 …

TensorFlow学习:使用官方模型进行图像分类、使用自己的数据对模型进行微调

前言 上一篇文章 TensorFlow案例学习&#xff1a;对服装图像进行分类 中我们跟随官方文档学习了如何进行预处理数据、构建模型、训练模型等。但是对于像我这样的业余玩家来说训练一个模型是非常困难的。所以为什么我们不站在巨人的肩膀上&#xff0c;使用已经训练好了的成熟模…

C++ PCL点云局部颜色变换

程序示例精选 C PCL点云局部颜色变换 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《C PCL点云局部颜色变换》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应用…

智能文本纠错API的崭露头角:革命性的写作辅助工具

前言 在数字化时代&#xff0c;文字是我们日常生活和工作中的不可或缺的一部分。不论是在社交媒体上发帖、撰写商务邮件还是完成学术论文&#xff0c;文字表达都是沟通的核心。然而&#xff0c;字词错误、语法错误和敏感信息却是许多人常常面临的挑战&#xff0c;它们不仅会影…

CSS图文悬停翻转效果完整源码附注释

实现效果截图 HTML页面源码 <!DOCTYPE html> <html><head><meta http-equiv="content-type

CTR特征建模:ContextNet MaskNet(Twitter在用的排序模型)

在之前的文章中 FiBiNet&FiBiNet模型&#xff0c;阐述了微博在CTR特征(Embedding)重要性建模方面的一些实践方向&#xff0c;今天再来学习下这个方面的两个相关研究&#xff1a;致力于特征和特征交互精炼(refine)的ContextNet和MaskNet&#xff0c;其中MaskNet也是Twitter(…