一、过滤器的基本知识点
- 在Java web项目开发中,过滤器的应用十分广泛,其中比较应用比较典型的就是字符编码过滤器。由于程序需要在多种平台下运行,其内部的Unicode字符集表示字符,所以处理中文数据就会产生乱码的情况,需要对其进行编码转化才可以正常显示。
- Servlet过滤器是客户端和目标资源的中间层组件,主要是用于拦截客户端的请求和响应信息。如当web容器收到一条客户端发来的请求
web容器判断该请求是否与过滤器相关联,如果相关联就交给过滤器进行处理,处理完可以交给下一个过滤器或者其他业务,当其他业务完成需要对客户端进行相应的时候,容器又将相应交给过滤器进行处理,过滤器处理完响应就将响应发送给客户端。
1:web容器是如何判断请求和过滤器相关联。
2:过滤器是如何将处理完的请求交给其他过滤器的
前提知识:过滤器有三个接口
1:Filter接口中有三个方法
(1)public void init(FilterConfig filterConfig)//这个参数中含有web.xml文件中的初始化参数,可以用来对请求进行处理 。
(2) public void doFilter(ServletRequest request,ServletRequest response,FilterChain chain)//要注意第三个参数它主要是用来将处理完的请求发送到下一个过滤器。
(3)public void destroy()//销毁过滤器
2:FilterChain:此方法主要用于将过滤器处理的请求或者响应传递给下一个过滤器对象。
(1)void doFilter(ServletRequest request,ServletRequest response)
3:FilterConfig:此接口由容器进行实现,用于获取过滤器初始化期间的参数信息方法有以下四个。
(1)返回过滤器的名称:public String getFilterName()
(2)返回初始化名称为name的参数集:public String getInitParameter(String name)
(3)返回所有参数名的枚举集合:public Enumeration getInitParameterNames(String name)
(4)返回Servlet的上下文对象:public ServletContext getServletContext()
Filter简介
- Servlet过滤器Fileter是一个小型的web组件,它们通过拦截请求和响应,以便查看、提取或以某种方式操作客户端和服务器之间交换的数据,实现“过滤”的功能。Filter通常封装了一些功能的web组件,过滤器提供了一种面向对象的模块化机制,将任务封装到一个可插入的组件中, Filter组件通过配置文件来声明,并动态的代理。
简单来说Servlet的Filter是:
-
声明式的:通过在web.xml配置文件中声明,允许添加、删除过滤器,而无需改动任何应用程序代码或jsp页面。
-
灵活的:过滤器可用于客户端的直接调用执行预处理和后期的处理工作,通过过滤链可以实现一些灵活的功能。
-
可移植的:由于现今各个web容器都是以Servlet的规范进行设计的,因此Servlet过滤器同样是跨容器的。
-
可重用的:基于其可移植性和声明式的配置方式,Filter是可重用的。
总的来说,Servlet的过滤器是通过一个配置文件来灵活的声明的模块化可重用组件。过滤器动态的截获传入的请求和传出的响应,在不修改程序代码的情况下,透明的添加或删除他们。其独立于任何平台和web容器。
(1)Filter体系结构
如其名字所暗示的一样,Servlet过滤器用于拦截传入的请求和传出的响应,并监视、修改处理web工程中的数据流。过滤器是一个可插入的自由组件。web资源可以不配置过滤器、也可以配置单个过滤器,也可以配置多个过滤器,形成一个过滤器链。Filter接受用户的请求,并决定将请求转发给链中的下一个组件,或者终止请求直接向客户端返回一个响应。如果请求被转发了,它将被传递给链中的下一个过滤器(以web.xml过滤器的配置顺序为标准)。这个请求在通过过滤链并被服务器处理之后,一个响应将以相反的顺序通过该链发送回去。这样,请求和响应都得到了处理。
(2)Filter工作原理
基于Filter体系结构的描述,我们可以看出Filter的工作原理,简单的通过一幅流程图加以演示:
客户端浏览器在访问web服务器的某个具体资源的时候,经过过滤器1中code1代码块的相关处理之后,将request请求传递给过滤链中的下一个过滤器2,(过滤链的顺序以配置文件中的顺序为基准)过滤器2处理完之后,request就传递的Servlet完成相应的逻辑。返回响应的过程类似,只是过滤链的顺序相反,这里就不多说了。
(3)Filter的创建过程
要编写一个过滤器必须实现Filter接口。实现其接口规定的方法。
-
实现javax.servlet.Filter接口
-
实现init方法,读取过滤器的初始化参数
-
实现doFilter方法,完成对请求或响应的过滤
-
调用FilterChain接口对象的doFilter方法,向后续的过滤器传递请求或响应
一个最基本的过滤器实现代码:
二、字符编码过滤器实例以及结果
1.创建字符编码过滤器的类,该类实现了Filter接口,并对于3种方法进行了实现。
import javax.servlet.*;
import java.io.IOException;
public class example65 implements Filter {
//字符编码(参数初始化)
protected String encoding=null;
//FilterConfig对象
protected FilterConfig filterConfig=null;
//初始化方法
public void init(FilterConfig filterConfig) throws ServletException{
//对filterConfig赋值
this.filterConfig=filterConfig;
//对初始化参数赋值
this.encoding=filterConfig.getInitParameter("encoding");
}
//过滤器处理方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException
{
//判断字符是否有效
if(encoding!=null)
{
//设置request字符编码
servletRequest.setCharacterEncoding(encoding);
//设置response字符编码
servletResponse.setContentType("text/html;charset="+encoding);
}
//传递给下一过滤器
filterChain.doFilter(servletRequest,servletResponse);
}
//销毁方法
@Override
public void destroy() {
//释放资源
this.encoding=null;
this.filterConfig=null;
}
}
2.在web.xml文件中,对过滤器进行配置。将以下代码放在web.xml文件中。
<!--设置过滤器-->
<!--声明字符编码过滤器-->
<filter>
<filter-name>example65</filter-name>
<filter-class>example65</filter-class>
<!--设置初始化参数-->
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>example65</filter-name>
<url-pattern>---</url-pattern>//在---处填入“/*”
<!--设置过滤器对应的请求方式-->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!--配置Servlet-->
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
3.通过请求过滤器进行验证。本例子中是Servlet发送中文信息进行验证。表单信息放在index.jsp文件中。
(1)修改index.jsp文件。
<%--
Created by IntelliJ IDEA.
User: yxb
Date: 2020/2/1
Time: 16:38
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=GB2312" language="java" %>
<html>
<head>
<title>字符过滤器</title>
</head>
<body>
<form action="MyServlet" method="post">
<p>
请输入你的中文名字:
<br>
<input type="text" name="name">
<input type="submit" value="提交">
</p>
</form>
</body>
</html>
(2)使用doPost()方法接收表单的请求,并将表单中的name属性输入到页面中。
具体代码如下:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class MyServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
PrintWriter out=response.getWriter();
//获取表单参数
String name = request.getParameter("name");
if(name!=null&&!name.isEmpty())
{
out.print(" 你好 "+name);
out.print("<br>欢迎来到我的主页。");
}
else{
out.print("请输入你的中文名字。");
}
out.print("<br><a href=example6-5.jsp>返回</a>");
out.flush();
out.close();
}
}
(3)结果展示
输入中文名字:
输出结果: