[关闭]
@yangjy 2015-01-08T16:51:19.000000Z 字数 4299 阅读 1252

Servlet过滤器

过滤器 java Servlet


Servlet过滤器是服务器与客户端请求与响应的中间层组件,在实际项目开发中Servlet过滤器主要用于对浏览器的请求进行过滤处理,将过滤后的请求转给下一资源。其实,Servlet过滤器与Servlet十分相似,只是多了一个具有拦截浏览器请求的功能。过滤器可以改变请求的内容来满足客户的需求。

开发一个过滤器必须实现Java定义好的javax.servlet.Filter接口:
这一接口含有三个过滤器必须执行的方法:

  • doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。同样也是上层过滤器调用的方法。引入的FilterChain对象提供了后续过滤器所要调用的信息。如果该过滤器是过滤器链中的最后一个过滤器,则将请求交给被请求资源。也可以直接给客户端返回响应信息。
  • init(FilterConfig):由Web容器来调用完成过滤器的初始化工作。它保证了在第一次doFilter()调用前由容器调用。能获取在 web.xml 文件中指定的初始化参数。
  • destroy():由Web容器来调用来释放资源,doFilter()中的所有活动都被该实例终止后,调用该方法。

1.字符编码过滤器

在编写Web程序时,经常出现乱码现象,本实例使用Servlet过滤器解决乱码问题。

代码

  1. public void destroy() {
  2. }
  3. public void doFilter(ServletRequest request, ServletResponse response,
  4. FilterChain chain) throws IOException, ServletException {
  5. this.request = (HttpServletRequest) request;
  6. this.response = (HttpServletResponse) response;
  7. charset = filterConfig.getInitParameter("charset");
  8. System.out.println("ConfigFilter " + charset);
  9. request.setCharacterEncoding(charset);
  10. response.setCharacterEncoding(charset);
  11. chain.doFilter(request, response);//请求转发
  12. }
  13. public void init(FilterConfig filterConfig) throws ServletException {
  14. this.filterConfig = filterConfig;//从Web务器获取过滤器配置对象
  15. }

过滤器开发完成后还需要在web.xml中进行配置。

代码演示:web.xml 中加入Filter配置

  1. <filter>
  2. <filter-name>ConfigFilter</filter-name>
  3. <filter-class>com.filter.ConfigFilter</filter-class>
  4. <init-param>
  5. <param-name>charset</param-name>
  6. <param-value>UTF-8</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>ConfigFilter</filter-name>
  11. <url-pattern>/FilterServlet</url-pattern>
  12. </filter-mapping>

解析

  1. <filter>节点描述该Filter对应的类是哪一个。写明具体路径
  2. <filter-mapping>中的<filter-name>必须和<filter>节点中的<filter-name>值相同,<init-param> 是Filter的参数。获取该参数的方式为:
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. charset=filterConfig.getInitParameter("charset"); }

2.防盗链过滤器

  • 防止通过其它URL地址直接访问本站资源。当URL地址不是本站地址时,在网页中显示错误信息。

代码演示

  1. public void destroy() {
  2. }
  3. public void doFilter(ServletRequest req, ServletResponse resp,
  4. FilterChain chain) throws IOException, ServletException {
  5. HttpServletRequest request = (HttpServletRequest) req;
  6. HttpServletResponse response = (HttpServletResponse) resp;
  7. String imurl = request.getRemoteAddr();
  8. System.out.println("request.getServerName() " + request.getServerName());
  9. System.out.println("imurl :" + imurl);
  10. if(imurl == null || !imurl.contains(request.getServerName())){
  11. request.getRequestDispatcher("../error.jsp").forward(request, response);
  12. }else{
  13. chain.doFilter(request, response);
  14. }
  15. }
  16. public void init(FilterConfig chain) throws ServletException {
  17. }

3.日志记录过滤器

在实际的项目开发过程中,经常需要在项目运行时记录并在控制台输出运行时的日志信息,便于查看运行状况。

  1. private Log log = LogFactory.getLog(this.getClass());
  2. private String filterName;
  3. public void destroy() {
  4. }
  5. public void doFilter(ServletRequest req, ServletResponse resp,
  6. FilterChain chain) throws IOException, ServletException {
  7. HttpServletRequest request = (HttpServletRequest) req;
  8. HttpServletResponse response = (HttpServletResponse) resp;
  9. long startTime = System.currentTimeMillis(); //运行前的时间
  10. String requestURI = request.getRequestURI(); //获取访问的URI
  11. //所有的地址栏信息
  12. requestURI = request.getQueryString() == null ? requestURI:(requestURI+ "?" +request.getQueryString());
  13. chain.doFilter(request, response);
  14. long endTime = System.currentTimeMillis();
  15. log.info(request.getRemoteAddr() + " 访问了 " + requestURI + ",总用时 " + (endTime-startTime) + " 毫秒。");
  16. log.hashCode();
  17. }
  18. public void init(FilterConfig chain) throws ServletException {
  19. filterName = chain.getFilterName();//获取Filter的name,启动Filter
  20. log.info("****** 启动 Filter:" + filterName);
  21. }

Filter日志最大的优点在于可拆卸性,当不需要记录日志信息功能时,只需要将Filter配置注释掉即可。

4.监控网站访问量过滤器

Servlet过滤器可以对用户提交的数据或服务器返回的数据进行更改。任何到达服务器的请求都会首先经过过滤器的处理。本实例应用过滤器的这个特点编写一个用于访问量统计的过滤器。

代码演示

  1. private static int num = 0;//定义全局变量
  2. public synchronized void doFilter(ServletRequest request, ServletResponse response,
  3. FilterChain chain) throws IOException, ServletException {
  4. this.num++;
  5. request.setAttribute("num", String.valueOf(num));
  6. chain.doFilter(request, response);
  7. }
  8. public void init(FilterConfig filterConfig) throws ServletException {
  9. }

在WEB开发中常见的应用过滤器的地方:

  • 异常捕获
  • 对用户的身份进行验证
  • 对用户发送的数据进行过滤和替换
  • 监控网站流量
  • 防止页面缓存
  • 对请求和相应加密处理

指定过滤器关联的URL样式。

url-pattern主要有四种匹配方式

  • 精确匹配,就是填写jsp或Servlet等需要过滤的请求的具体地址,例如:/Filter/TestFilter
  • 扩展匹配,由“*”号和扩展名组成,例如*.jsp
  • 路径前缀匹配,包含一个目录和一个/* 例如:/Servlet/*指的是对Servlet目录下的所有资源进行过滤
  • 全部匹配,使用/*,指的是对所有资源都过滤

使用Filter的好处:

在Filter执行的整个过程中客户端和目标资源是不知道过滤器的存在的。Filter提供的是一种声明式的服务,即在不用在原程序上做任何修改,只需要编写Filter,原程序想用Filter,只需要在XML文件中声明一下即可。他具有可插拔的能力,用的时候配上web.XML,不用的时候只需要修改web.xml,对整个系统没有影响,这种声明式的服务非常方便,也非常强大。
其次,使用Filter进行控制业务也非常方便,比如验证用户是否登录,是否有操作权限,判断Session,字符集等,放到Filter里,可以省去大量重复的代码和繁琐的控制。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注