过滤器,用于执行过滤任务的对象,针对指定请求响应执行,通过doFilter()
方法进行过滤。常用于验证过滤、日志记录、图像转换、数据压缩、加密等方面。
生命周期
实例化 -> init()
-> doFilter()
-> destory()
,在doFilter()
方法中进行过滤判断,当无需过滤时执行chain.doFilter(request, response)
即可
使用步骤
1.创建一个类实现Filter
接口
2.重写接口中的方法,其中实现过滤功能的是doFilter()
方法
3.进行路由配置
注:
只有执行chain.doFilter(request, response)
方法,资源才能够被正常访问到
Filter路由配置
配置Filter的作用路由,可以通过两种方式进行配置:在web.xml中进行配置;通过@WebFilter
注解进行配置
1.web.xml配置
定义
通过<filter>
标签定义一个filter,并为其配置<filter-name>
和<filter-class>
映射
通过<filter-mapping>
配置映射,主要配置<filter-name>
和<url-pattern>
(要过滤的路径),其他还有:
(1)<servlet-name>
代表对指定<servlet-name>
的Servlet进行拦截
(2)<dispatcher>
代表当以何种方式去访问web资源时进行拦截,默认是REQUEST
(浏览器直接访问时过滤),还有其他参数:FORWARD
(转发请求时过滤)、ERROR
(通过异常机制调用时过滤)、INCLUDE
(通过RequestDispatcher.include()
调用时过滤)
使用举例
过滤器:
package com.servlet;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
public class FilterTest implements Filter {
public void init(FilterConfig fConfig) throws ServletException {
// 初始化
}
public FilterTest() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
boolean flag = true;
if (flag) {
//如果需要过滤,执行的语句
} else {
chain.doFilter(request, response); //执行这句说明内容通过,无需过滤
}
}
public void destroy() {
// 结束
}
}
在web.xml中配置如下:
<filter>
<filter-name>test</filter-name>
<filter-class>com.servlet.FilterTest</filter-class>
</filter>
<filter-mapping>
<filter-name>test</filter-name>
<url-pattern>/*</url-pattern> //对所有内容进行过滤
</filter-mapping>
注解配置
和Servlet的注解配置类似,举例:
@WebFilter("/*")
public class FilterTest implements Filter {
...
}
Filter调用顺序
当多个Filter对同一个资源进行拦截时,则会形成Filter链,其中调用顺序由<filter-mapping>
标签的顺序来确定,举例:
<filter>
<filter-name>FilterTest1</filter-name>
<filter-class>com.mvc.filter.FilterTest1</filter-class>
</filter>
<filter>
<filter-name>FilterTest2</filter-name>
<filter-class>com.mvc.filter.FilterTest2</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTest2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterTest1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
结果是FilterTest2先过滤,然后FilterTest1再过滤,虽然是FilterTest1先定义的,但是<filter-mapping>标签里却是FilterTest2在前,所以FilterTest2先进行过滤
FilterChain
FilterChain是Servlet提供的对象,里面提供了对某一资源的过滤请求调用链的视图,根据上面的调用顺序可以知道Filter链里由多个Filter组成,而这之间的传递连接就是通过FilterChain来实现的
FilterConfig
是Filter的配置对象,在Filter的init()
方法中就有传入该参数,主要提供了以下方法:
1.getFilterName()
:获取Filter名称
2.getInitParameter()
:获取Filter初始化参数
3.getInitParameterNames()
:获取所有参数的name
4.getServletContext()
:获取ServletContext对象
编码过滤器
对于发送过来的数据,可以通过统一设置编码,从而解决乱码问题。
实现过程
1.因为get和post方法的解决方式不一样,因此要分开设置。
2.post方法中直接通过setCharacterEncoding()
方法设置即可
3.get方法中的设置是通过getParameter()
获取值以后在通过String(byte[] bytes, String charsetName)
来设置的,所以可以通过继承该接口的一个实现类后重写getParameter()
方法,使其在获取值的过程当中自动编码,举例:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class FilterTest implements Filter {
public FilterTest() {
}
public void init(FilterConfig fConfig) throws ServletException {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if (req.getMethod().equals("POST")) { //post方法编码设置
req.setCharacterEncoding("utf-8");
chain.doFilter(req, response); //传入编码后的request对象
} else { //get方法编码设置
chain.doFilter(new ChardetSet(req), response); //传入的request对象里的getParameter方法是重写过的
}
}
}
class ChardetSet extends HttpServletRequestWrapper { //继承HttpServletRequest接口的一个实现类,这样只用重写需要的方法,而不用像继承接口那样需要把所有方法都实现
HttpServletRequest request;
public ChardetSet(HttpServletRequest request) {
super(request);
this.request = (HttpServletRequest) request;
}
public String getParameter(String name) { //重写getParameter方法
name = request.getParameter(name);
try {
return new String(name.getBytes("iso-8859-1"), "utf-8"); //解决get方法乱码
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
这里只重写了getParameter()
方法,对于多值的情况还需要去重写getParameterValues()
方法,这里仅做个示例
网友评论