Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 400|回复: 0

Java框架之SpringMVC 05-拦截器-异常映射-Spring工作流程

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-15 03:06:16 | 显示全部楼层 |阅读模式

    SpringMVC

    拦截器

      Spring MVC也可以使用拦截器对请求进行拦截处理,可以自定义拦截器来实现特定的功能,自定义的拦截器可以实现HandlerInterceptor接口中的个方法也可以继承HandlerInterceptorAdapter 适配器类按照需要那个方法,就实现哪个方法

    过滤器与拦截器区别

      过滤器:过滤器在Servlet之前操作
      拦截器:拦截器在Servlet之后,请求处理器(Controller)之前操作。

    拦截器三个方法

      ① preHandle():这个方法在(Controller)处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回 true;如果不需要再调用其他的组件去处理请求,则返回false。(如果返回false则后续操作都不再执行,类似于过滤器的 doFilter 所以正常情况下不要返回 false)

      ② postHandle():这个方法在(Controller)处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前(在视图渲染之前)被调用,在该方法中对用户请求request进行处理。

      ③ afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后(转发|重定向 之后)被调用,可以在该方法中进行一些资源清理关闭的操作。

    配置拦截器

    <mvc:interceptors>
            <!--   为所有请求设置拦截器 也可用 ref 引用已经装配好的拦截器-->
            <bean id="firstHandlerInterceptor" class="main.controller.FirstHandlerInterceptor"></bean>
            <mvc:interceptor>
                <!--     表示指定拦截器只拦截/test/下的所有请求-->
                <mvc:mapping path="/test/**/"/>
                <!--     表示访问/test/test.do的请求不会触发拦截器-->
                <mvc:exclude-mapping path="/test/test.do"/>
             <!--     为指定的请求设置拦截器 也可用 ref 引用已经装配好的拦截器-->
             <bean id="testInterceptor" class="main.controller.TestInterceptor"></bean> 
            </mvc:interceptor> 
    </mvc:interceptors>

     程序执行顺序

      1. preHandle():执行请求处理器的请求(Controller)方法之前执行。 
      2. 执行请求处理器的请求(Controller)方法
      3. postHandle():执行请求处理器的请求(Controller)方法之后,在视图渲染之前。
      4. 视图渲染
      5. afterCompletion():视图渲染(转发|重定向)之后执行。

    多个拦截器的执行流程

      当存在多个拦截器时的执行顺序,由配置的先后顺序决定。(preHandle() 先配置,先执行) 
      preHandle():与拦截器配置的先后顺序一致
      postHandle():与拦截器配置的先后顺序相反。底层倒序循环调用的
      afterCompletion():与拦截器配置的先后顺序相反。

    preHandle()返回值为false时的工作原理

      第一个拦截器的preHandle()的返回值为false:
        只执行第一个拦截器的prehandle()方法,执行完,return;(后续的方法都不执行) 
      不是第一个拦截器的preHandle()的返回值为false: 
        当前拦截器之前的拦截器的afterCompletion()都会被执行。

      当两个拦截器的 preHandle() 方法都返回 true 时,按照虚线路执行

      当第二个拦截器 preHandle() 方法返回 false 时按照实现路线执行

     异常处理

      在SpringMVC中,无论请求控制器中是否存在异常,都会返回ModelAndView对象

      Spring MVC 通过 HandlerExceptionResolver  处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常

      DispatcherServlet  默认装配的 HandlerExceptionResolver 有 DefaultHandlerExceptionResolver 解析器会自动将标准的Spring MVC异常解析为HTTP错误状态码

      使用 <mvc:annotation-driven/> 配置会装配Spring3.0后新增的异常解析器,实现更精细化处理。如果希望对所有异常进行统一处理或指定某一异常跳转页面,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,可实现跳转到指定页面,并报告异常.

    配置异常解析器

        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <!--    为所有异常定义默认的处理页面,exceptionMappings未定义的,
                    value表示跳转页面,至于文件路径和后缀已经在 viewResolver 中指定-->
            <property name="defaultErrorView" value="error"></property>
            <!--    定义异常处理页面用来获取异常信息的变量名,被存放到 request 域中-->
            <property name="exceptionAttribute" value="exception"></property>
            <!--    需要特殊处理的异常,全类名作为key,异常页文件名作为值,可将不同的异常映射到不同的页面上-->
            <property name="exceptionMappings">
                <props>
                    <prop key="java.lang.NullPointerException">nullPointer</prop>
                </props>
            </property>
        </bean>

    <mvc:annotation-driven/>

      是spring MVC为@Controllers分发请求所必须的,即启用注解驱动,解决了@Controller注解使用的前提配置。

      同时它还提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB,读写JSON的支持(Jackson)。

      它会自动为我们注册了很多的Bean,最重要的就是RequestMappingHandlerMappingRequestMappingHandlerAdapter

        第一个是HandlerMapping的实现类,它会处理@RequestMapping 注解,并将其注册到请求映射表中。
        第二个是HandlerAdapter的实现类,它是处理请求的适配器,说白了,就是确定调用哪个类的哪个方法,并且构造方法参数,返回值。

      简单的说,用什么注解,就需要声明对应的BeanPostProcessor。而Spring为我们提供了一种极为方便注册这些BeanPostProcessor的方式,即使用各种标签来隐式地向 Spring 容器注册

    Spring工作流程

      相关类

        HandlerMapping(请求处理器的映射对象):定义了一个所有请求和请求处理器对象之间的映射关系对象

        HandlerExecutionChain(请求处理器执行链对象):定义了 当前请求处理器对象,和所有拦截器对象。

        HandlerAdapter(请求处理器的适配器对象):调用当前请求处理器的请求方法。

      执行流程对应下图理解

        1)用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获

        2)DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI):判断请求URI对应的映射
          ① 不存在:
            再判断是否配置了 mvc:default-servlet-handler:
            如果没配置,则控制台报映射查找不到,客户端展示404错误
            如果有配置,则执行目标资源(一般为静态资源,如:JS,CSS,HTML)
          ② 存在:
            执行下面流程

        3)根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

        4)DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。

        5)如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法【正向】

        6)提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
          ① HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
          ② 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
          ③ 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
          ④ 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

        7)Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;

        8)此时将开始执行拦截器的postHandle(...)方法【逆向】

        9)根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet,根据Model和View,来渲染视图

        10)在返回给客户端时需要执行拦截器的AfterCompletion方法【逆向】

        11)将渲染结果返回给客户端

     

    Spring与SpringMVC

      spring容器与springMVC容器对象的关系

        springMVC容器对象,默认交个DispatcherServlet管理

        spring容器对象,需要我们管理(交给Listener管理)

      spring容器对象描述

        Root WebApplicationContext: root of context hierarchy

      springMVC容器对象描述

        WebApplicationContext for namespace 'springDispatcherServlet-servlet':root of context hierarchy

      spring容器对象是父,springMVC容器对象是子。子类可以直接调用父类方法。

      SpringMVC 的 IOC 容器中的 bean 可以引用 Spring IOC 容器中的 bean.反之则不行. 

      在web应用下,获取spring容器对象方式

    ServletContext servletContext = httpSession.getServletContext();
    ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);

     

      在web应用下,获取springMVC容器对象可直接通过装配属性的方式获取

        @Autowired
        private XmlWebApplicationContext context;

    配置文件

      若 Spring 的 IOC 容器和 SpringMVC 的 IOC 容器扫描组件的包有重合的部分, 就会导致有的 bean 会被创建 2 次,可通过一个包含一个排除的方式解决

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-2 04:31 , Processed in 0.060809 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表