首页 > 技术文章 > Filter 过滤器

hongdada 2017-03-31 16:29 原文

Filter简介:

Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。

例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

Code:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>SpringMVCDemo Web Application</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.gaussic.servlet.HelloWorldServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/servlet/HelloWorld</url-pattern>
    </servlet-mapping>
 
    <!-- 编码过滤器 -->
    <filter>
        <filter-name>setCharacterEncoding</filter-name>
        <filter-class>com.gaussic.filter.EncodingFilter</filter-class>
        <init-param>
            <param-name>charset</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>setCharacterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 请求url日志记录过滤器 -->
    <filter>
        <filter-name>logfilter</filter-name>
        <filter-class>com.gaussic.filter.LogFilter</filter-class>
        <!--配置logfilter过滤器的初始化参数-->
        <init-param>
            <description>配置logfilter过滤器的初始化参数</description>
            <param-name>name</param-name>
            <param-value>gacl</param-value>
        </init-param>
        <init-param>
            <description>配置logfilter过滤器的初始化参数</description>
            <param-name>like</param-name>
            <param-value>java</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>logfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

特别注意servlet,filter

过滤器Filter:

package com.gaussic.filter;


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 java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Administrator on 2017/3/31 0031.
 */
public class EncodingFilter implements Filter {


    private FilterConfig filterConfig = null;
    private String defaultCharset = "UTF-8";

    // 项目结束时就已经进行销毁
    public void destroy() {
        System.out.println("end do the encoding filter!");
    }

    public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //得到在web.xml中配置的字符编码
        String charset = filterConfig.getInitParameter("charset");
        System.out.println("before encoding  filter!");
        if(charset==null){
            charset = defaultCharset;
        }
        request.setCharacterEncoding(charset);
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset="+charset);

        MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
        chain.doFilter(requestWrapper, response);

        //chain.doFilter(req, resp);
        System.out.println("after encoding  filter!");
        System.err.println("------------------8888----------------------");
    }

    // 项目启动时就已经进行读取
    public void init(FilterConfig config) throws ServletException {
        this.filterConfig = config;
        System.out.println("begin do the encoding filter!");
    }
}

对get的请求返回内容进行转码:

package com.gaussic.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * Created by Administrator on 2017/3/31 0031.
 */
public class MyCharacterEncodingRequest extends HttpServletRequestWrapper {
    //定义一个变量记住被增强对象(request对象是需要被增强的对象)
    private HttpServletRequest request;
    //定义一个构造函数,接收被增强对象
    public MyCharacterEncodingRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    /* 覆盖需要增强的getParameter方法
     * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
     */
    @Override
    public String getParameter(String name) {
        try{
            //获取参数的值
            String value= this.request.getParameter(name);
            if(value==null){
                return null;
            }
            //如果不是以get方式提交数据的,就直接返回获取到的值
            if(!this.request.getMethod().equalsIgnoreCase("get")) {
                return value;
            }else{
                //如果是以get方式提交数据的,就对获取到的值进行转码处理
                value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
                return value;
            }
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

日志过滤器:

package com.gaussic.filter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;

/**
 * Created by Administrator on 2017/3/31 0031.
 */
public class LogFilter implements Filter {
    FilterConfig config;

    public void destroy() {
        this.config = null;
    }

    public void doFilter(ServletRequest req, ServletResponse res,
                         FilterChain chain) throws IOException, ServletException {
        // 获取ServletContext 对象,用于记录日志
        ServletContext context = this.config.getServletContext();
        //long before = System.currentTimeMillis();
        System.out.println("before the log filter!");
        //context.log("开始过滤");
        // 将请求转换成HttpServletRequest 请求
        HttpServletRequest hreq = (HttpServletRequest) req;
        // 记录日志
        System.out.println("Log Filter已经截获到用户的请求的地址:"+hreq.getServletPath() );
        //context.log("Filter已经截获到用户的请求的地址: " + hreq.getServletPath());
        try {
            // Filter 只是链式处理,请求依然转发到目的地址。
            chain.doFilter(req, res);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("after the log filter!");

    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("begin do the log filter!");
        this.config = config;

        //得到过滤器的名字
        String filterName = config.getFilterName();
        //得到在web.xml文件中配置的初始化参数
        String initParam1 = config.getInitParameter("name");
        String initParam2 = config.getInitParameter("like");
        //返回过滤器的所有初始化参数的名字的枚举集合。
        Enumeration<String> initParameterNames = config.getInitParameterNames();

        System.out.println(filterName);
        System.out.println(initParam1);
        System.out.println(initParam2);
        while (initParameterNames.hasMoreElements()) {
            String paramName = (String) initParameterNames.nextElement();
            System.out.println(paramName);
        }
        System.out.println("begin do the log filter end!");
    }

}

Servlet:

package com.gaussic.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created by Administrator on 2017/3/31 0031.
 */
public class HelloWorldServlet extends HttpServlet {

    /**
     * 查看httpservlet实现的service一看便知,起到了一个controll控制器的作用(转向的)
     * 之后便是跳转至我们熟悉的doget,dopost等方法中
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("doservice..."+this.getInitParameter("encoding"));

        super.service(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("doget...");
        String username = req.getParameter("username");
        //获取请求方式
        String method = req.getMethod();
        //获取输出流
        PrintWriter out = resp.getWriter();
        out.write("Method:"+method);
        out.write("<br/>");
        out.write("接收到的参数:"+username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("dopost...");
        doGet(req, resp);
    }
}

运行以后日志:

begin do the encoding filter!
begin do the log filter!
logfilter
gacl
java
like
name
begin do the log filter end!
//......
before encoding  filter!
before the log filter!
Log Filter已经截获到用户的请求的地址:/
after the log filter!
after encoding  filter!
------------------8888----------------------
before encoding  filter!
before the log filter!
Log Filter已经截获到用户的请求的地址:/
after the log filter!
after encoding  filter!
------------------8888----------------------
before encoding  filter!
before the log filter!
Log Filter已经截获到用户的请求的地址:/
after the log filter!
after encoding  filter!
------------------8888----------------------
31-Mar-2017 16:33:57.245 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory D:\Program Files\Tomcat9\webapps\manager
31-Mar-2017 16:33:57.322 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory D:\Program Files\Tomcat9\webapps\manager has finished in 75 ms
------------------8888----------------------
before encoding  filter!
before the log filter!
Log Filter已经截获到用户的请求的地址:/servlet/HelloWorld
doservice...null
doget...
after the log filter!
after encoding  filter!
before encoding  filter!
before the log filter!
Log Filter已经截获到用户的请求的地址:/servlet/HelloWorld
doservice...null
doget...
after the log filter!
after encoding  filter!
------------------8888----------------------
"D:\Program Files\Tomcat9\bin\catalina.bat" stop
Using CATALINA_BASE:   "C:\Users\Administrator\.IntelliJIdea2016.3\system\tomcat\Unnamed_SpringMVCDemo"
Using CATALINA_HOME:   "D:\Program Files\Tomcat9"
Using CATALINA_TMPDIR: "D:\Program Files\Tomcat9\temp"
Using JRE_HOME:        "D:\Program Files\Java\jdk1.8.0_102"
Using CLASSPATH:       "D:\Program Files\Tomcat9\bin\bootstrap.jar;D:\Program Files\Tomcat9\bin\tomcat-juli.jar"
31-Mar-2017 16:37:14.434 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
31-Mar-2017 16:37:14.435 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8085"]
31-Mar-2017 16:37:14.487 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-55366"]
31-Mar-2017 16:37:14.537 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina
end do the encoding filter!

 

 

http://www.cnblogs.com/xdp-gacl/p/3948353.html

http://www.cnblogs.com/xdp-gacl/p/3952405.html

http://blog.csdn.net/sd0902/article/details/8395641

推荐阅读