zoukankan      html  css  js  c++  java
  • 云笔记项目-过滤器与拦截器学习

    在做云笔记项目的过程中,没有登录的情况下,也可以直接访问edit.html页面。这个跟以前自己用Servlet做过的PadAndFilterManagement情况类似,当时在没有登录的情况下可以访问任何的action,后面加了过滤器才解决。只是在云笔记项目中,其使用的Spring MVC框架,即也可以使用Spring容器下的拦截器Interceptor进行拦截。但是过滤器和拦截器到底有什么区别,博客中有很多大牛分享了经验,这里直接贴过来,作为今后自己的查看的参考。

    过滤器Filter和拦截器Interceptor的主要区别

    (1)使用范围:Filter是Servlet规范的,只能用于Web程序中,而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。

    (2)规范不同:Filter是在Servlet规范中定义的,由Servlet容器支持。拦截器Interceptor是在Spring容器中的,由Spring框架支持。

    (3)可以调用的资源不同:拦截器Interceptor是Spring的一个组件,由Spring管理,配置在Spring文件中,因此可以使用Spring里的任何资源、对象。比如Service,对象,数据源,事务管理等,通过注入到拦截器就可以进行深层次访问。Filter不具备此功能。

    (4)Filter只在Servlet前后起作用,Interceptor能够深入到方法前后,异常抛出前后等,因此拦截器的使用具有更大的弹性,如果只拦截action请求,在Spring框架程序中,优先使用拦截器。

    过滤器Filter和拦截器Interceptor的执行顺序

    项目中使用了过滤器进行特定网页的过滤,如不过滤log_in.html,让用户首先能看到登录页面。并且使用了拦截器进行action的拦截,如果是登录注册的请求就不进行了拦截。其实项目使用过滤器也可以实现需求,但是同时使用了两种的话,就有必要大致了解浏览器访问服务端后,过滤器和拦截器的执行顺序。参考了大牛的博文,进行如下测试:

    (1)过滤器

     1 package Filter;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.Filter;
     6 import javax.servlet.FilterChain;
     7 import javax.servlet.FilterConfig;
     8 import javax.servlet.ServletException;
     9 import javax.servlet.ServletRequest;
    10 import javax.servlet.ServletResponse;
    11 
    12 /**
    13  * 测试过滤器
    14  * @author yangchaolin
    15  *
    16  */
    17 public class SomeFilter implements Filter{
    18 
    19     public void destroy() {
    20      System.out.println("过滤器的destroy方法执行了");        
    21     }
    22 
    23     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
    24             throws IOException, ServletException {
    25        System.out.println("过滤器的doFilter...before执行了");
    26        chain.doFilter(req, res);    
    27        System.out.println("过滤器的doFilter...after执行了");
    28     }
    29 
    30     public void init(FilterConfig config) throws ServletException {
    31       System.out.println("过滤器的init方法执行了");
    32     }
    33 
    34 }

    (2)拦截器

     1 package Interceptors;
     2 
     3 import javax.servlet.http.HttpServletRequest;
     4 import javax.servlet.http.HttpServletResponse;
     5 
     6 import org.springframework.web.servlet.HandlerInterceptor;
     7 import org.springframework.web.servlet.ModelAndView;
     8 /**
     9  * 拦截器类需要实现HandlerInterceptor接口
    10  * @author yangchaolin
    11  *
    12  */
    13 public class SomeInterceptor implements HandlerInterceptor{
    14     /**
    15      * DispatcherServlet在收到请求后,会先调用preHandler方法,如果该方法的返回值为true,则继续向后调用Controller的方法
    16      * 如果返回值是false,则中断请求
    17      * 
    18      * DispatcherServlet,拦截器以及Controller会共享同一个request,response
    19      * handler:Controller的方法对象,利用了java反射机制,后面了解学习
    20      */
    21     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    22             throws Exception {
    23         System.out.println("拦截器的preHandler方法执行了");
    24         return true;
    25     }
    26     /**
    27      * 是Controller处理完后,在将ModelAndView返回给前端控制器DispatcherServlet之前,执行的方法
    28      * 可以在该方法里,修改ModelAndView的处理结果
    29      */
    30     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    31             ModelAndView modelAndView) throws Exception {
    32         System.out.println("拦截器的postHandler方法执行了");
    33         
    34     }
    35     /**
    36      * 最后执行
    37      * ex:是处理器Controller所抛出的异常
    38      * 可以写一个拦截器专门处理处理器Controller抛出的异常
    39      */
    40     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    41             throws Exception {
    42         System.out.println("拦截器的afterCompletion方法执行了");
    43         
    44     }
    45 
    46 }

    (3)web.xml中配置过滤器

    1   <!-- 测试拦截器配置 -->
    2   <filter>
    3     <filter-name>someFilter</filter-name>
    4     <filter-class>Filter.SomeFilter</filter-class>
    5   </filter> 
    6   <filter-mapping>
    7      <filter-name>someFilter</filter-name>
    8      <url-pattern>/*</url-pattern>
    9   </filter-mapping>

    (4)spring-mvc.xml中配置拦截器

    1     <!-- 设置拦截器Interceptor -->
    2     <!-- 如果想要拦截所有的请求,path应该写成/** -->    
    3     <mvc:interceptors>
    4       <mvc:interceptor>
    5        <mvc:mapping path="/**"/>       
    6        <bean class="Interceptors.SomeInterceptor"></bean>
    7       </mvc:interceptor>
    8     </mvc:interceptors>

    (5)控制器中方法

     1 package Controller;
     2 
     3 import org.springframework.stereotype.Controller;
     4 import org.springframework.web.bind.annotation.RequestMapping;
     5 
     6 @Controller
     7 public class HelloController {
     8     @RequestMapping("/hello.do")
     9     public String hello() {
    10         System.out.println("控制器的hello()方法执行了");
    11         return "hello";        
    13     }
    14     /**
    15      * 如果路径加一个demo,然而拦截器mapping还是/*的话,将不会拦截
    16      * 如果想实现各种路径的拦截,不论几层都能实现拦截效果的话,需要将mapping修改为/**
    17      * @return
    18      */
    19     @RequestMapping("/demo/hello.do")
    20     public String hello1() {
    21         System.out.println("控制器的hello1()方法执行了");
    22         return "hello";        
    24     }
    25 }

     测试部分

    (1)启动测试项目,地址1为:http://localhost:8088/SpringMVC03/hello.do,控制台输出结果为:

     (2)启动测试项目,地址2为:http://localhost:8088/SpringMVC03/demo/hello.do,控制台输出结果为:

    在两次请求服务端后,控制台只输出了一次"过滤器的init方法执行了"。说明过滤器初始化过程在servlet容器中只执行了一次。

    (3)启动测试项目,地址3为:http://localhost:8088/SpringMVC03/demo.do,控制器输出结果为:

    从测试的结果来看,发现在浏览器发送请求给服务端的时候,过滤器Filter更早于拦截器Interceptor执行,而在浏览器接收服务端返回的信息时,过滤器Filter在拦截器Interceptor执行完后才执行结束,所以过滤器的方法更加靠近浏览器端。

     总结图示

    ① 发送action请求后,Filter的doFilter方法开始执行(此时还未执行完)。

    ② DispatcherServlet会得到web的请求,调用HandlerMapping进行控制器匹配,如果控制器没有对应的action地址,将不会执行Interceptor的方法(如发送demo.do请求时没执行拦截器的方法)。当控制器有对应的请求时会开始执行拦截器的方法。

    ③ Interceptor的preHandler方法执行。

    ④ 控制器的方法执行。

    ⑤ 控制器执行后,将结果(本例中为一个“hello”字符串)发给ModelAndView。

    ⑥ ModelAndView将结果再发送给DispatcherServlet之前,会执行Interceptor的postHandler方法。

    ⑦ DispatcherServlet将ModelAndView返回的结果发送给视图解析器解析,如本例解析得到/WEB-INF/hello.jsp。

    ⑧ 视图解析器将渲染页面准备发送给浏览器前,将执行afterCompletion方法。

    ⑨ 最后,将执行完Filter的doFilter方法。

    参考博客:https://blog.csdn.net/chenleixing/article/details/44573495

    参考博客:https://blog.csdn.net/zxd1435513775/article/details/80556034

  • 相关阅读:
    07. pt-fifo-split
    05. pt-diskstats
    06. pt-duplicate-key-checker
    坑爹的tp-link管理密码设置
    windows核心编程 第5章job lab示例程序 解决小技巧
    FormatMessage将错误代码转换成对应的字符串
    调试 内存查看StringCchCopy的运行前后
    对硬盘扇区的操作,练手代码
    关不掉的窗口
    读取unicode日志文件并清除记录的垃圾文件
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/10549020.html
Copyright © 2011-2022 走看看