Filter过滤器介绍&解决get/post乱码过滤器
什么是Filter
- Filter及其作用介绍
Filter是sun公司中servlet2.3后增加的一个新功能.
Servlet规范中三个技术 Servlet Listener Filter
在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器
通过Filter可以拦***问web资源的请求与响应操作(get/post).
WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。 - Filter API介绍
Filter是javax.servlet包下的一个接口主要有以下三个方法- void destroy()
- void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
- void init(FilterConfig filterConfig)
Filter入门
- 创建步骤介绍
1. 创建一个类实现javax.servlet.Filter接口
2. 得写接口方法
3. 在web.xml文件中配置Filter - Filter在web.xml文件中配置的目的:
1. 配置拦截什么样的资源。
2. Filter初始化
<filter>
<filter-name>demo1Filter</filter-name>
<filter-class>cn.itcast.web.filter.Demo1Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1Filter</filter-name>
<url-pattern>/demo1</url-pattern>
</filter-mapping>
- 演示Filter的拦截操作
注意:在Filter的doFilter方法内如果没有执行chain.doFilter(request,response),那么资源是不会被访问到的
- FilterChain功能介绍
FilterChain 是 servlet 容器为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图。过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。
void doFilter(ServletRequest request,ServletResponse response,FilterChain chain){
chain.doFilter(request,response);
}
三、Filter链与生命周期
- Filter链介绍
多个Filter对同一个资源进行了拦截,那么当我们在开始的Filter中执行
chain.doFilter(request,response)时,是访问下一下Filter,直到最后一个Filter执行
时,它后面没有了Filter,才会访问web资源。 - 关于多个FIlter的访问顺序问题
如果有多个Filter形成了Filter链,那么它们的执行顺序是怎样确定的?
它们的执行顺序取决于在web.xml文件中配置的先后顺序。 - Filter生命周期
当服务器启动,会创建Filter对象,并调用init方法,只调用一次.
当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,
这个方法是真正拦截操作的方法.
当服务器关闭时,会调用Filter的destroy方法来进行销毁操作.
四、FilterConfig介绍
- FilterConfig介绍
- FilterConfig功能介绍
在Filter中的init方法上有一个参数叫FilterConfig
FilterConfig是Filter的配置对象
它的作用:
1.获取Filter的名称
2.获取初始化参数
3.获取ServletContext对象 - FilterConfig常用API
五、Filter配置详解
- Filter基本配置介绍
<filter>
<filter-name>filter名称</filter-name>
<filter-class>filter类全名</filter-class>
</filter>
<filter-mapping>
<filter-name>filter名称</filter-name>
<url-pattern>映射路径</url-pattern>
</filter-mapping>
- 关于url-pattern配置
1.完全匹配
要求必须以"/“开始.
2.目录匹配
要求必须以”/"开始,以结束.
3.扩展名匹配
不能以"/"开始,以.xxx结束. - 关于servlet-name配置
针对于servlet拦截的配置 配置
在Filter中它的配置项上有一个标签
它用于设置当前Filter拦截哪一个servlet。
是通过servlet的name来确定的。 - 关于dispatcher配置
可以取的值有 REQUEST FORWARD ERROR INCLUDE
它的作用是:当以什么方式去访问web资源时,进行拦截操作.
1.REQUEST 当是从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置的 它也是默认值
2.FORWARD 它描述的是请求转发的拦截方式配置
3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
4.INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用
六、解决get/post乱码过滤器
package com.book.web.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
@WebFilter(filterName="/EncodingFilter",urlPatterns={"/encodingFilter"})
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//处理请求乱码
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletRequest myRequest = new MyRequest(httpServletRequest);
//处理响应代码
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
class MyRequest extends HttpServletRequestWrapper{
//自定义request对象
private HttpServletRequest request;
private boolean hasEncode;
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
//对所需方法进行增强,进行覆盖
@Override
public Map getParameterMap() {
//获得请求方式get/post
String method = request.getMethod();
if(method.equalsIgnoreCase("post")){
try {
//处理post乱码
request.setCharacterEncoding("utf-8");
return super.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}else if(method.equalsIgnoreCase("get")){
Map<String, String[]> parameterMap = request.getParameterMap();
if(!hasEncode){//确保get手动编码只进行一次
for (String parameterName : parameterMap.keySet()){
String[] values = parameterMap.get(parameterName);
if(values != null){
for (int i = 0; i < values.length; i++) {
try {
values[i] =
new String(values[i].getBytes("IOS-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回参数的第一个值
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}