Filter过滤器

架构师 来源:myflyingangel2016 275℃ 0评论

源码示例:

package com.ucenter.filter;
import java.io.IOException;


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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/*
 * 登录过滤器,必须登录才能访问,否则全部转发到登录页面
 */
public class LoginFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {


    }


    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // 获得在下面代码中要用的request,response,session对象
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;
        HttpSession session = servletRequest.getSession();
        
        // 获得用户请求的URI
        String path = servletRequest.getRequestURI();
        
        // 从session里去用户信息
        Integer userID = (Integer) session.getAttribute("userID");


        /*创建类Constants.java,里面写的是无需过滤的页面
        for (int i = 0; i < Constants.NoFilter_Pages.length; i++) {


            if (path.indexOf(Constants.NoFilter_Pages[i]) > -1) {
                chain.doFilter(servletRequest, servletResponse);
                return;
            }
        }*/
        
        // 登陆页面无需过滤 unlock verify superverify sendmessage
if (path.indexOf("unlockSec") > -1 || path.indexOf("isUserExist") > -1 || path.indexOf("sendmessage") > -1
|| path.indexOf("checkuserphone") > -1 || path.indexOf("finduser") > -1
|| path.indexOf("modifypwd") > -1 || path.indexOf("resetpwd") > -1 || path.indexOf("regist") > -1
|| path.indexOf("addlog") > -1 || path.indexOf("login") > -1 || path.indexOf("css") > -1
| path.indexOf("font") > -1 || path.indexOf("js") > -1 || path.indexOf("images") > -1) {
chain.doFilter(servletRequest, servletResponse);
return;
}


        // 判断如果没有取到员工信息,就跳转到登陆页面
        if (userID == null || "".equals(userID)) {
            // 跳转到登陆页面
            servletResponse.sendRedirect("login");
        } else {
            // 已经登陆,继续此次请求
            chain.doFilter(request, response);
        }


    }
    @Override
    public void destroy() {


    }


}


web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>kbs-ucenter</display-name>
 
    <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>


<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<!-- 防止spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>


<servlet>
<description>spring mvc servlet</description>
<servlet-name>kbs-ucenter</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>kbs-ucenter</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置登陆过滤器 -->
<filter>
       <filter-name>login</filter-name>
       <filter-class>com.ucenter.filter.LoginFilter</filter-class>
   </filter>

   <filter-mapping>
       <filter-name>login</filter-name>
       <url-pattern>/*</url-pattern>
</filter-mapping>



<!-- 配置session超时时间,单位分钟 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>


<welcome-file-list>
<welcome-file>templates/login/index.html</welcome-file>
</welcome-file-list>
</web-app>


过滤器(Filter)位于客户端和web应用程序之间,用于检查和修改两者之间流过的请求和响应。
在请求到达Servlet/JSP之前,过滤器截获请求。 在响应送给客户端之前,过滤器截获响应。
多个过滤器形成一个过滤器链,过滤器链中不同过滤器的先后顺序由部署文件web.xml中过滤器映射<filter-mapping>的顺序决定。 最先截获客户端请求的过滤器将最后截获Servlet/JSP的响应信息。 

    可以为一个Web应用组件部署多个过滤器,这些过滤器组成一个过滤器链,每个过滤器只执行某个特定的操作或者检查。这样请求在到达被访问的目标之前,需要经过这个过滤器链。

    Servlet API的2.3版本的一个新功能就是能够为servlet和JSP页面定义过滤器。过滤器提供了某些早期服务器所支持的非标准“servlet链接”的一种功能强大且标准的替代品。过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上。过滤器可附加到一个或多个servlet或 JSP页面上,并且可以检查进入这些资源的请求信息。在这之后,过滤器可以作如下的选择:

    以常规的方式调用资源(即,调用servlet或JSP页面)。
    利用修改过的请求信息调用资源。
    调用资源,但在发送响应到客户机前对其进行修改。
    阻止该资源调用,代之以转到其他的资源,返回一个特定的状态代码或生成替换输出。 

  过滤器只在与servlet规范2.3版兼容的服务器上有作用。如果你的Web应用需要支持旧版服务器,就不能使用过滤器。
  
1. 建立基本过滤器
建立一个过滤器涉及下列五个步骤:

1)建立一个实现Filter接口的类。这个类需要三个方法,分别是:doFilter、init和destroy。doFilter方法包含主要的过滤代码(见第2步),init方法建立设置操作,而destroy方法进行销毁。

2)在doFilter方法中放入过滤行为。doFilter方法的第一个参数为ServletRequest对象。此对象给过滤器提供了对进入的信息(包括表单数据、cookie和HTTP请求头)的完全访问。第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。最后一个参数为 FilterChain,如下一步所述,此参数用来调用servlet或JSP页。

3)调用FilterChain对象的doFilter方法。Filter接口的doFilter方法取一个FilterChain对象作为它的一个参数。在调用此对象的doFilter方法时,激活下一个相关的过滤器。如果没有另一个过滤器与servlet或JSP页面关联,则servlet或JSP页面被激活。

4)对相应的servlet和JSP页面注册过滤器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素。

5)禁用激活器servlet。防止用户利用缺省servlet URL绕过过滤器设置。

例如:建立一个实现Filter接口的类
所有过滤器都必须实现javax.servlet.Filter。这个接口包含三个方法,分别为doFilter、init和destroy。
1、public void doFilter(ServletRequset request, ServletResponse response,FilterChain chain)
    thows ServletException, IOException

每当调用一个过滤器(即,每次请求与此过滤器相关的servlet或JSP页面)时,就执行其doFilter方法。正是这个方法包含了大部分过滤逻辑。

第一个参数为与传入请求有关的ServletRequest。对于简单的过滤器,大多数过滤逻辑是基于这个对象的。如果处理HTTP请求,并且需要访问诸如getHeader或getCookies等在ServletRequest中无法得到的方法,就要把此对象构造成 HttpServletRequest。

第二个参数为ServletResponse。除了在两个情形下要使用它以外,通常忽略这个参数。首先,如果希望完全阻塞对相关 servlet或JSP页面的访问。可调用response.getWriter并直接发送一个响应到客户机。其次,如果希望修改相关的servlet或 JSP页面的输出,可把响应包含在一个收集所有发送到它的输出的对象中。然后,在调用serlvet或JSP页面后,过滤器可检查输出,如果合适就修改它,之后发送到客户机。

DoFilter的最后一个参数为FilterChain对象。对此对象调用doFilter以激活与servlet或JSP页面相关的下一个过滤器。如果没有另一个相关的过滤器,则对doFilter的调用激活servlet或JSP本身。

2、public void init(FilterConfig config)thows ServletException
init 方法只在此过滤器第一次初始化时执行,不是每次调用过滤器都执行它。对于简单的过滤器,可提供此方法的一个空体,但有两个原因需要使用init。首先,FilterConfig对象提供对servlet环境及web.xml文件中指派的过滤器名的访问。因此,普遍的办法是利用init将 FilterConfig对象存放在一个字段中,以便doFilter方法能够访问servlet环境或过滤器名。其次,FilterConfig对象具有一个getInitParameter方法,它能够访问部署描述符文件(web.xml)中分配的过滤器初始化参数。

3、public void destroy( )
此方法在利用一个给定的过滤器对象永久地终止服务器(如关闭服务器)时调用。大多数过滤器简单地为此方法提供一个空体,不过,可利用它来完成诸如关闭过滤器使用的文件或数据库连接池等清除任务。

4、注册过滤器
部署描述符文件的2.3版本引入了两个用于过滤器的元素,分别是:filter和filter-mapping。filter元素向系统注册一个过滤对象,filter-mapping元素指定该过滤对象所应用的URL。
4.1)filter元素
filter元素位于部署描述符文件(web.xml)的前部,所有filter-mapping、servlet或servlet-mapping元素之前。filter元素具有如下六个可能的子元素:
icon 这是一个可选的元素,它声明IDE能够使用的一个图象文件。
filter-name 这是一个必需的元素,它给过滤器分配一个选定的名字。
display-name 这是一个可选的元素,它给出IDE使用的短名称。
description 这也是一个可选的元素,它给出IDE的信息,提供文本文档。
filter-class 这是一个必需的元素,它指定过滤器实现类的完全限定名。
init-param 这是一个可选的元素,它定义可利用FilterConfig的getInitParameter方法读取的初始化参数。单个过滤器元素可包含多个init-param元素。

filter-mapping元素
filter-mapping元素位于web.xml文件中filter元素之后serlvet元素之前。它包含如下三个可能的子元素
@filter-name 这个必需的元素必须与用filter元素声明时给予过滤器的名称相匹配。
@url-pattern 此元素声明一个以斜杠(/)开始的模式,它指定过滤器应用的URL。所有filter-mapping元素中必须提供url-pattern或 servlet-name。但不能对单个filter-mapping元素提供多个url-pattern元素项。如果希望过滤器适用于多个模式,可重复整个filter-mapping元素。
@servlet-name 此元素给出一个名称,此名称必须与利用servlet元素给予servlet或JSP页面的名称相匹配。不能给单个filter-mapping元素提供多个servlet-name元素项。如果希望过滤器适合于多个servlet名,可重复这个filter-mapping元素。
--------------------------------------------------------------------------------------------------
##代码示例一:
未登录无权访问系统相关内容(如:用户只有登陆之后才能浏览resource目录下的资源,而这些resource的地址都是静态地址,这时候就用到了过滤器)
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
   HttpServletRequest req = (HttpServletRequest) req;
   HttpServletResponse resp = (HttpServletResponse) res;
   HttpSession session=req.getSession();
   ServletContext application=session.getServletContext();
   
      if(session.getAttribute("username")==null)
      {
       response.sendRedirect("error/priv_error.jsp");
       return;
      }
      else
      {
       chain.doFilter(request, response);
      }
}
web.xml中如下配置:
<filter>
      <filter-name>myFilter</filter-name>
      <filter-class>cn.com.test.filter.myFilter</filter-class>
   </filter>

<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/resource/*</url-pattern>
</filter-mapping>

关闭

IT问道推荐

银行贷款频频被拒?
“Dr信用牛牛”让你远离信用污点 国内首家信用健康管理平台免费为你提供信用修复方案