springMVC+拦截器、过滤器

https://blog.csdn.net/weixin_44176169/article/details/104852285?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242

https://blog.csdn.net/a745233700/article/details/80963758?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

https://blog.csdn.net/jianyuerensheng/article/details/51258942

MVC模型概述

Model(模型):数据模型,提供要展示的数据。数据Dao+服务层Service
View(视图):进行模型展示
Controller(控制器):接收用户请求,委托给模型进行处理,处理完毕后将返回的模型数据给视图进行展示。其实就是一个调度员的工作。控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

下图中就是SpringMvc较为完整的流程图。其中需要我们实现的是Handler(Controller)中,我们需要做的业务处理。

在这里插入图片描述

  1. 用户点击某个请求路径,发起一个request请求,此请求会被前端控制器(DispatchServlet)处理。
  2. DispatchServlet调用请求处理器映射器(HandleMapping),HandleMapping根据请求的url去查找Handler。
  3. HandleMapping根据配置找到相应的Handler(可能包含若干个Interceptor拦截器),返回给DispatchServlet。
  4. DispatchServlet请求处理器适配器(HandlerAdapter)去执行相应的Handler处理器(常称为Controller)。
  5. 处理器适配器执行Handler处理器。
  6. Handler处理器执行完毕之后会返回给处理器适配器一个ModelAndView对象(SpringMVC底层对象,包括Model数据模型和View视图信息)。
  7. 处理器适配器接收到Handler处理器返回的ModelAndView后,将其返回给前端控制器(Controller调用业务逻辑处理)。
  8. 前端控制器接收到ModelAndView后,会请求视图解析器(ViewResolver)对视图进行解析。
  9. 视图解析器根据View信息匹配到相应的视图结果,反馈给前端控制器。
  10. 前端控制器收到View具体视图后,进行视图渲染,将Model中的模型数据填充到View视图中的request域,生成最终的视图(View)。
  11. 前端控制器向用户返回请求结果。

主要涉及组件

前端控制器 DispatcherServlet:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。

处理器映射器 HandlerMapping:根据请求的URL来查找Handler。用于存放编程时写的@RequestMapping的值及对应的handler处理器。当请求的url过来时,从此映射中找到对应的handler处理器。

处理器适配器 HandlerAdapter:负责执行Handler

处理器 Handler:即我们常说的Controller,需要程序员开发

视图解析器 ViewResolver:进行视图的解析,根据视图逻辑名将ModelAndView解析成真正的视图(view)
视图View:View是一个接口, 它的实现类支持不同的视图类型,如jsp,freemarker,pdf等等


用户向服务器发送请求,请求会到DispatcherServlet,DispatcherServlet 对请求URL进行解析,得到请求资源标识符(URI),然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括一个Handler处理器对象、多个HandlerInterceptor拦截器对象),最后以HandlerExecutionChain对象的形式返回。

 DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

  • HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
  • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等 数据格式化:对请求消息进行数据格式化。
  • 如将字符串转换成格式化数字或格式化日期等 数据验证:
  • 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

拦截器、过滤器

https://blog.csdn.net/huyiju/article/details/83028720

什么是过滤器

过滤器使用filter实现,拦截的是request请求,基于回调,基于servlect规范

依赖容器,拦截的是地址,粒度很大

过滤器Filter:过滤器通过实现Filter接口,实现了过滤器的三个方法,分别是init方法,dofilter方法和destory方法,随着容器的启动和销毁而初始化和销毁,依赖于servlet容器,过滤器拦截的是地址栏请求,过滤器实在进入容器后执行的servlet之前后执行,针对的在处理业务之前的操作。

chain.doFilter(request, response);这个方法的调用作为分水岭。事实上调用ServletdoService()方法是在这个方法中进行的。

什么是拦截器

基于Java的jdk动态代实现的,实现HandlerInterceptor接口。不依赖于servlet容器,

拦截器针对于controller方法,并且能获取到所有的类,对类里面所有的方法实现拦截,粒度更小,拦截器中可以注入service,也可以调用业务逻辑。拦截器是实现了 HandlerInterceptor 的三个方法:preHandlepostHandleafterCompletion

使用场景

过滤器(Filter)通常用于实现通用的、与框架无关的功能,如身份验证、授权、日志记录、请求和响应的数据转换等。

拦截器(Interceptor)通常用于实现与 Spring 框架相关的功能,如验证用户身份、授权、请求参数处理、异常处理等

实现方式

过滤器(Filter)需要实现 javax.servlet.Filter 接口,并实现 init、doFilter 和 destroy 方法。

拦截器(Interceptor)需要实现 HandlerInterceptor 接口(对于请求拦截)或ClientHttpRequestInterceptor 接口(对于客户端请求拦截),并实现相应的方法。

总的来说,过滤器和拦截器在功能上有一定的重叠,但它们的使用场景、处理层级和实现方式有所不同。选择使用过滤器还是拦截器取决于你的具体需求和场景。当你需要处理与框架无关的请求时,可以使用过滤器;当你需要实现与 Spring 框架相关的功能时,拦截器可能是更好的选择。

拦截器、过滤器使用区别

两者都是AOP编程思想的实现,都能够实现权限控制和日志记录等问题的处理,但是两者粒度不同拦截对象不一样

适用范围不同Filter是servlet的规范,只能用于web程序,但是拦截器可以用于application等程序

规范不同Filter是servlet的规范。但是Interceptor是spring容器支撑,有spring框架支持

使用资源不同spring的拦截器由于依赖spring,也是spring的一个组件,因此能够在拦截器中使用spring的任何资源和对象。例如service对象,数据源,事务管理等,通过ioc注入拦截器即可,而filter不能

粒度不同Filter只能在servlet的前后起作用,而拦截器能在方法前后异常前后执行,更加灵活,粒度更小,spring框架程序优先使用拦截器。

拦截器、过滤器的区别

https://blog.csdn.net/huyiju/article/details/83028720

①拦截器是基于java的反射机制的,而过滤器是基于函数回调。

②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  
④拦截器只能对action动态请求起作用(静态请求,例如:不会对js、css、img等静态资源的请求起到拦截作用);而过滤器可以对所有的请求起作用,无法实现细粒度的请求拦截;
  
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

过滤器和拦截器之间的关系如下图,Filter包裹Servlet,Servlet包裹Interceptor

在这里插入图片描述
过滤器的触发时机是容器后,servlet之前,所以过滤器的 doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) 的入参是ServletRequest,而不是HttpServletRequest,因为过滤器在HttpServlet之前。
过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。

**过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。**
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    System.out.println("before...");

    chain.doFilter(request, response);

    System.out.println("after...");
}

这个chain.doFilter(request, response) 作用是将请求转发给过滤器链上下一个对象,下一个对象是指filter,如果没有filter那就是你请求的资源

过滤器应用:

@WebFilter(urlPatterns = "/*") 
@Component
public class EncodingFilter implements Filter { 

        @Override 
        public void init(FilterConfig filterConfig) throws ServletException { 

        }

        @Override 
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
                             FilterChain filterChain) throws IOException, ServletException { 

            //统⼀处理请求和响应的乱码 
            servletRequest.setCharacterEncoding("UTF-8"); 
            servletResponse.setContentType("text/html;charset=utf-8"); 
            filterChain.doFilter(servletRequest,servletResponse); 

        }

        @Override 
        public void destroy() { 

        } 

}

拦截器是被包裹在过滤器之中

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("preHandle");
    return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("postHandle");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    System.out.println("afterCompletion");
}
  • preHandle 这个方法是在过滤器的 chain.doFilter( request, response ) 方法的前一步执行,且在调用Controller之前调用,当返回false后,会跳过之后的拦截器,并且不会执行所有的拦截器 postHandle ,并且调用返回true的拦截器的 afterCompletion 方法

  • postHandle 是调用 Controller 之后被调用,但是在渲染 View 页面之前

  • afterCompletion 是调用完 Controller 接口,渲染 View 完页面后调用,返回true的拦截器都会调用该拦截器的 afterCompletion 方法,顺序相反。

具体流程图:
在这里插入图片描述

在这里插入图片描述

HandlerInterceptor 接口

在HandlerInterceptor接口中,定义了 3 个方法,分别为preHandle()、postHandle()和afterCompletion(),我们就是通过复写这 3 个方法来对用户的请求进行拦截处理的。因此,我们可以通过直接实现HandlerInterceptor接口来实现拦截器的功能。不过在 Spring 框架之中,其还提供了另外一个接口和一个抽象类,实现了对HandlerInterceptor接口的功能扩展,分别为:AsyncHandlerInterceptor和HandlerInterceptorAdapter.

对于AsyncHandlerInterceptor接口,其在继承HandlerInterceptor接口的同时,又声明了一个新的方法afterConcurrentHandlingStarted();而HandlerInterceptorAdapter抽象类,则是更进一步,在其继承AsyncHandlerInterceptor接口的同时,又复写了preHandle方法。因此,AsyncHandlerInterceptor更像是一个过渡的接口。

在实际应用中,我们一般都是通过实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter抽象类,复写preHandle()、postHandle()和afterCompletion()这 3 个方法来对用户的请求进行拦截处理的。下面,我们就详细介绍这个 3 个方法。

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)方法,该方法在请求处理之前进行调用。Spring MVC 中的Interceptor是链式调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor。每个Interceptor的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor中的preHandle方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求做一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔(Boolean)类型的,当它返回为false时,表示请求结束,后续的Interceptor和控制器(Controller)都不会再执行;当返回值为true时,就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的时候,就会是调用当前请求的控制器中的方法。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法,通过preHandle方法的解释,我们知道这个方法包括后面要说到的afterCompletion方法都只能在当前所属的Interceptor的preHandle方法的返回值为true的时候,才能被调用。postHandle方法在当前请求进行处理之后,也就是在控制器中的方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对控制器处理之后的ModelAndView对象进行操作。postHandle方法被调用的方向跟preHandle是相反的,也就是说,先声明的Interceptor的postHandle方法反而会后执行。这和 Struts2 里面的Interceptor的执行过程有点类似,Struts2 里面的Interceptor的执行过程也是链式的,只是在 Struts2 里面需要手动调用ActionInvocation的invoke方法来触发对下一个Interceptor或者是action的调用,然后每一个Interceptor中在invoke方法调用之前的内容都是按照声明顺序执行的,而invoke方法之后的内容就是反向的。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法,也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。因此,该方法将在整个请求结束之后,也就是在DispatcherServlet渲染视图之后执行,这个方法的主要作用是用于进行资源清理的工作。

多个拦截器顺序 @Order(int) int数越小,优先级越高

在这里插入图片描述
springmvc的拦截器实现HandlerInterceptor接口后,会有三个抽象方法需要实现,分别为方法前执行preHandle,方法后postHandle,页面渲染后afterCompletion。

1、当俩个拦截器都实现放行操作时,顺序为preHandle 1,preHandle 2,postHandle 2,postHandle 1,afterCompletion 2,afterCompletion 1

2、当第一个拦截器preHandle返回false,也就是对其进行拦截时,第二个拦截器是完全不执行的,第一个拦截器只执行preHandle部分。

3、当第一个拦截器preHandle返回true,第二个拦截器preHandle返回false,顺序为preHandle 1,preHandle 2 ,afterCompletion 1

demo网址链接~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

总结

一、调用顺序

preHandle按拦截器定义顺序调用

postHandler、afterCompletion按拦截器定义逆序调用

二、调用条件

postHandler在拦截器链内所有拦截器返成功调用(即,如果有多个拦截器,其中一个的preHandle返回false,则所有的postHandler都不会被调用!!!)

afterCompletion只有preHandle返回true才调用(即,如果有多个拦截器,只要自己的preHandler返回true就能调用)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC 中的过滤器拦截器都可以在请求处理之前或之后进行一些特定的操作,但它们的实现方式和作用范围不同。 过滤器是基于 Servlet 规范实现的,在 Servlet 容器中运行,可以拦截所有的请求(包括静态资源请求),并对请求进行处理。过滤器通常用于请求的预处理和后处理,比如编码转换、日志记录、权限校验、资源缓存等。 拦截器是基于 Spring MVC 框架实现的,在 DispatcherServlet 中运行,只能拦截 Spring MVC 的请求(即只能拦截到经过 DispatcherServlet 的请求),并对请求进行处理。拦截器通常用于请求的预处理和后处理,比如权限校验、日志记录、性能监控等。 下面是一个简单的 Spring MVC 过滤器拦截器的示例: ```java // 过滤器实现类 public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化方法 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 处理请求的方法 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); chain.doFilter(request, response); } @Override public void destroy() { // 销毁方法 } } // 拦截器实现类 public class LogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 处理请求前的方法 System.out.println("请求 URL:" + request.getRequestURI()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 处理请求后的方法 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 请求处理完成后的方法 } } ``` 在 Spring MVC 中配置过滤器拦截器: ```xml <!-- 配置过滤器 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>com.example.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置拦截器 --> <mvc:interceptors> <bean class="com.example.LogInterceptor" /> </mvc:interceptors> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值