IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringMvc二刷 -> 正文阅读

[Java知识库]SpringMvc二刷

SpringMvc二刷

b站视频:https://www.bilibili.com/video/BV1Ry4y1574R (92~95的dispatcherServlet源码解析不是很懂,太顶了)

图片

在这里插入图片描述

  • MVC简介

    • model:模型,模型层,指JavaBean
      • 实体类Bean:用于存储数据的
      • 业务处理Bean:指service和Dao对象,用于处理业务逻辑和数据访问
    • view:视图层,指工程里面的html和lsp页面
    • controller:控制层,指工程中的servlet,作用是接受请求和响应浏览器

    MVC工作流程:

    用户通过视图层(前端浏览器的html页面)发送请求到服务器,在服务器中请求 被Controller接受,Controller调用对应的Model(实体类Bean和业务处理Bean)层处理请求,处理完毕后将结果返回到Controller,Controller再根据请求处理的结果找到对应的View试图,渲染数据后最终响应到浏览器。

  • spirngmvc时候,控制层使用@controller仅为注册组件,还需要手动在resource下的springMVC.xml配置文件里面进行组件扫描(Component-scan base-package=“com.ws.mvc.controller”),相当于先要存在这个组件,然后再选择是否使用该组件。

  • MVC工作更详细流程:

    浏览器发送请求,若请求地址符合前端控制器的url-pattren,该请求就会被前端控制器DispatchServlet处理,前端控制器会读取SpringMVC核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中@RequestMapperin注解的value属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法,处理请求的方法需要返回一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成(工作流程见下面),通过Thymleaf对试图进行渲染,最终转发到试图所对应页面

  • 视图名称被视图解析器解析流程:视图解析器(Thyleaf)也需要在springMvc.xml里面进行配置,并且还要配置前缀后缀,所以当控制层给dispatcherServlet返回该视图名称,会给手动拼接前缀(文件地址),后缀(。jsp),然后进入该页面

  • @RequestMapping("/test")
    public String testServlet(HttpServletRequest request)(){}
    关于上述接口传参为HttpServletRequest request()的时候,具体是如何处理的。
      
    	在理解了上面mvc工作流程之后,结合图片,就会知道,到这一步匹配传参的时候就已经经过了:请求-->dispatcherServlet-->HandlerMapping(找到接口地址)-->返回dispatcherServlet-->再进入接口处理的组件HandlerAdapter.
        
        到这步之后,假如我们的接口传参为HttpServletRequest,就会将DispatcherServlet获取到的请求参数自动覆盖掉这个传参的HttpServletRequest,我们就可以使用这个request了。
        (但是呀,我们的直接就能使用@RequestParm参数,不需要使用HttpServletRequest

image-20220325160431727

@Requestparam详解

  • @RequestParam()是将请求参数和控制器方法的形参创建映射关系

    @RequestHeader(“Host”)String host; 是将请求头信息和控制器方法的形参创建映射关系

    @CookieValue是将cookie数据和控制器方法形参创建映射关系

characterEncodingFlieter编码过滤器详解

  • 出现乱码问题
    • 原因:请求中的某个参数如:sex=男,到控制器的形参接受的时候可能会出现编码错误
    • 乱码问题也分get请求和post请求
    • get请求的乱码问题在Tomcat的配置文件里面设置,通常是被处理过的
    • 所以说我们通常指的都是Post请求的乱码问题
    • 所以这里我们要想:当请求来服务器的时候,是DisPatcherServlet接受请求在前,之后再是我们的控制层形参获取经由dispatcherServlet转发的请求,所以这里我们要在dispatcherServlet获取请求之前就进行编码处理
      • 这里就要考虑服务器的三大组件:监听器,过滤器,Servlet
      • 其中执行顺序为:ServletContextLinster–>过滤器–>Servlet
      • 其中的ServletContextLinster是监听器,旨在监听Servlet的创建和销毁,只会执行一次
      • 所以就要在过滤器里面配置
      • 所以就要在springmvc.xml里面进行组件注册

tomcat自带的web.xml

  • tomcat里面的conf也有web.xml,这个文件对于所有项目都生效的
    项目里面的web.xml和它相同的,但是就近原则,如果项目自己配置了web.xml则已项目自己配置的web.xml为主

  • 解析tomcat里面的web.xml
    1 加载DefaultServlet–服务器启动的时候初始化

    1. 加载JSpServlet–处理对于JSp页面的访问
    2. 1中加载的DefautlServlet的映射
      default
      /

    注意事项:!!!

    这里就出现问题了,我们自己项目也配置了这个DefaultServlet但是这个为dispatcherServlet
    我们原来默认的DafaultSrevlet(tomcat里面的web.xml)是可以访问到静态资源的
    但是我们自己项目里面配置的默认Servlet是dispatcherServlet这个遇到请求直接就去controller层找方法去了
    是没有访问静态资源的能力的
    所以我们在disptacherServlet配置web.xml里面需要自己去配置允许访问静态资源

    需要下面的两行一起配置,缺一不可
    mvc:default-servlet-handler–只有他的话,代表请求只能访问静态路径
    mvc:annotation-driven–必须两行注解一起使用,代表着dispatcher先进行路径映射,
    当映射不到正确的url的时候,把处理权交给默认的defaultServlet去静态资源那边处理

@RestController底层研究—@ResonpseBody

  • 现在能够理解两个注解@RequestBody和@ResponseBody
    两个实体类:requestEntity和reponseEntity到底是什么了

    • 首先理解:@RequestBody和requestEntity是将请求报文转为java对象
      @ResponseBody和eponseEntity是将Java对象转化为响应报文格式

    • 然后就是:@RequestBody (用在控制器形参上面) ==请求体
      请求到接口的时候,形参为一个Po,使用@ReqeustBody将请求中的请求体信息拿出来,封装成形参里面的po(这里使用String也是可以接收的,输出entity.toString(),只是不推荐)

    image-20220330140854952

    • 然后就是: @ResponseBody (用在控制器类上面):只要在控制器Controller方法里面有这个注解,那么这个controller整个类里面的方法,返回的所有Java数据都会直接封装到响应报文的响应体中去。

    • 这里重点知道每个controller里面的@RestController是干嘛的吧
      @RestController是@ResponseBody和@Controller和其他注解的集合注解
      所以标注了这个注解的所有方法返回值都会直接被封装到响应报文的请求体里面去!!

    • RequestEntity ==请求类=请求头+请求体

      这个主要作用就是用在控制层方法的形参,用于接收请求的完整报文image-20220330140909055

    • ResponseEntity :用户控制器方法的返回值类型,控制器方法的返回值就是响应到浏览器的响应报文。

JSON的作用!!!

  • !!!!!JSON到底为什么产生!!!!!!!!

    • 方法返回值为实体类user的时候,在标注了@ResponseBody的情况下,
      当user放到响应报文体里面去的时候,浏览器是获取不到这个的,(浏览器只能获取到简单的数据格式:字符串)会直接报错500(httpmessageNotwriterableException:no convert found for return value of type:com.ws.bean.User)
      这个时候就需要一种固定格式 -能够完整的展示User的所有信息,而且还能被浏览器端访问----JSON

    • 想要在上述问题解决返回值要为json格式需要几步

      1. 导入jackson的依赖
      2. web.xml中配置mvc注解驱动mvc:annotation-driven/(重点就是这步,此时会在HandlerAdapor中自动装配一个消息转换器:Mappingackson2HttpMessageConverter,可以将响应到浏览器的java对象转化为JSon格式的字符串)
      3. 处理器方法上加@ResponBody
      4. 将控制器方法返回值变为实体类,就会自动转化为JSON格式的字符串!!!(这里不是json对象哦,是json形式的字符串!!!,你要是直接传json到浏览器他还是展示不出来,只能是json的字符串)

      (上面那么多步其实234都已经做过了,所以实际项目上只要加入jackson的包就可以直接实现实体类转json的过程了)

回顾json

json就是一种数据交互格式

xml其实也是数据交互格式,只不过xml更多的用户配置文件的编写

json编写方便,而且解析方便

dom4j解析xml文件,会将整个xml进行一层一层的解析,从根标签开始

ServletContext:servlet上下文

ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。

img

springmvc进行文件上传

  1. maven依赖:commons-fileupload
  2. 前端传文件 type=file ,enctype=“multipart/form-data”
  3. 后端接受文件 MultipartFile file (注意这里不能直接将请求中的文件直接转化为multipart形式,需要配置文件上转解析器,才能转化)
  4. 配置文件上传解析器,将上传的文件封装为MultipartFile

拦截器Interceptor:拦截控制器方法的

过滤器是在disaptcherServlet之前的,过滤所有的请求

拦截器是在dispatcherServlet–>Controller的controller前后

? 分为preHandler,postHandler,afterHandler(Handler一直可以看成Controller)

请求–>filter过滤器(过滤所有请求)–>dispatcherServlet–>Controller

  • preHandler:控制器方法之前执行
  • Posthandler:控制器方法一起执行
  • afterHandler:控制器方法执行完返回ModelAndView之后执行的

这里有个思想在这:

我们知道了拦截器的执行时间,想要模拟一个这个拦截器,怎么去源码里面看

!!!去dispatcherServlet源码里面去看,找到handlerMapper之后,handlerAdaptor附近的代码

  1. 双击shift,搜索dispatcherServlet
  2. alt+7找到所有方法,找到doDispath方法(源码1060行附近)
  3. 找到applyPreHandler,applyPostHandler

image-20220330155455835

通过上面的拦截器去理解mybatis的pageInteceptor:分页插件拦截器

image-20220330160041595

在写mybatis的时候,我们并没有写任何关于分页的代码,只是加载了分页插件(拦截器),当有控制器方法去使用这个插件提供的page方法的时候,就会自动执行这个拦截器 进行查询数据时候的分页功能

自定义拦截器

image-20220330162149091

  • 自己编写一个拦截器继承HandlerInteceptor,实现他的三个方法
  • 然后去web.xml注册到组件里面(注册+扫描才行)
  • 然后就去web.xml里面进行各种路径配置

image-20220330162746714

  • 被排除的就不会走拦截器,其他的都会走拦截器
  • 并且/*之代表着一层关系
    • 像/s /a /d 等等
    • 但是不代表着/d/d /d/g这种两层的
    • 假如拦截的是/**那么就相当于拦截所有的请求,此时就与过滤器相同意思了

多个拦截器怎么生效,什么顺序

先自定义配置两个拦截器: 先在web.xml配置firstInteceptor再配置secondIntecptor

执行的顺序为:

image-20220330170700998

  • preHandler是按照配置顺序来执行的
  • PostHandler和afterhandler是配置的反顺序执行的
  • 原理就是:首先获取所有的拦截器,然后for循环进行遍历,preHandler里面i++,剩下两个是i–执行
  • image-20220330172016749

image-20220330171814167

当有五个拦截器12345,3的preHandler返回的是false(即进行拦截),那么会执行哪些拦截器呢

preHandler会执行:123的

postHandler一个都不会执行

afterHandler会执行:2 1 的

最终顺序就是Pre1 pre2 pre3 after 2 after1这五个

异常处理解析器(包含@ControllerAdvice和@ExceptionHandler)

当页面出现某个指定的异常的时候,我们可以设置指定的跳转页面

  • 基于配置的异常处理:

image-20220330175217121

image-20220330175242351

这样在执行上述请求的时候,当执行到1/0的时候,发现了arithmeticException就会自动跳转到error.html页面里面

web.xml里面还能配置error页面里面具体输出的信息等等。。

  • 基于注解的异常处理:(重点)

image-20220330175832626

自定义一个异常处理类:

@ControllerAdvice相当于@Component标注该类为组件

@ExceptionHandler相当于之前配置文件里面写的key ,value

当哪个控制器方法抛出这个异常的时候,那么返回的modelAndView全权由这个@Exceptionhandler来返回

SpringMvc配置文件配置了哪些东西(重点!!!!)

不仅要看是如何配置的,还要看配置的时候是用的还是mvc:,这个跟下面的webConfig配置类有很大关系!!

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描组件-->
    <context:component-scan base-package="com.atguigu.mvc"></context:component-scan>

    <!--配置视图解析器-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <mvc:view-controller path="/" view-name="index"></mvc:view-controller>


    <mvc:default-servlet-handler />

    <!--开启mvc的注解驱动-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- 处理响应中文内容乱码 -->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="defaultCharset" value="UTF-8" />
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html</value>
                        <value>application/json</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!--配置文件上传解析器,将上传的文件封装为MultipartFile-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

    <!--配置拦截器-->
    <mvc:interceptors>
        <ref bean="firstInterceptor"></ref>
        <ref bean="secondInterceptor"></ref>
        <!--<bean class="com.atguigu.mvc.interceptors.FirstInterceptor"></bean>-->
        <!--<ref bean="firstInterceptor"></ref>-->
        <!--
            <mvc:interceptor>
                <mvc:mapping path="/**"/>
                <mvc:exclude-mapping path="/"/>
                <ref bean="firstInterceptor"></ref>
            </mvc:interceptor>
        -->
    </mvc:interceptors>

    <!--配置异常处理-->
    <!--<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
        &lt;!&ndash;设置将异常信息共享在请求域中的键&ndash;&gt;
        <property name="exceptionAttribute" value="ex"></property>
    </bean>-->

</beans>

1 .扫描组件

2.视图解析器(跳转到success,自动寻找到success.html)

3.view-controller (初始时项目路径为“/”的时候,访问的页面)

4.default-servlet-handler(处理静态资源)

5.mvc注解驱动

6.文件上传解析器(multipartFile 形参接收文件类型)

7.异常处理

8。拦截器

public class webConfig implements WebMvcConfiguer到底啥意思

在看这个之前,一定要仔细了解以下springmvc里面的web.xml里面配置的各种东西

在Springmvc里面使用配置类代替web.xml

相当于用配置类代替配置文件

springmvc配置文件转配置类的时候,配置文件以标签注册的可以直接在配置类里面使用同样的注册,但是以注册的各种东西(主要是各种解析器)都需要通过实现webMvcConfigure接口来实现

如:使用webMvcConfigure接口实现拦截器:

image-20220331155654896

如:使用webMvcConfigure接口实现defaultServletHandler

image-20220331155703117

如:使用webMvcConfigure接口实现view-controller

image-20220331155715940

如:使用webMvcConfigure接口实现异常处理

image-20220331155727166

springmvc配置文件转配置类的时候,配置文件以标签注册的可以直接在配置类里面使用同样的注册,但是以注册的各种东西(主要是各种解析器)都需要通过实现webMvcConfigure接口来实现

如:使用webMvcConfigure接口实现拦截器:

[外链图片转存中…(img-AuDE87In-1648713497573)]

如:使用webMvcConfigure接口实现defaultServletHandler

[外链图片转存中…(img-Kzx53XVr-1648713497573)]

如:使用webMvcConfigure接口实现view-controller

[外链图片转存中…(img-CQpuAZI0-1648713497573)]

如:使用webMvcConfigure接口实现异常处理

[外链图片转存中…(img-UVI9UD5P-1648713497573)]

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:11:18  更:2022-04-01 23:14:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:19:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码