过滤器是指拦截请求,并对传给被请求资源的ServletRequest或ServletResponse进行处理的一个对象。过滤器可以用于登录、加密和解密、会话检查、图片转换等等。过滤器可以配置为拦截一个或多个资源。
(一)过滤器的用法
1)implements Filter
2)实现Filter的destroy()、init(FilterConfig filterConfig)、doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain)
3)配置过滤器,配置过滤器有2种方式,具体的下面介绍。
(二)实例代码
package test.com.servlet.filter; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; 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.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; import javax.servlet.http.HttpServletRequest; @WebFilter(filterName="LoggingFilter",urlPatterns={"/*"}, initParams = { @WebInitParam(name="logFileName",value="log.txt"), @WebInitParam(name="prefix",value="URI:") }) public class LoggingFilter implements Filter{ private PrintWriter logger; private String prefix; public void destroy() { System.out.println("destroying filter"); if(logger != null){ logger.close(); } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { System.out.println("LoggingFilter.doFilter"); HttpServletRequest httpServletRequest = (HttpServletRequest) request; logger.println(new Date() + " " + prefix + httpServletRequest.getRequestURL()); logger.flush(); //这一步是必须的,不然请求就卡在这了。 filterChain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { prefix = filterConfig.getInitParameter("prefix"); String logFileName = filterConfig.getInitParameter("logFileName"); String appPath = filterConfig.getServletContext().getRealPath("/"); System.out.println("FilterName :" + filterConfig.getFilterName()); System.out.println("logFileName:" + logFileName + ",appPath:" + appPath); try { logger = new PrintWriter(new File(appPath,logFileName)); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
(三)配置方式
1)注解的方式
@WebFilter(filterName="LoggingFilter",urlPatterns={"/*"}, initParams = { @WebInitParam(name="logFileName",value="log.txt"), @WebInitParam(name="prefix",value="URI:") })
2)配置文件的方式(web.xml)
<filter> <filter-name>LoggingFilter</filter-name> <filter-class>test.com.servlet.filter.LoggingFilter</filter-class> <init-param> <param-name>logFileName</param-name> <param-value>log.txt</param-value> </init-param> <init-param> <param-name>prefix</param-name> <param-value>URI:</param-value> </init-param> </filter> <filter-mapping> <filter-name>LoggingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
这里的两种方式不同于servlet的配置方式,servlet的配置无所谓注解还是xml配置。过滤器要是单独的也是无所谓那种方式,但是有关联的则需要控制顺序。比如来了个工人,要安排他干活,我要先给他工具,再安排他工作。总不能让他先工作再给工具吧。这就需要控制顺序。
控制顺序只能在xml文件配置中实现。
<filter> <filter-name>LoggingFilter</filter-name> <filter-class>test.com.servlet.filter.LoggingFilter</filter-class> <init-param> <param-name>logFileName</param-name> <param-value>log.txt</param-value> </init-param> <init-param> <param-name>prefix</param-name> <param-value>URI:</param-value> </init-param> </filter> <filter-mapping> <filter-name>LoggingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>TestChainFilter</filter-name> <filter-class>test.com.servlet.filter.TestChainFilter</filter-class> </filter> <filter-mapping> <filter-name>TestChainFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
按上面的配置,我将先经过LoggingFilter过滤再通过TestChainFilter处理。
(四)注意点
在编写过滤器时个人觉得有一点非常需要注意,就是在写public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain)方法时,方法的最后一定要以filterChain.doFilter(request, response);结尾,如果没写则请求就会卡在那,不会调用请求!
(五)声明周期
1、项目启动时,servlet容器就会调用init方法。
2、每次调用过滤器时调用doFilter方法。
3、在服务器停止的时候,由servlet容器调用destory()方法。