Java Web 过滤器
什么是过滤器(Filter)
过滤器:任何实现了Filter接口的类称为过滤器类。
实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理
通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理
应用场景
- 统一设置编码格式
- 访问权限控制
- 敏感字符过滤等(并未尝试)
思维导图
注:在Filter中只有执行 chain.dofilter(request,response) 才算一个过滤,也只有执行此代码后才会进行放行以执行dofilter()以后的代码。
创建Filter
下面我们来创建一个Filter类。
1. 创建一个类
包名和类名
2. 实现接口Filter
3. 鼠标悬浮在类名上,点击Add unimplemented methods
自动生成三个方法
public class CharacterEncodedFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
}
public void destroy() {
}
}
我们需要用到doFilter()方法。
4. 在web.xml中配置Filter
<filter>
<filter-name>web.xml中的名称(两个要像同)比如这里为:ABC</filter-name>
<filter-class>Filter类全限定类名</filter-class>
</filter>
<filter-mapping>
<filter-name>web.xml中的名称(两个要像同)那么这里也为:ABC</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>
Filter接口中doFilter方法
doFilter方法最为关键,它有三个参数:
参数1 : ServletRequest request
参数2 : ServletResponse response
参数3 : FilterChain chain 过滤器链
过滤器对象由容器来实例化, 当有请求请求该过滤器时,容器会调用doFilter方法来处理请求,并将ServletRequest接口、ServletResponse接口、FilterChain接口的实现类对象传入参数。
请求和响应对象真实类型是HttpServletRequest和HttpServletResponse
案例----统一设置编码格式
在Java Web项目中一定会使用到Servlet类,但Servlet类会需要我们对request和response中的字符集编码进行配置,这时如果Servlet类过多,字符集编码发生变化时修改起码会很麻烦。所以可以使用拦截,将字符集编码
配置等工作我们可以放到Filter类中来实现。
- 根据上面的步骤,我们创建了一个Filter类,这时候我们需要用到doFilter方法,在方法中编写字符集编码配置代码。
代码如下:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//FilterChain是过滤器链
//HttpServletRequest 是 ServletRequest接口的子接口,HttpServletResponse同理
//如想使用子接口独有的方法,就要将ServletRequest强转为HttpServletRequest
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//因在web.xml修改过字符编码,所以只需修改POST的字符集
req.setCharacterEncoding("utf-8");
//放行 doFilter()方法,可以将请求和响应对象放行
chain.doFilter(req, resp);
/*
* 若未在web.xml修改过字符编码,可以使用以下方法
*
* 获取到提交的方式
* String method = request.getMethod();
*
* 修改POST的字符集
* req.setCharacterEncoding("utf-8");
*
* 获取参数
* String uname = req.getParameter("uname");
*
* 判断是否是GET方式提交
* if("GET".equals(method)) {
* 修改该参数的字符编码
* uname = new String(uname.getBytes("ISO-8859-1"), "utf-8");
* }
*
* 将修改过的参数存入域对象中
* req.setAttribute("uname", uname);
*
* //放行 doFilter()方法,可以将请求和响应对象放行
* chain.doFilter(req, resp);
*
* 后续如想显示、存入可以使用域对象中的get方法获取值
*
* 但是这个方法并不好,如获取的参数很多,将非常麻烦
*
*/
}
- 配置Filter,在web.xml
<filter>
<filter-name>CharacterEncodedFilter</filter-name>
<filter-class>com.apps.web.filter.CharacterEncodedFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodedFilter</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>
常用配置项:
filter-class 指定的Filter类全限定类名
url-pattern 配置要拦截的资源
A. 以指定资源匹配。例如"/index.jsp"
B. 以目录匹配。例如"/servlet/"
C. 以后缀名匹配,例如".jsp"
D. 通配符,拦截所有web资源。"/*"
我这里的:
<url-pattern>/register</url-pattern>
指向的是Servlet映射名url-pattern,因为我们要拦截这个Servlet类,以目录匹配。可以看Servlet在web.xml中的代码
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.apps.web.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>
- 这时候,在我们访问/register时,便会被Filter类CharacterEncodedFilter拦截,修改过字符编码后,才会放行到Servlet类。