关于Filter的学习

103 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

在Filter的学习前,我们要先了解什么是Filter,Filter的作用是什么及是如何实现的,接下来就一起来学习!

一、Filter的定义

Filter拦截请求和响应,以便查看、提取或以某种方式操作正在客户端和服务器之间交换的数据。Filter可以改变一个请求(Request)或者是修改响应(Response)。Filter与Servlet的关联由Web应用的配置描述文件或注解来明确。用户发送请求给Servlet时,在Servlet处理请求之前,与此Servlet关联的Filter首先执行,然后才是Servlet的执行,Servlet执行完毕又会回到Filter。如果一个Servlet有多个Filter,则根据配置的先后次序依次执行。

二、Filter的应用

(1)访问特定资源(Web页、JSP页、Servlet)时的身份验证。

(2)访问资源的记录跟踪。

(3)访问资源的转换。

三、Filter的实现

一个Filter必须实现javax.Servlet.Filter接口,即实现下面的三个方法

(1)doFilter(ServletRequest, ServletResponse, FilterChain)。用来实现过滤行为的方法。引入的FilterChain对象提供了后续Filter所要调用的信息。

(2)init(FilterConfig)。由容器所调用的Filter初始化方法。容器确保在第一次调用doFilter方法前调用此方法,一般用来获取在web.xml文件中指定的初始化参数。

(3)destroy()。容器在破坏Filter实例前,doFilter()中的所有活动都被该实例终止后,调用该方法。

四、实例

···

@WebFilter("/Main")
public class TimeTrackFilter implements Filter {

        private static final boolean debug = true;

        // The filter configuration object we are associated with. If
        // this value is null, this filter instance is not currently
        // configured.
        private FilterConfig filterConfig = null;

        /**
         * Default constructor.
         */
        public TimeTrackFilter() {
                // TODO Auto-generated constructor stub
        }

        /**
         * @see Filter#destroy()
         */
        public void destroy() {
                // TODO Auto-generated method stub
        }

        /**
         * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
         */
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                        throws IOException, ServletException {
                Date startTime, endTime;
                double totalTime;
                StringWriter sw = new StringWriter();
                System.out.println("我在Filter中");
                startTime = new Date();
                chain.doFilter(request, response);
                endTime = new Date();
                totalTime = endTime.getTime() - startTime.getTime();
                totalTime = totalTime;
                System.out.println("我在Filter中");
                PrintWriter writer = new PrintWriter(sw);
                System.out.println("===============");
                System.out.println("耗时: " + totalTime + " 毫秒");
                System.out.println("===============");
//		filterConfig.getServletContext().log(sw.getBuffer().toString());
        }

        /**
         * @see Filter#init(FilterConfig)
         */
        public void init(FilterConfig fConfig) throws ServletException {
                System.out.println("init");
                this.filterConfig = filterConfig;
                if (filterConfig != null) {
                        if (debug) {
                                log("TimeTrackFilter:Initializing filter");
                        }
                }
        }

        private void sendProcessingError(Throwable t, ServletResponse response) {
                String stackTrace = getStackTrace(t);

                if (stackTrace != null && !stackTrace.equals("")) {
                        try {
                                response.setContentType("text/html");
                                PrintStream ps = new PrintStream(response.getOutputStream());
                                PrintWriter pw = new PrintWriter(ps);
                                pw.print("<html>\n<head>\n<title>Error</title>\n</head>\n<body>\n"); // NOI18N

                                // PENDING! Localize this for next official release
                                pw.print("<h1>The resource did not process correctly</h1>\n<pre>\n");
                                pw.print(stackTrace);
                                pw.print("</pre></body>\n</html>"); // NOI18N
                                pw.close();
                                ps.close();
                                response.getOutputStream().close();
                        } catch (Exception ex) {
                        }
                } else {
                        try {
                                PrintStream ps = new PrintStream(response.getOutputStream());
                                t.printStackTrace(ps);
                                ps.close();
                                response.getOutputStream().close();
                        } catch (Exception ex) {
                        }
                }
        }

        public static String getStackTrace(Throwable t) {
                String stackTrace = null;
                try {
                        StringWriter sw = new StringWriter();
                        PrintWriter pw = new PrintWriter(sw);
                        t.printStackTrace(pw);
                        pw.close();
                        sw.close();
                        stackTrace = sw.getBuffer().toString();
                } catch (Exception ex) {
                }
                return stackTrace;
        }

        public void log(String msg) {
                filterConfig.getServletContext().log(msg);
        }

        /**
         * Return a String representation of this object.
         */
        @Override
        public String toString() {
                if (filterConfig == null) {
                        return ("TimeTrackFilter()");
                }
                StringBuffer sb = new StringBuffer("TimeTrackFilter(");
                sb.append(filterConfig);
                sb.append(")");
                return (sb.toString());
        }

        public FilterConfig getFilterConfig() {
                return filterConfig;
        }

        public void setFilterConfig(FilterConfig filterConfig) {
                this.filterConfig = filterConfig;
        }

        public static boolean isDebug() {
                return debug;
        }

}

···

以上通过对Filter的实例学习,可以看到Filter是包裹在Servlet组件外面的一层防护网。在请求到达Servlet前后都会经过Filter的处理。