概述
java过滤器是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。
可以实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等高级功能。
主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
JAVA 如何使用filter
1.实现filter接口,重写dofilter()方法.
注意事项:在JAVA的servlet不允许直接对request中的parameter直接进行修改,需要使用AMHttpServletRequestWrapper来实现对request中的parameter的修改.
import java.io.IOException;
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.http.HttpServletRequest;
/**
* @Description:
* @author: jackromer
* @version: 1.0, Dec 14, 2018
*/
public class SpecialCharactersFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {//使用filterConfig初始化filter
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest http_req = (HttpServletRequest)request;
//在JAVA的servlet不允许直接对request中的parameter直接进行修改,需要使用AMHttpServletRequestWrapper来实现对request中的parameter的修改.
AMHttpServletRequestWrapper amHttpServletRequestWrapper = new AMHttpServletRequestWrapper(http_req, http_req.getParameterMap());
Map<String,String[]> map = amHttpServletRequestWrapper.getParameterMap();
if(map.containsKey("XXX")) {
String searchKey = map.get("XXX")[0];
if (searchKey.contains("%")) {
String newSearchKey = searchKey.replaceAll("%", "\\\\%");//处理%特殊字符,对其转义用于查询数据
String newArr [] = {newSearchKey};
amHttpServletRequestWrapper.setParameter("XXX", newArr);//重设参数值
}
}
chain.doFilter(amHttpServletRequestWrapper, response);
}
/**
* @see javax.servlet.Filter#destroy()
*/
@Override
public void destroy() {
}
}
2. AMHttpServletRequestWrapper的实现
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* @Description:
* @author: zhouqiang
* @version: 1.0, Dec 14, 2018
*/
public class AMHttpServletRequestWrapper extends HttpServletRequestWrapper {
Map<String, String[]> params = null;
@SuppressWarnings({ "unchecked", "rawtypes" })
public AMHttpServletRequestWrapper(HttpServletRequest request, Map inParam) {
super(request);
params = new HashMap(inParam);
}
public void setParameter(String key, String value) {
params.put(key, new String[] { value });
}
public void setParameter(String key, String[] values) {
params.put(key, values);
}
@Override
public String getParameter(String name) {
Object v = params.get(name);
if (v == null) {
return null;
} else if (v instanceof String[]) {
String[] strArr = (String[]) v;
if (strArr.length > 0) {
return strArr[0];
} else {
return null;
}
} else {
return v.toString();
}
}
@Override
public Map<String, String[]> getParameterMap() {
return params;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Enumeration<String> getParameterNames() {
Vector l = new Vector(params.keySet());
return l.elements();
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
3.初始化filterConfig
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @Description:
* @author: zhouqiang
* @version: 1.0, Dec 14, 2018
*/
@Configuration
public class FilterConfig extends WebMvcConfigurerAdapter {
/**
* 初始化过滤器
*
* @return
* @Bean 注解必加,否则过滤器失效
*/
@Bean
public FilterRegistrationBean indexFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new SpecialCharactersFilter());
registration.addUrlPatterns("/*");
/**
* 再有一个过滤器的话,可以设置成 registration.setOrder(Integer.MAX_VALUE - 1)
* spring boot 会按照order值的大小,从小到大的顺序来依次过滤
*/
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
}
4. 使用web.xml 配置过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--配置过滤器-->
<filter>
<filter-name>SpecialCharactersFilter</filter-name>
<filter-class>com.xxx.xxx.SpecialCharactersFilter</filter-class>
</filter>
<!--映射过滤器-->
<filter-mapping>
<filter-name>SpecialCharactersFilter</filter-name>
<!--“/*”表示拦截所有的请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Filter链
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。
在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
Filter 链的使用
1.再定义一个filter
import java.io.IOException;
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.http.HttpServletRequest;
/**
* @Description:
* @author: jackromer
* @version: 1.0, Dec 14, 2018
*/
public class SpecialCharactersFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {//使用filterConfig初始化filter
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest http_req = (HttpServletRequest)request;
//do something...
chain.doFilter(amHttpServletRequestWrapper, response);
}
/**
* @see javax.servlet.Filter#destroy()
*/
@Override
public void destroy() {
}
}
2.配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>FilterTest</display-name>
<filter>
<filter-name>SpecialCharactersFilter</filter-name>
<filter-class>com.xxx.xxx.SpecialCharactersFilter</filter-class>
<init-param>
<param-name>xxx</param-name>
<param-value>xxx-value</param-value>
</init-param>
</filter>
<filter>
<filter-name>SpecialCharactersFilter2</filter-name>
<filter-class>com.xxx.xxx.SpecialCharactersFilter2</filter-class>
<init-param>
<param-name>yyy</param-name>
<param-value>yyy-value</param-value>
</init-param>
</filter>
<!-- 故意将filter-mapping倒过来写,观察顺序是和哪个标签一致 -->
<!-- filter在filter chain中的执行顺序是按照 filter-mapping中的配置顺序来执行的 -->
<filter-mapping>
<filter-name>com.xxx.xxx.SpecialCharactersFilter2</filter-name>
<!-- 只过滤根目录下go.html -->
<url-pattern>/go.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>com.xxx.xxx.SpecialCharactersFilter</filter-name>
<!-- 过滤根目录下所有资源(实验中只放了go.html) -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>go.html</welcome-file>
</welcome-file-list>
</web-app>
总结
JAVA 的filter可以非常简单的实现web服务器的过滤功能, 包括页面,参数,请求路径等等.