Filter笔记(一)

Filter过滤器简介

        Filter是拦截Request请求的对象, 在用户的请求访问到目标资源之前处理request和response,它可以用于日志记录/加密解密/Session检查/文件保护.通过Filter可以拦截处理某个或者某些资源

        Filter的配置可以通过注解或者部署在web.xml中来完成,一般情况下来说要访问到一个资源要部署很多的Filter,除非对Filter的触发顺序有要求,否则都可以使用注解来配置Filter

所有过滤器都应该实现Filter接口,接口定义了init(),doFilter(),distory()三个方法

1.init(FilterConfig filterConfig)

在Web程序启动时根据web.xml中的配置信息创建Filter实例化对象并保存在服务器端的内存中,同时调用Filter的init()方法,初始化方法在一个Filter对象的生命周期中只会被调用一次,init()方法在被调用的时候会传递一个包含Filter配置和运行环境的FilterConfig对象,以用来部署Filter的初始化参数.

2.doFilter(ServletRequest request,ServletResponse response,FilterChain chain)

        在客户端请求服务器资源的时候, 容器就会调用和目标资源相关联过滤器的doFilter()方法,方法中的request和response是上一个Filter传递过来的请求/响应对象,chain参数代表当前的Filter链对象,在当前Filter指定的操作执行完后,在doFilter()方法中调用FilterChain对象的doFilter方法。之后请求会被交给Filter链的下一个Filter去继续处理。如果当前的Filter是Filter链的最后一个Filter。那么就会直接执行目标Servlet,也可以直接向客户端返回响应信息,或者利用RequestDispatcher的forward()和include()方法,以及 HttpServletResponse的sendRedirect()方法将请求转向到其他资源。 反之:如果Filter链中任意一个doFilter()方法在执行的过程中出现了错误,那么将不会继续执行接下来Filter中的doFIlter方法,   过滤器的使用并不会依赖具体的协议  

3.destory()

在容器销毁Filter对象之前被调用,在一个Filter的生命周期里只会被执行一次,同时可以释放过滤器使用的资源

4.1:配置Filter注意事项

        1.确认需要拦截的Servlet

    2.确认初始化的参数值,例如日志过滤器文件名,日志前缀等。这些属性可以在Filter的初始化时通过调用filterConfig.getInitParameter(“web.xml中配置的参数名称”)来获得

        3.起好Filter的名字,一般来说一个页面都会有很多Filter,所以便于区分

4.2:Filter的xml配置

Filter的xml配置类似于Servlet的配置

首先需要配置一个Filter

<filter>
    <--Filter的名字,这个Filter是用来记访问的记录的-->
    <filter-name>AccessFilter</filter-name>
    
    <--Filter实现类的具体位置-->
    <filter-class>com.dxy.web.filter.AccessFilter</filter-class>
    
    <--对该Filter加上一些初始化参数,在Web程序启动的时候这些参数会自动被部署好-->
    <--例如我需要写一个访问记录器,那么我可以配置一个日志文件的文件名-->
    <init-param>
            <param-name>FileName</param-name>
            <param-value>filter.logging</param-value>
    </init-param>
    <--再加上一个日志的前缀-->
    <init-param>
        <param-name>prefix</param-name>
        <param-value>Request:</param-value>
    </init-param>
</filter>
现在Filter配置好了,需要把Filter放在指定的Servlet上

<--Filter映射到Servlet上-->
<filter-mapping>
    <--要映射的Filter的名字-->
    <filter-name>AccessFilter</filter-name>
    <!-- 访问过滤 -->
    <servlet-name>AccessServlet</servlet-name>
</filter-mapping>

Hmmm......直白点来说意思就是每当这个叫做AccessServlet的Servlet要处理访问请求的时候都会先执行这个Filter中doFilter的内容。而这个Filter中会记录下用户访问的请求

注:在Filter映射的过程中也可以根据URL进行拦截


<url-pattern>/xxx</url-pattern><url-pattern>/xxx</url-patt

这样Filter也会将处理该地址的Servlet进行拦截

4.3:Filter实现类

package com.dxy.web.filter;
​
import javax.servlet.*;
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;
​
​
//所有的Filter实现累都要实现Filter接口
public class AccessFilter implements Filter {
​
    //输出流记录日志
    private PrintWriter logger;
    //Filter初始化参数中的前缀名称
    private String prefix;
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //获取前缀名称
        prefix = filterConfig.getInitParameter("prefix");
        
        //获取日志文件名
        String filename = filterConfig.getInitParameter("FileName");
        
        //获取应用的运行时位置
        String Path = filterConfig.getServletContext().getRealPath("/");
        try {
            File file = new File(Path, filename);
            file.createNewFile();
            logger = new PrintWriter(file);
        } catch (FileNotFoundException e) {
            throw new ServletException(e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }
​
    }
​
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        //因为处理的是Http请求,所以这里要进行类型转换
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        //获取请求的URI
        String host = httpServletRequest.getRemoteHost();
        String uri = httpServletRequest.getRequestURI();
        //打印出的访问日志信息
        String in =new String ((new Date() + " " + prefix + uri+" host:"+host
                + " Port:"+request.getRemotePort()).getBytes("ISO-8859-1"),"UTF-8");
        logger.println(in);
        //打印一次刷新一次,不能关闭输出流
        logger.flush();
        //继续下一个Filter
        chain.doFilter(request, response);
    }
​
    @Override
    public void destroy() {
        if (logger != null) {
            logger.close();
        }
    }
}

这样子一个简单的Filter就算是写好了,只要Filter映射到的Servlet接受到访问请求,访问的记录就会被记录下来。

        会有后续,仅供个人学习使用。

猜你喜欢

转载自blog.csdn.net/qq_38449518/article/details/82261892