【学习笔记】SpringMVC工作原理

108 阅读2分钟

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

使用CharacterEncodingFilter

  • SpringMVC底层默认处理响应乱码

  • SpringMVC处理请求乱码步骤

    1. 注册CharacterEncodingFilter

      • 注册CharacterEncodingFilter必须是第一Filter位置
    2. 为CharacterEncodingFilter中属性encoding赋值

    3. 为CharacterEncodingFilter中属性forceEncoding/forceRequestEncoding赋值

<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--   设置编码为UTF-8     -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    <!--   解决请求与响应乱码     -->
        <init-param>
    <!-- 调用方法setForceRequestEncoding,这里只是指定request,底层已经处理相应乱码了,可能会出现冲突-->
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

源码解析SpringMVC工作原理

视图解析器对象【ViewResolver】

  • 概述:SpringMVC中所有视图解析器对象均实现ViewResolver接口
  • 作用:使用ViewResolver将View对象从ModelAndView中解析出来。

    • ThymeleafViewResolver的837行代码

      //底层使用反射的方式,newInstance()创建视图对象
      final AbstractThymeleafView viewInstance = BeanUtils.instantiateClass(getViewClass());
      

视图对象【View】

  • 概述:SpringMVC中所有View对象均实现View接口。

  • 作用:视图渲染

    • 将数据共享到域中【request、session、application(ServletContext)】
    • 跳转路径【转发或重定向】

源码解析:

  • 无论方法返回是ModelAndView还是String,最终SpringMVC底层,均会封装为ModelAndView对象【前端控制器调用Controller的入口】

    //DispatcherServlet的1061行代码
    ModelAndView mv = null;
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
  • SpringMVC解析mv【ModelAndView】

    //DispatcherServlet的1078行代码
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    
  • ThymeleafView对象中344行代码【SpringMVC底层处理响应乱码】

    //computedContentType="text/html;charset=UTF-8"
    response.setContentType(computedContentType);
    
  • WebEngineContext对象中783行代码【SpringMVC底层将数据默认共享到request域】

    this.request.setAttribute(name, value);
    

\

视图控制器&重定向&加载静态资源

视图控制器

步骤

  1. 添加mvc:view-controller标签

  2. 添加mvc:annotation-driven标签

    有20+功能,配置后可以解决其他请求路径失效的问题。

  • 示例代码:
<!--    添加视图控制器,为指定URL映射视图-->
    <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
    <mvc:view-controller path="/rest" view-name="rest_crud"></mvc:view-controller>
    <mvc:view-controller path="/request" view-name="request"></mvc:view-controller>
​
    <mvc:annotation-driven></mvc:annotation-driven>

重定向

重定向页面不可以写在Web-INF下。不使用视图解析器解析资源

语法:return "redirect:/ xxx.html";

发现报错404。此时我们需要将资源加载到服务器。

加载静态资源

  • DefaultServlet加载静态资源到服务器。

    • 静态资源:html、css、js
    • tomcat-> conf-> web.xml关键代码如下:

      <servlet>
              <servlet-name>default</servlet-name>
              <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
              <init-param>
                  <param-name>debug</param-name>
                  <param-value>0</param-value>
              </init-param>
              <init-param>
                  <param-name>listings</param-name>
                  <param-value>false</param-value>
              </init-param>
              <load-on-startup>1</load-on-startup>
          </servlet>
      <servlet-mapping>
              <servlet-name>default</servlet-name>
              <url-pattern>/</url-pattern>
          </servlet-mapping>
      
  • 问题原因:

    • 表层原因:html请求被DispatcherServlet拦截,但是没有找到请求处理的对应方法,但是请求静态资源本来就不需要处理方法。
    • 深层次:DispatcherServlet与默认DefaultServlet配置均为/,导致DispatcherServlet中配置将DefaultServlet中配置的/覆盖了。【导致无法加载静态资源】
  • 解决方案:

        <!--  解决重定向时的静态资源加载问题  -->
        <mvc:default-servlet-handler></mvc:default-servlet-handler>
        <mvc:annotation-driven></mvc:annotation-driven>
    

    \