Filter过滤器
一、Filter简介
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
二、Filter是如何实现拦截的?
Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
- 调用目标资源之前,让一段代码执行。
- 是否调用目标资源(即是否让用户访问web资源)。
- 调用目标资源之后,让一段代码执行。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问。
三、Filter开发入门
3.1、Filter开发步骤
Filter开发分为二个步骤:
- 编写java类实现Filter接口,并实现其doFilter方法。
- 如果是配置XML, 在
web.xml
文件中使用<filter>
和<filter-mapping>
元素对编写的filter类进行注册,并设置它所能拦截的资源。如果是配置注解,在自定义的Filter类上,使用@WebFilter
直接,最关键的属性是:filterName
,urlPatterns
与initParams
3.2、IDEA开发Filter流程
选择创建Filter
创建Filter类名以及配置方式
Filter类代码
package com.yingside.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(filterName = "TestFilterDemo",
urlPatterns = "/*", //通配符,表示对根目录下所有资源过滤
initParams = {
@WebInitParam(name = "charset", value = "utf-8") //这里可以放一些初始化的参数
}
)
public class TestFilterDemo implements Filter {
public void destroy() {
System.out.println("TestFilterDemo.destroy ---- 容器销毁时调用");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("TestFilterDemo.doFilter ---- 过滤前");
chain.doFilter(req, resp);
System.out.println("TestFilterDemo.doFilter ---- 过滤后");
}
public void init(FilterConfig config) throws ServletException {
System.out.println("TestFilterDemo.init ---- 初始化Filter时调用,单例模式,只会调用一次");
}
}
使用web.xml配置
注意:注解和web.xml选择一种方式配置就可以了,不要两个都配置
在配置文件中的配置如下:
<!--配置过滤器-->
<filter>
<filter-name>TestFilterDemo</filter-name>
<filter-class>com.yingside.filter.TestFilterDemo</filter-class>
<!--配置TestFilterDemo过滤器的初始化参数-->
<init-param>
<description>配置TestFilterDemo过滤器的初始化参数</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<!--映射过滤器-->
<filter-mapping>
<filter-name>TestFilterDemo</filter-name>
<!--“/*”表示拦截所有的请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
这样,访问界面上的所有请求,都会触发filter拦截,可以自定义一个Servlet页面做一下测试,甚至是静态页面的请求也会触发过滤器
这是一个简单的配置流程,那么现在我们来看一个Filter过滤器的实际应用
四、Filter统一过滤字符编码
每次建一个Servlet都需要去过滤request Post,Get请求的一些字符编码,以及Response响应的编码,能不能一次性解决这个问题,Filter过滤器就能帮我们解决这个问题
过滤器Filter:
package com.yingside.filter;
import com.yingside.wrapper.CharacterEncodingRequest;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CharacterEncodingFilter",
urlPatterns = "/*",
initParams = {
@WebInitParam(name = "charset", value = "utf-8")
}
)
public class CharacterEncodingFilter implements Filter {
private FilterConfig config;
private String defaultCharset = "UTF-8";
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//将请求和相应转换为HttpServletRequest,HttpServletResponse
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//读取初始化的参数
String charset = config.getInitParameter("charset");
if(charset==null){
charset = defaultCharset;
}
//设置Post请求编码
request.setCharacterEncoding(charset);
//设置响应编码
response.setContentType("text/html;charset="+charset);
//但是get请求的乱码问题,需要具体参数的转换
//这里不能直接获取参数,我们也不知道到底是哪些参数需要转换
//但是,java提供Request对象的装饰模式,让我们可以自定义加强Request对象
//我们可以自己继承这个类增强Request对象,
//在这个装饰模式的类中,我们可以加强getParameter(name)这个方法
CharacterEncodingRequest characterEncodingRequest = new CharacterEncodingRequest(request);
//注意这里传入过滤链中的request是我们加强过的request了
chain.doFilter(characterEncodingRequest, resp);
}
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
}
CharacterEncodingRequest类:
package com.yingside.wrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.UnsupportedEncodingException;
public class CharacterEncodingRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
public CharacterEncodingRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
//获取参数的值
String value = this.request.getParameter(name);
if (value == null) {
return null;
}
//如果不是get请求,直接返回参数的值
if(!this.request.getMethod().equalsIgnoreCase("get")){
return value;
}
else{
try {
value = new String(value.getBytes("ISO8859-1"),"UTF-8");
return value;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
}
Comments