Javaweb-过滤器详解(实例)
一.为什么要用过滤器??
想象已经开发好应用程序的主要商务功能了,但现在有几个需求出现:
(1)针对所有的Servlet,产品经理想要了解从请求到响应之间的时间差。
(2)针对某些特定的页面,客户希望只有特定几个用户才可以浏览。
(3)基于安全方面的考量,用户输入的特定字符必须过滤并替换为无害的字符。
(4)请求与响应的编码从Big5改用UTF-8.
以第一个需求而言,也许你的直觉就是,打开每个Servlet,在doXXX开头与结
尾取得系统时间,计算时间差,但如果页面有上百个或上千个,怎么完成这些需求?
如果产品经理在你完成需求后,又要求拿掉计算时间差的功能,你怎么办?
我们发现
(1)运行Servlet的service()方法“前”,记录起始时间,Servlet的service()方法
运行“后”,记录结束时间并计算时间差。
(2)运行Servlet的service()方法“前”,验证是否为允许的用户。
(3) 运行Servlet的service()方法 “前”,对请求参数进行字符过滤与替换。
(4)运行Servlet的service()方法“前”,对请求与响应对象设置编码.
经过以上分析,可以发现这些需求,可以在真正运行Servlet的service()方法“前”
那么只要我们在这个前的地方设置一个一个像筛子一样的东西进行过滤,那就可以了
二.过滤器可以用在哪里
- 进行service操作前,对request进行操作
- chain.doFilter()//这个过程是必须调用的,以堆栈的形式回归上来,最深的地方就是service()方法
- 在service后,对response进行处理或者压缩。
三.举例子,利用请求封装器实现字符的重新编码
这是一个简单的Filter,过滤所有的请求
@WebFilter (
urlPatterns = { "/*" },
设置过滤器初始参数
initParams = {
@WebInitParam (name = "ENCODING", value = "UTF-8")
})
public class EncodingFilter implements Filter {
private String ENCODING;
public void init (FilterConfig config) throws ServletException {
ENCODING = config.getInitParameter ("ENCODING");//读取初始参数
}
public void doFilter (ServletRequest request,ServletResponse response, FilterChain chain)throws I0Exception, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if ("GET". equals (req. getMethod())) {
req = new EncodingWrapper (req, ENCODING); //GET 请求时创建封装器!!!这是最关键的地方
else {
req. setCharacterEncoding (ENCODING) ;
chain. doFilter (req, response); //调用FiterChain的doFilter()
}
public void destroy() {}
}
包装类HttpServletRequestWrapper,继承了这个类,就能实现绝大部分的东西。
public class EncodingWrapper extends HttpServletRequestWrapper{
private String ENCODING;
public EncodingWrapper (HttpServletRequest request, String ENCODING) {
super (request);+-❷ 必须调用父类构造器,传入HttpServletRequest实例
this . ENCODING = ENCODING;
}
@Override
public String getParameter (String name) {//重新定义getParameter ()方法
String value = getRequest().getParameter(name) ;
if(value != nu1l) {
try {
byte[] b = value. getBytes ("IS0-8859-1");//将取得的请求参数
value = new String (b, ENCODING);
值进行编码转换
} catch (UnsupportedEncodingException e) {
throw new RuntimeException (e) ;
}
return value;
}
}
}
四.利用filter实现运行了多少秒
@WebFilter (filterName "per formance", ur1Patterns={"/*"})//使用@WebFilter 标注
public class PerformanceFilter implements Filter {//实现Filter接口
private FilterConfig config;
@Override
public void init (FilterConfig config) throws ServletException {
this.config = config;
@Override
public void doFilter (ServletRequest request,ServletResponse response,FilterChain chain)throws IOException, ServletException {
long begin = System. currentTimeMillis();
chain.doFilter (request,response) ;//这一步其实是个递归的过程,一步步往下走,最后调用Service的操作。
config.getServletContext().log ("Request process in”+
(System.currentTimeMillis() - begin) +”milliseconds") ;
}//
@Override
public void destroy() {}
}
五.过滤器的触发时机
触发时机默认是由浏览器发出请求,如果是通过Requestdispatcher的forward以及include,则要在标签额外进行配置。
@WebFilter (
filterName="some,
urlPatterns= {"/some"},
dispatche rTypes={
DispatcherType.FORIARD,
DispatcherType.INCLUDE,
DispatcherType.REQUEST,
DispatcherType.ERROR,
DispatchorType.ASYNC
}
)
如果不设置任何dispatcherTypes, 则默认为BQUEST。 rOROARD 就是指通过Request-
Dispatcher的forward ()而来的请求可以套用过滤器INCLUDE 就是指通过RequestDispatcher
的include()而来的请求可以套用过滤器。ERROR是指由容器处理例外而转发过来的请求
可以触发过滤器。ASYNC是指异步处理的请求可以触发过滤器。