网站开发过程中,一般都会采用前端发送网络请求,后端响应的模式,也即是 C/S 模式。通过 Filter 能够在 C/S 中建立一道闸门,拦截前端发送的请求。拦截后可以对请求进行预处理,然后在交个服务端进行处理。 Filter 在很多歌场景下都很有用。
Filter 生命周期
建立自己的 Filter
类 MyFilter
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.print("****** init ******");
}
//每次过滤都会执行的方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.print("****** doFilter2 ******");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.print("****** destroy ******");
}
}
能够看到 MyFilter
中需要实现的 3 个方法 init、doFilter 和 destroy。 init
方法在 web 网站初始化的时候调用;doFilter
在被过滤的对象执行时调用;destroy
在 MyFilter 销毁时调用。
Filter 在 web 网站的应用
- 通过 Filter 统一全站响应的数据编码格式
在web.xml
文件中,将MyFilter
设置为拦截全站所有的网络请求:
<filter>
<filter-name>Filter1</filter-name>
<filter-class>filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在 MyFilter
的 doFilter
方法中设置数据编码格式:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)servletResponse;
servletResponse.setContentType("text/html;charset=" + encoding);
filterChain.doFilter(servletRequest, servletResponse);
}
- 控制浏览器缓存
在 Filter 中针对图片设置一定时间的缓存时间,避免反复加载图片资源消耗带宽。
在web.xml
中设置MyFilter
拦截图片资源的网络请求:
<filter>
<filter-name>Filter1</filter-name>
<filter-class>filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>*.png</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.gif</url-pattern>
<url-pattern>*.bmp</url-pattern>
</filter-mapping>
在 MyFilter
的 doFilter
方法中设置数据编码格式:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)servletResponse;
HttpServletRequest req = (HttpServletRequest)servletRequest;
//不缓存
/*res.setHeader("cache-control", "no-cache");
res.setHeader("pragma", "no-cache");
res.setDateHeader("expires", 0);*/
//缓存1小时
res.setDateHeader("expires", System.currentTimeMillis() + 1000l*60*60);
filterChain.doFilter(servletRequest, servletResponse);
}
- 解决全站乱码问题
get/post 请求中,参数默认采用ISO8859-1
编码格式,会造成中文无法正常显示的错误。需要将请求参数改为utf-8
格式,才能正常显示中文字符。
使用MyFilter
拦截所有网络请求,对Request
采用包装类MyHttpServletRequestWrapper
拦截调用的方法,重写getParameterMap
方法。当在 request 中调用getParameter
方法时,就会调用包装类中的方法,对中文进行自动转化。
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)servletRequest;
HttpServletResponse res = (HttpServletResponse)servletResponse;
MyHttpServletRequestWrapper myRequest = new MyHttpServletRequestWrapper(req);
filterChain.doFilter(myRequest,res);
}
@Override
public void destroy() {
}
}
class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{
private HttpServletRequest request;
public MyHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
Map<String, String[]> map = getParameterMap();
String[] values = map.get(name);
if (values != null){
return values[0];
}else {
return null;
}
}
//Map 方法是基础方法
private boolean hasEncoding = false;//防止反复解码;
@Override
public Map<String, String[]> getParameterMap() {
String method = request.getMethod();
if ("post".equalsIgnoreCase("method")){
try{
request.setCharacterEncoding("utf-8");
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
}else {
Map<String, String[]> map = request.getParameterMap();
Set<String> keys = map.keySet();
if (!hasEncoding){
hasEncoding = true;
for (String key: keys){
String[] values = map.get(key);
for(int i = 0; i < values.length; i++){
try {
values[i] = new String(values[i].getBytes("ISO8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
}
return super.getParameterMap();
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> map = getParameterMap();
String[] values = map.get(name);
return values;
}
}
总结
Filter 相当于在前端的请求和后台服务间设立的一道大门,通过该大门可以实现请求的统一处理、个别请求和定制化处理和请求的放行和拒绝等功能。灵活使用 Filter
能够减少重复代码,加快网站开发效率。
网友评论