系统定制开发JavaWeb过滤器(Filter)详解,是时候该把过滤器彻底搞懂了(万字说明)

        注意:系统定制开发这篇文章很长,系统定制开发学习完后将会解决你对于过滤器(Filter)系统定制开发的所有疑惑,系统定制开发下面将通过理论和代码系统定制开发的结合来进行讲解演示..... 


 目录


基本介绍

        过滤器,系统定制开发顾名思义就是对事物进行过滤的,在Web系统定制开发中的过滤器,系统定制开发当然就是对请系统定制开发求进行过滤,系统定制开发我们使用过滤器,系统定制开发就可以对请求进行拦截,系统定制开发然后做相应的处理,系统定制开发实现许多特殊功能。系统定制开发如登录控制,权限管理,系统定制开发过滤敏感词汇等.

系统定制开发过滤器原理

        系统定制开发当我们使用过滤器时,系统定制开发过滤器会对游览器的请求进行过滤,系统定制开发过滤器可以动态的分为3个部分,1.系统定制开发放行之前的代码,2.放行,3.系统定制开发放行后的代码,这3系统定制开发个部分分别会发挥不同作用。

  • 系统定制开发第一部分代码会对游览系统定制开发器请求进行第一次过滤,系统定制开发然后继续执行
  • 第二部分代码就是将游览器请求放行,如果还有过滤器,那么就继续交给下一个过滤器
  • 第三部分代码就是对返回的Web资源再次进行过滤处理

我们使用过滤器,也就是说,不止请求会经过过滤器,我们的响应也会经过过滤器。


过滤器(Filter)接口

        我们学习过滤器,肯定就要先看一下官方给我们提供的过滤器接口。下面我们使用Idea来查看Filter。

         我们通过官方提供的过滤器可以看出过滤器(Filter)使用起来还是比较简单的,下面我们就来学习如何使用过滤器(Filter)


使用过滤器(Filter)

        我们使用过滤器肯定要导入相应的jar包才行,Filter就在servlet-api.jar中,我们将该jar包放到WEB-INF下的lib目录下面,然后加入项目。

创建过滤器(Fliter)

        我们创建Filter,只需要继承Filter接口就行。

  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. public class MyFilter implements Filter {
  4. @Override
  5. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  6. }
  7. }

         Filter接口有3个方法,但是只有一个方法没有实现,我们只需要实现这个方法就行。我们可以发现,我们实现了一个doFilter方法,这个方法就是我们写过滤代码的地方,具体逻辑就是和上面介绍的过滤器原理一样的。


使用过滤器(Filter)

        我们先来感受一下如何使用过滤器,细节我们后面慢慢说明。我们在上面创建的类中写入以下代码,并且加一个WebFIlter注解

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import java.io.IOException;
  4. @WebFilter("/*")
  5. public class MyFilter implements Filter {
  6. @Override
  7. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  8. System.out.println("对request进行过滤");
  9. //下面这行代码就是放行
  10. filterChain.doFilter(servletRequest,servletResponse);
  11. System.out.println("对response进行过滤");
  12. }
  13. }

        我简单介绍下上面的代码,WebFilter("/*")表示对所有请求进行过滤,而在doFilter中的放行代码,也就是filterChain.doFilter(servletRequest,servletResponse);这行代码就是对拦截进行放行,细节我们后面讲,现在先怎么理解就行。

        启动服务器,然后我们在游览器中输入,注意,filter是我们自己配置的web工程路径,后面的abc随便输入的。我们下面来查看游览器后控制台输出。

游览器输出 

控制台输出 

        现在,我们就已经可以得出两个结论了,过滤器并不会管资源是否存在,而只会对配置的拦截路径进行拦截。拦截不仅会对请求进行拦截,而且还会对相应进行拦截。


配置过滤器(Filter)拦截路径 

        配置Filter的拦截路径有2种方式,一种是注解,一种是方式,我们分别进行讲解。

注解方式

        我们如果使用注解来进行配置,那么我们就需要使用@WebFilter,我们不说废话,直接看该注解的源码。

        里面的配置项还是有很多的,下面我对常用配置项进行说明:

  • filterName:该filter的名字
  • initParams:初始化参数
  • displayName:filter显示名称
  • servletNames:指定对哪些servlet进行过滤
  •  asyncSupported:是否支持异步模式
  • urlPatterns:指定拦截路径
  • value:指定拦截路径

        注意:urlPatterns和value是一样的。urlPatterns和value只能配置一个,不能两个都配置,两个都配置就会报错。

        对于使用@WebFilter,里面的多个参数用 , 进行分隔。 

        说明:如果我们仅仅需要配置一个拦截路径,那么我们可以直接简写@WebLister("拦截路径"),如@WebFilter("/*")就是拦截所有请求。 


xml方式 

        xml方式可以说是和Servlet使用xml配置方式一样了,这里就不废话,直接配置一个。

  1. <filter>
  2. <filter-name>myFilter</filter-name>
  3. <filter-class>com.clucky.filter.MyFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>myFilter</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

        这个就是xml配置方式,只不过把注解换成了xml标签来配置,里面属性都是一样的,这个和Servlet的配置方式基本一样,这里就不再赘述了。


过滤器(Filter)

        我们都知道Servlet有一个生命周期,当然Filter也有一个生命周期,下面我们就来探讨一下Filter的生命周期。

        Filter的生命周期和Servlet也十分相似,如果大家对Servlet的生命周期不怎么熟悉,那么可以看一下这篇文章。

        我们创建一个类,实现Filter的所有方法。

  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. public class LifeCycleFilter implements Filter {
  4. @Override
  5. public void init(FilterConfig filterConfig) throws ServletException {
  6. }
  7. @Override
  8. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  9. }
  10. @Override
  11. public void destroy() {
  12. }
  13. }

理论说明 

          Filter有3个阶段,分别是初始化,拦截和过滤,销毁。

  1. 初始化阶段:当服务器启动时,我们的服务器(Tomcat)就会读取配置文件,扫描注解,然后来创建我们的Filter。
  2. 拦截和过滤阶段:只要请求资源的路径和拦截的路径相同,那么过滤器就会对请求进行过滤,这个阶段在服务器运行过程中会一直循环。
  3. 销毁阶段:当服务器(Tomcat)关闭时,服务器创建的Filter也会随之销毁。

代码演示

        Filter的三个阶段就对应着Filter的3个方法,init方法会在Filter创建时调用,doFilter方法会在请求和拦截匹配时调用,destroy方法会在Filter销毁时调用。我们来对这些方法进行编写验证。

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import java.io.IOException;
  4. @WebFilter("/*")
  5. public class LifeCycleFilter implements Filter {
  6. @Override
  7. public void init(FilterConfig filterConfig) throws ServletException {
  8. //这个方法就是初始化方法,在Filter创建时调用
  9. System.out.println("调用了init()方法");
  10. }
  11. @Override
  12. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  13. //这个方法就是过滤和拦截的方法,当请求和拦截匹配时调用
  14. System.out.println("调用了doFilter()方法");
  15. }
  16. @Override
  17. public void destroy() {
  18. //这个方法就是销毁方法,在Filter销毁前调用
  19. System.out.println("调用了destroy()方法");
  20. }
  21. }

启动服务器控制台输出

进行拦截时控制台输出 

关闭服务器控制台输出 

        都和我们预想的一样,到此,我们就成功验证了Filter的生命周期。 


 FilterConfig和FilterChain说明

        FilterConfig和FilterConfig这2个对象是由服务器(Tomcat)在创建和调用Filter对象时所传入的,这2个对象十分有用,FilterConfig对象可以读取我们配置的初始参数,FilterChain可以实现多个Filter之间的连接。


FilterConfig

        老规矩,我们要学习一个对象,首先查看类图和源代码

        里面的方法就4个,下面我们分别进行讲解

  • getFilterName():获取filter的名称
  • getServletContext():获取ServletContext
  • getInitparamter(String var1):获取配置的初始参数的值
  • getInitParamterNames():获取配置的所有参数名称

FilterConfig实例运用

        我们在init方法中使用FilterConfig来读取配置的数据库的信息,然后输出。

java代码

  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. import java.util.Enumeration;
  4. public class MyFilterConfig implements Filter {
  5. @Override
  6. public void init(FilterConfig filterConfig) throws ServletException {
  7. System.out.println("-----------获取全部key:value------------");
  8. //得到所有配置参数的名字
  9. Enumeration<String> names = filterConfig.getInitParameterNames();
  10. while (names.hasMoreElements()) {
  11. //得到每一个名字
  12. String name = names.nextElement();
  13. System.out.println(name+" = "+filterConfig.getInitParameter(name));
  14. }
  15. System.out.println("-----------end.....------------");
  16. }
  17. @Override
  18. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  19. }
  20. @Override
  21. public void destroy() {
  22. }
  23. }

xml配置 

  1. <filter>
  2. <filter-name>myFilterConfig</filter-name>
  3. <filter-class>com.clucky.filter.MyFilterConfig</filter-class>
  4. <init-param>
  5. <param-name>driver</param-name>
  6. <param-value>com.mysql.jdbc.Driver</param-value>
  7. </init-param>
  8. <init-param>
  9. <param-name>url</param-name>
  10. <param-value>jdbc:mysql://localhost:3306/equip_employ_manage?serverTimezone=GMT</param-value>
  11. </init-param>
  12. <init-param>
  13. <param-name>username</param-name>
  14. <param-value>root</param-value>
  15. </init-param>
  16. <init-param>
  17. <param-name>password</param-name>
  18. <param-value>root</param-value>
  19. </init-param>
  20. </filter>
  21. <filter-mapping>
  22. <filter-name>myFilterConfig</filter-name>
  23. <url-pattern>/*</url-pattern>
  24. </filter-mapping>

启动服务器,控制台输出

         我们使用FilterConfig提供的方法就成功实现了功能,FilterConfig就是用来读取配置文件的。


FilterChain 

        一样,我们还是先来查看源代码以及类图

         我们查看类图,可以发现FilterChain就只有一个方法,其实这个方法就是用来对拦截进行放行的,如果有多个拦截器,那么就会继续调用下一个Filter进行拦截。doFilter方法需要传入个参数,一个是ServletRequest,一个是ServletResponse参数,这个直接传入进行。

        Tomcat在调用过滤器时,默认就会传入Request和Response,这个参数封装了请求和响应,我们直接使用就行。ServletResquest和ServletResponse可以直接强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法。

 将ServletRequest转成HttpServletRequest


FilterChain应用实例

        我们前面一直都是一个Filter,现在我们来配置2个Filter,通过FilterChain来进行多个过滤。

第一个Filter

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import java.io.IOException;
  4. @WebFilter("/*")
  5. public class Filter01 implements Filter {
  6. @Override
  7. public void init(FilterConfig filterConfig) throws ServletException {
  8. }
  9. @Override
  10. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  11. System.out.println("调用过滤器01对请求进行过滤~~~~");
  12. //放行,如果还有过滤器,那么就执行下一个过滤器
  13. filterChain.doFilter(servletRequest,servletResponse);
  14. System.out.println("调用过滤器01对响应进行过滤~~~~");
  15. }
  16. @Override
  17. public void destroy() {
  18. }
  19. }

第二个过滤器

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import java.io.IOException;
  4. @WebFilter("/*")
  5. public class Filter02 implements Filter {
  6. @Override
  7. public void init(FilterConfig filterConfig) throws ServletException {
  8. }
  9. @Override
  10. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  11. System.out.println("调用过滤器02对请求进行过滤~~~~");
  12. //放行,如果还有过滤器,那么就执行下一个过滤器
  13. filterChain.doFilter(servletRequest,servletResponse);
  14. System.out.println("调用过滤器02对响应进行过滤~~~~");
  15. }
  16. @Override
  17. public void destroy() {
  18. }
  19. }

        启动服务器,然后我们游览器输入(filter是我配置的web工程路径)来进行访问,查看控制台输出。

         我们可以看见Filter01先进行过滤,然后交给Filter02,然后访问资源,然后Filter02对响应进行过滤,然后Filter01对响应进行过滤。图示如下:

        我们先使用Filter01对请求进行过滤,那么很自然的,我们就是使用Filter02先对响应进行过滤。 


 多个Filter的执行顺序

        上面我们配置了2个过滤器,那么我们怎么知道那个过滤器先执行呢?其实大家可以直接使用代码进行验证,培养独立思考的习惯,这里我就直接给出答案了。

  • 如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是<filter-mapping>在web配置的顺序,配置在上面那么就会先执行。
  • 如果我们是使用@WebFilter进行配置的,那么执行顺序就是字符比较顺序来执行,例如有2个过滤器,一个是AFilter,一个是BFilter,那么AFilter就会先执行。
  • 如果注解和xml混用,那么在web.xml中配置的会先执行。

执行顺序验证

        我这里就验证第一条,也就是web.xml中配置的顺序和<filter-mapping>顺序一样,其他大家感兴趣自己验证。

xml配置顺序 3->1->2

  1. <filter>
  2. <filter-name>filter03</filter-name>
  3. <filter-class>com.clucky.filter.Filter03</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>filter03</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>
  9. <filter>
  10. <filter-name>filter01</filter-name>
  11. <filter-class>com.clucky.filter.Filter01</filter-class>
  12. </filter>
  13. <filter-mapping>
  14. <filter-name>filter01</filter-name>
  15. <url-pattern>/*</url-pattern>
  16. </filter-mapping>
  17. <filter>
  18. <filter-name>filter02</filter-name>
  19. <filter-class>com.clucky.filter.Filter02</filter-class>
  20. </filter>
  21. <filter-mapping>
  22. <filter-name>filter02</filter-name>
  23. <url-pattern>/*</url-pattern>
  24. </filter-mapping>

Filter01

  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. public class Filter01 implements Filter {
  4. @Override
  5. public void init(FilterConfig filterConfig) throws ServletException {
  6. }
  7. @Override
  8. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  9. System.out.println("调用过滤器01对请求进行过滤~~~~");
  10. //放行,如果还有过滤器,那么就执行下一个过滤器
  11. filterChain.doFilter(servletRequest,servletResponse);
  12. System.out.println("调用过滤器01对响应进行过滤~~~~");
  13. }
  14. @Override
  15. public void destroy() {
  16. }
  17. }

Filter02

  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. public class Filter02 implements Filter {
  4. @Override
  5. public void init(FilterConfig filterConfig) throws ServletException {
  6. }
  7. @Override
  8. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  9. System.out.println("调用过滤器02对请求进行过滤~~~~");
  10. //放行,如果还有过滤器,那么就执行下一个过滤器
  11. filterChain.doFilter(servletRequest,servletResponse);
  12. System.out.println("调用过滤器02对响应进行过滤~~~~");
  13. }
  14. @Override
  15. public void destroy() {
  16. }
  17. }

Filter03

  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. public class Filter03 implements Filter{
  4. @Override
  5. public void init(FilterConfig filterConfig) throws ServletException {
  6. }
  7. @Override
  8. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  9. System.out.println("调用过滤器03对请求进行过滤~~~~");
  10. //放行,如果还有过滤器,那么就执行下一个过滤器
  11. filterChain.doFilter(servletRequest,servletResponse);
  12. System.out.println("调用过滤器03对响应进行过滤~~~~");
  13. }
  14. @Override
  15. public void destroy() {
  16. }
  17. }

        我们启动服务器,游览器访问,然后查看控制台输出是不是我们配置的3->1->2的顺序

         发现执行顺序果然是这样,另外2个的验证大家感兴趣可以自己验证,我这里就不验证了,如果嫌麻烦,那么记住就行了。


Filter应用实例(实现敏感词汇过滤) 

        我们学了那么多,现在来做一个实例,我们写一个评论页面,可以进行评论,如果评论中含有我们定义的敏感词汇,那么我们就进行过滤,使用**来进行代替。

代码实现

jsp页面

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>评论</title>
  5. </head>
  6. <body>
  7. <h1>输入评论内容</h1>
  8. <form action="${pageContext.request.contextPath}/comment" method="post">
  9. <textarea name="message" cols="30" rows="10"></textarea>
  10. <input type="submit" value="提交">
  11. </form>
  12. <p >${requestScope.get("name")}<span style="color: red">${requestScope.get("comment")}</span></p>
  13. </body>
  14. </html>

Filter代码

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import javax.servlet.annotation.WebInitParam;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. @WebFilter(servletNames = {"comment"},initParams = {@WebInitParam(name = "sensitiveWord", value = "zz")})
  8. public class CommentFilter implements Filter {
  9. private List<String> sensitiveWords = new ArrayList<>();
  10. @Override
  11. public void init(FilterConfig filterConfig) throws ServletException {
  12. //得到敏感词汇
  13. String word = filterConfig.getInitParameter("sensitiveWord");
  14. //加入集合
  15. sensitiveWords.add(word);
  16. }
  17. @Override
  18. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  19. //设置编码
  20. servletRequest.setCharacterEncoding("utf-8");
  21. servletResponse.setContentType("text/html;charset=utf-8");
  22. //得到评论
  23. String message = servletRequest.getParameter("message");
  24. for (String sensitiveWord : sensitiveWords) {
  25. //对所有敏感词汇进行过滤
  26. if (message.contains(sensitiveWord)){
  27. //替换敏感词汇
  28. message = message.replace(sensitiveWord, "**");
  29. }
  30. }
  31. //存入request域
  32. servletRequest.setAttribute("comment",message);
  33. //放行
  34. filterChain.doFilter(servletRequest,servletResponse);
  35. }
  36. @Override
  37. public void destroy() {
  38. }
  39. }

Servlet代码

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebServlet;
  3. import javax.servlet.http.*;
  4. import java.io.IOException;
  5. import java.util.HashSet;
  6. @WebServlet(name = "comment",value = "/comment")
  7. public class CommentServlet extends HttpServlet {
  8. //记录评论敏感词汇的ip
  9. private HashSet<String> hashSet = new HashSet<>();
  10. @Override
  11. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. String message = request.getParameter("message");
  13. String comment = (String) request.getAttribute("comment");
  14. if (message.equals(comment)){
  15. System.out.println("没有敏感词汇.....");
  16. //设置名字
  17. request.setAttribute("name","good boy:");
  18. }else {
  19. //有敏感词汇,记录IP
  20. String localAddr = request.getLocalAddr();
  21. System.out.println(localAddr);
  22. hashSet.add(localAddr);
  23. //设置名字
  24. request.setAttribute("name","bad boy:");
  25. }
  26. //转发到comment.jsp页面
  27. request.getRequestDispatcher("/comment.jsp").forward(request,response);
  28. }
  29. @Override
  30. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  31. this.doGet(request, response);
  32. }
  33. }

代码验证

        我们输入,来访问jsp页面.

         输入评论内容:你好啊!!!

         下面显示了我们的评论,我们再来输入:你真是个zz

         显示你真是个**,我们的评论过滤就成功了。


总结 

        通过上面的学习,相信大家对Filter的掌握肯定也上了一个台阶,但是理论知识的掌握并不能代码大家已经真正学会了,打开编译器,开始练习吧,技术就就是靠一行行代码堆起来的!!!

        如果觉得讲的还不错,那么就点赞评论支持一下吧 

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发