欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > 板块一 Servlet编程:第九节 过滤器全解 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程:第九节 过滤器全解 来自【汤米尼克的JAVAEE全套教程专栏】

2025/2/24 2:37:45 来源:https://blog.csdn.net/Tommy_Nike/article/details/136285634  浏览:    关键词:板块一 Servlet编程:第九节 过滤器全解 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程:第九节 过滤器全解

  • 一、什么是过滤器
  • 二、过滤器的实现
      • 一个过滤器拦截一个目录
      • 多个过滤器(Filter链)拦截一个目录
  • 三、过滤器处理中文乱码问题
  • 四、使用XML配置过滤器

程序员始终在为代码的可复用性努力着,过滤器也是一个典型的提高可复用性的工具,它让我们在一些逻辑上可以实现一劳永逸的效果

一、什么是过滤器

Filter 即为过滤,用于在Servlet之外对Request或者Response进行修改。它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理
使用Filter的完整流程:Filter 对用户请求进行预处理,接着将请求交给Servlet 进行处理并生成响应,最后Filter再对服务器响应进行后处理。 举个栗子,在 板块一 Servlet编程:第三节Request 中,请求响应进入Servlet的时候,每个文件都要对请求响应作中文乱码的处理,非常难受,如果在数据流入每个Servlet文件前面都经过一个过滤器,就能在过滤器里一劳永逸解决中文乱码问题了
在这里插入图片描述
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链
在这里插入图片描述

请求时先配置先执行;响应时以相反的顺序执行。
在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
在HttpServletResponse到达客户端之前,拦截HttpServletResponse。根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

二、过滤器的实现

在当前包下新建一个Fileter目录,作过滤器层
在这里插入图片描述
在Filter目录下新建filter1.java,现在的目录结构为
在这里插入图片描述

一个过滤器拦截一个目录

在filter1.java中实现一个过滤器需要以下步骤
实例

  • 实现接口
    在这里插入图片描述
  • 重写实现生命周期的三个方法
    在这里插入图片描述
    其中init()destroy()显然是我们耳熟能详的过滤器的生命周期的两个方法。而doFilter()就是过滤器的核心:过滤方法
    重写方法后,要在其中添加filterChain.doFilter(servletRequest,servletResponse);表示过滤后能放行的资源,也就是放行了来时的请求以及去时的响应,否则请求响应无法到达资源
    因此总体的doFliter()方法代码为
	@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOExceptionServletException {System.out.println("正在经过过滤器");filterChain.doFilter(servletRequest,servletResponse);}
  • 最后加上过滤器的访问注解@WebFilter("/start")
    注解中的目录就是过滤器将会过滤的目录,当然通常情况下是很多个项目一起过滤,此处只过滤start.java

最终filter.java的代码为

package www.caijiyuan.Filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;import java.io.IOException;@WebFilter("/start")
public class filter1 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器初始化成功");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOExceptionServletException {System.out.println("正在经过过滤器");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("过滤器销毁");}
}

它将过滤的start.java文件内容为

package www.caijiyuan.Servlt;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/start")
public class start extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletExceptionIOException {System.out.println("访问到Start");}
}

启动服务器,在浏览器中访问start,即可得到
在这里插入图片描述
可以看出服务器访问start.java文件之前是先经过lfilter1.java过滤器的

多个过滤器(Filter链)拦截一个目录

就如一、什么是过滤器中图示的,当有多个过滤器时,对于同一个文件请求的拦截顺序和响应的拦截顺序刚好相反,我们用实例来验证
在过滤器层中新添一个filter2
在这里插入图片描述
除了文件名内容与filter1完全一致

package www.caijiyuan.Filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;import java.io.IOException;@WebFilter("/start")
public class filter2 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器初始化成功");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOExceptionServletException {System.out.println("filter2正在拦截");filterChain.doFilter(servletRequest,servletResponse);System.out.println("filter2处理响应");}@Overridepublic void destroy() {System.out.println("过滤器销毁");}
}

此时再启动服务器,在浏览器中访问start.java即可在控制台打印
在这里插入图片描述
这就是filter链的演示效果,此外,如果filter1和filter2二者有一没有对请求响应进行filterChain.doFilter放行就会导致最终无法到达资源

三、过滤器处理中文乱码问题

早在Servlet的request和response两大对象小节我们就已经总结过中文乱码问题,现在我们就假设Tomcat8及以上POST请求时,使用Fliter处理中文乱码问题
在这里插入图片描述
实例:通过EncoderFliter.java过滤hello.jsp向after.java传递的中文参数

  • 实现生命周期:新建一个EncoderFliter.java的过滤器,implements自父类是Servlet包的Filter,并且在类中重写三个生命周期方法init\doFilter\destroy注意
  • 请求响应类型转换:doFilter中的request和response对象来自Servlet的实体,而我们之前用的request和response是来自HttpServlet的实体,因此需要在doFilter方法中类型转换
  • 处理乱码request.setCharacterEncoding("UTF-8");
  • 放行资源filterChain.doFilter(request,response);
  • Filter注释标识过滤范围,"*"为全部

最终EncoderFliter.java代码为

package www.caijiyuan.Filter;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 EncodeFliter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOExceptionServletException {// 基于HTTPHttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;// 处理POST请求乱码request.setCharacterEncoding("UTF-8");//放行资源filterChain.doFilter(request,response);}@Overridepublic void destroy() {}
}

此时的项目结构为
在这里插入图片描述

在hello.jsp中写一个POST表单用于传递请求参数

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>hello</title><h1>Tomcat with IDEA</h1>
</head>
<body>
<form action="after" method="post">输入参数<input type="text" name="name"><button>提交</button>
</form>
</body>
</html>

after.java用于接收参数

package www.caijiyuan.Servlt;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/after")
public class after extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletExceptionIOException {String name = req.getParameter("name");System.out.println(name);}
}

启动服务器在浏览器中访问hello.jsp,并传中文参
在这里插入图片描述
在没有使用过滤器之前,after.java在控制台打印
在这里插入图片描述

使用了过滤器之后,after.java在控制台打印
在这里插入图片描述
说明参数在被after接受之前确实先经过EncoderFliter.java过滤器,并且成功执行了doFilter里的设置。
这在我们有大量文件需要处理相同的设置时尤为方便,可以达到一劳永逸的效果,例如在访问一个购物网站时有些资源是登录以后才能查看的,例如在未登录状态下访问购物车就是一个非法访问,应该跳转到登录界面。这个非法访问拦截操作就可以用过滤器来实现

四、使用XML配置过滤器

除了用Servlet配置一个过滤器,其实我们还可以使用web.xml帮我们配置过滤器一些特定的参数,其基本格式为

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><filter><filter-name>FilterName</filter-name><filter-class>包的路径</filter-class><!-- Optional: Filter initialization parameters --><init-param><param-name>参数名</param-name><param-value>参数值</param-value></init-param></filter><filter-mapping><filter-name>FilterName</filter-name><url-pattern>/urlPattern</url-pattern><!-- Optional: Specify dispatcher types --><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher><dispatcher>INCLUDE</dispatcher><dispatcher>ERROR</dispatcher></filter-mapping></web-app>

例如,我们上面的处理中文乱码的过滤器就可以这样写
EncodeFilter.java

package www.caijiyuan.Filter;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class EncodeFilter implements Filter {public void init(FilterConfig config) throws ServletException {}public void destroy() {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletExceptionIOException {// 基于HTTPHttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;// 处理POST请求乱码request.setCharacterEncoding("UTF-8");//放行资源filterChain.doFilter(request,response);}
}

可以看出少了注解,此时过滤器覆盖的路径可以在web.xml中配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><filter><filter-name>EncodeFilter</filter-name><filter-class>www.caijiyuan.Filter.EncodeFilter</filter-class></filter><filter-mapping><filter-name>EncodeFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

此时实现的效果与使用Servlet配置过滤器一致
注意,XML的配置必须写在中,若配置XML文件请保证语法配置正确,否则Tomcat无法正常启动
可以看到XML中过滤器还有初始参数这一项

<init-param><param-name>参数名</param-name><param-value>参数值</param-value>
</init-param>

举个栗子可以这样使用:过滤器中使用初始化参数

<filter><filter-name>CustomFilter</filter-name><filter-class>com.example.CustomFilter</filter-class><init-param><param-name>apiKey</param-name><param-value>YOUR_API_KEY</param-value></init-param>
</filter>

我们定义了一个名为CustomFilter的过滤器,并为它指定了一个名为apiKey的初始化参数,其值为YOUR_API_KEY
在过滤器的init()方法中,可以通过FilterConfig对象来获取这个初始化参数

public class CustomFilter implements Filter {private String apiKey;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {apiKey = filterConfig.getInitParameter("apiKey");}...
}

如此或取了初始化参数的值,并将其存储在apiKey变量中供过滤器的其他方法使用,初始化参数是可选的,可以根据需要在过滤器的配置中添加或删除它们

以上就是此小节的所用内容了,我们学习了过滤器最基础的使用方法,下一节中我们将学习过滤器的兄弟:监听器

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词