Filter可以用于以下方面:
记录request和response的log进行认证和授权进行压缩和加压,非HTTPS的加密和解密错误处理。对于tomcat,出现错误通常会给出一个500的页面,还有错误诊断信息,对于一个公众服务,这些诊断信息可能会向黑客泄漏一些敏感信息,通过Filter,我们可以用try{}catch(){},将这些诊断信息记录在log中,而向公众展现一个通用的错误页面。Filter可以在Servlet执行前以及执行后进行相应的动作,而不仅仅在执行前。
和定义Servlet相似。在匹配条件中,可以指定url,可以指定servlet名字,也可以指定分派方式dispatcher。dispatcher有以下之中模式:
REQUEST:普通模式,来自客户端的请求FORWARD:通过RequestDispatcher的forward(),或者<jsp:forward>INCLUDE:通过RequestDispatcher的include(),或者<jsp:include>ERROR:请求错误页面来处理HTTP错误,例如404,500ASYNC:来自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的主要问题是无法确定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" ); } }前面我们了解如何通过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相关文章