过滤器

作者: 码而优则仕 | 来源:发表于2020-08-31 14:42 被阅读0次

    过滤器

    过滤器是指拦截请求,并对传给被请求资源的ServletRequest或ServletResponse 进行处理的一个对象。过滤器可以用于登录,加密和解密,会话检查,图片转换等等。过滤器可以配置为拦截一个或多个资源。

    过滤器配置可以通过注解或者部署描述符来完成。如果同一个资源或同一组资源中应用了多个过滤器,则其调用顺序有时候显得比较重要,这时候就需要用到部署描述符。

    核心接口/类:

    FilterFilterConfigFilterChain

    过滤器类必须实现Filter接口;接口定义了三个方法:init,doFilter,destroy。

    void init(FilterConfig filterConfig)

    当过滤器启动时,比如应用程序启动时,Servlet容器就会调用init方法。不用等到调用与过滤器相关的资源之后,才调用init方法。这个方法只调用一次,并且应该包含该过滤器的初始化代码。

    void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain)

    每次调用与过滤器相关的资源时,Servlet容器都会调用Filter实例的doFilter 方法。该方法会收到一个ServletRequest,ServletResponse和FilterChain。

    doFilter的实现可以访问 ServletRequest和ServletResponse。因此,可以在ServletRequest中添加属性,或者在ServletResponse中添加一个标头。甚至可以对ServletRequest或者ServletResponse进行修改,改变他们的行为。doFilter方法实现的最后一行代码应该是调用FilterChain(作为doFilter方法的第三个参数)中的doFilter方法:

    filterChain.doFilter(request,response)

    一个资源可以与多个过滤器(更专业地说,是一条过滤器链)关联,FilterChain.doFilter()通常会引发调用链中的下一个过滤器被调用。在链中的最后一个过滤器中调用FilterChain.doFilter会引发资源本身被调用。如果没有在Filter.doFilter方法实现代码的最后调用FilterChain.doFilter方法,那么程序的处理将会在这个地方停止,并且不会调用请求。

    注意,doFilter方法是FilterChain接口中唯一的方法。它与Filter中的doFilter方法稍有不同。在FilterChain中,doFilter只有两个参数,而不是三个。

    除非一个过滤器类在部署描述符的多个filter元素中进行了申明,否则Servlet容器将只给每一类过滤器创建一个实例。由于Servlet/JSP应用程序通常是多用户的应用程序,因此可以同时通过多个线程访问一个过滤器实例,但你必须谨慎处理好多线程的问题。

    过滤器的配置

    配置过滤器的目标如下:

    • 确定过滤器要拦截哪些资源

    • 要传给过滤器init方法的启动初始值。

    • 给过滤器起个名字

    FilterConfig 接口允许通过其getServletContext方法访问ServletContext

    ServletContext getServletContext();

    String getFilterName();
    
    ServletContext getServletContext();
    
    String getInitParameter(String var1);
    
    Enumeration<String> getInitParameterNames();
    

    配置过滤器有两种方法。一种是利用WebFilter注解类型,一种通过部署描述符注册来配置。

    范例如下:

    package cn.com.yuns.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.annotation.WebInitParam;
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    
    /**
     * 日志过滤器
     *
     * @author wsq
     * @version LoggingFilter.java  2020/7/30  上午8:28 下午
     */
    @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;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            String prefix = filterConfig.getInitParameter("prefix");
            this.prefix = prefix;
            String logFileName = filterConfig.getInitParameter("logFileName");
            String appPath = filterConfig.getServletContext().getRealPath("/");
            System.out.println("logFileName:" + logFileName);
    
            try {
                logger = new PrintWriter(new File(appPath, logFileName));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                throw new ServletException(e.getMessage());
            }
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("LoggingFilter doFilter");
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            logger.println(new Date() + " " + prefix + httpServletRequest.getRequestURI());
            logger.flush();
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("destroy File");
            if (logger != null) {
                logger.close();
            }
        }
    }
    
    package cn.com.yuns.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    @WebFilter(filterName = "ImageProtectorFilter", urlPatterns = {"*.png", "*.jpg", "*.gif","*.jpeg"})
    public class ImageProtectorFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("ImageProtectorFilter");
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            String referer = httpServletRequest.getHeader("referer");
            System.out.println("referer:" + referer);
            if (referer != null) {
                filterChain.doFilter(servletRequest, servletResponse);
            } else {
                throw new ServletException("Image not Available");
            }
        }
    
    }
    
    package cn.com.yuns.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Properties;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @author wsq
     * @version DownloadCounterFilter.java  2020/7/30  上午9:50 下午
     */
    @WebFilter(filterName = "DownloadCounterFilter", urlPatterns = {"/*"})
    public class DownloadCounterFilter implements Filter {
    
        ExecutorService executors = Executors.newSingleThreadExecutor();
    
        Properties downloadLog;
    
        File logFile;
    
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("DownloadCounterFilter");
            String appPath = filterConfig.getServletContext().getRealPath("/");
            logFile = new File(appPath, "downloadLog.txt");
            if (!logFile.exists()) {
                try {
                    logFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            downloadLog = new Properties();
            try {
                downloadLog.load(new FileReader(logFile));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            final String uri = httpServletRequest.getRequestURI();
            executors.execute(new Runnable() {
                @Override
                public void run() {
                    String propertie = downloadLog.getProperty(uri);
                    if (null == propertie) {
                        downloadLog.setProperty(uri, "1");
                    } else {
                        int count = 0;
                        try {
                            count = Integer.parseInt(propertie);
                        } catch (Exception e) {
                        }
                        count++;
                        downloadLog.setProperty(uri, Integer.toString(count));
                        try {
                            downloadLog.store(new FileWriter(logFile), "");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            executors.shutdown();
        }
    }
    
    <%--
      Created by IntelliJ IDEA.
      User: wsq
      Date: 2020/7/30
      Time: 9:24 下午
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Image</title>
    </head>
    <body>
    <a href="image/888.png">程序代码</a><br><br>
    <a href="image/linyin.jpeg">凛音桃花1</a><br><br>
    <a href="image/520.jpeg">凛音桃花1</a><br><br>
    <a href="image/sx.jpeg">松下纱荣子</a><br><br>
    </body>
    </html>
    

    过滤器的顺序

    如果多个过滤器应用于同一个资源,那么调用顺序就很重要,必须用部署描述符管理应该先调用哪一个过滤器。假如Filter1必须在Filter2之前调用,那么在部署描述符中,Filter 的 申明就要放在 Filter2的申明之前。

    <filter>
        <filter-name>Filter1</filter-name>
        <filter-class>Filter1</filter-class>
        <init-param>
            <param-name>qqqq</param-name>
            <param-value>qqq</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>Filter1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <filter>
        <filter-name>Filter2</filter-name>
        <filter-class>Filter2</filter-class>
        <init-param>
            <param-name>www</param-name>
            <param-value>wwwww</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>Filter2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    如果没有部署描述符,是不可能管理过滤器调用顺序的。

    相关文章

      网友评论

          本文标题:过滤器

          本文链接:https://www.haomeiwen.com/subject/buksrktx.html