Java for Web学习笔记(三九):Filter(1)用途、定义和顺序

Filter的用途

Filter可以用于以下方面:

  1. 记录request和response的log
  2. 进行认证和授权
  3. 进行压缩和加压,非HTTPS的加密和解密
  4. 错误处理。对于tomcat,出现错误通常会给出一个500的页面,还有错误诊断信息,对于一个公众服务,这些诊断信息可能会向黑客泄漏一些敏感信息,通过Filter,我们可以用try{}catch(){},将这些诊断信息记录在log中,而向公众展现一个通用的错误页面。

Filter可以在Servlet执行前以及执行后进行相应的动作,而不仅仅在执行前。

定义Filter

通过web.xml定义

和定义Servlet相似。在匹配条件中,可以指定url,可以指定servlet名字,也可以指定分派方式dispatcher。dispatcher有以下之中模式:

  1. REQUEST:普通模式,来自客户端的请求
  2. FORWARD:通过RequestDispatcher的forward(),或者<jsp:forward>
  3. INCLUDE:通过RequestDispatcher的include(),或者<jsp:include>
  4. ERROR:请求错误页面来处理HTTP错误,例如404,500
  5. ASYNC:来自AsyncContext的异步请求
<filter>
  <filter-name>myFilter</filter-name>
  <filter-class>com.abc.MyFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>myFilter</filter-name>
  <url-pattern>/foo</url-pattern>
  <url-pattern>/bar/*</url-pattern>
  <servlet-name>myServlet</servlet-name>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>ASYNC</dispatcher>
</filter-mapping>

如果没有指定dispacher,缺省为REQUEST。

Filter的init()将在web app启动时执行,在ServletContextListeners的初始化之后,执行的顺序按web.xml中<filter>定义的顺序。

使用Annotation定义

@WebFilter(
    filterName = "myFilter",
    urlPatterns = { "/foo", "/bar/*" },
    servletNames = { "myServlet" },
    dispatcherTypes = { DispatcherType.REQUEST, DispatcherType.ASYNC }
)
public class MyFilter implements Filter{
    ... ...
}

使用annotation的主要问题是无法确定filter的执行顺序,通常只在单个filter的请求下使用。但是,基于某些原因,例如我们需要通过ProGuard进行扰码,不适用web.xml的定义方式,我们还可以在代码中进行设定。在大型的web app中很少使用annotation来定义,一般采用部署描述(web.xml)或/和代码定义。

在代码中定义

前面提到filter的初始化在ServletContextListener的初始化之后执行,因此定义filter,需要在ServletContextListener的初始化过程中定义,还可以在ServletContainerInitializer的onStartup()中定义。

@WebListener
public class GlobalLisener implements ServletContextListener {
    ......
    public void contextInitialized(ServletContextEvent event)  { 
        ServletContext context = event.getServletContext();
        //【1】通过addFilter()来顺序添加filter
        FilterRegistration.Dynamic registration = context.addFilter("myFilter", new MyFilter());
        //【2】设置filter的匹配
        //  -- 第一个参数为null,则是缺省的REQUEST模式
        //  -- 第二个参数false表明在代码设置的filter先于web.xml中设置的filter,true则是先web.xml定义的filter后代码设置的。
        registration.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC),false, "/foo", "/bar/*" );
        registration.addMappingForServletNames( EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC),false, "myServlet" );
    }	
}

Filter的顺序

前面我们了解如何通过web.xml和代码设定filter的优先顺序。filter可以通过url或者servlet名字进行匹配。在实际的匹配中,先执行满足url匹配的filter,如果有多个,则按filter的优先顺序,接着执行满足servlet名字匹配的filter,如果有多个,则按filter的优先顺序。例:FilterA优先于filterB,对于某个http请求,filterA是serveltName匹配,filterB是url匹配,则先执行filterB。


相关链接: 我的Professional Java for Web Applications相关文章


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值