SpringMVC框架的学习

Updated on with 0 views and 0 comments

SpringMVC框架的学习

SpringMVC框架

springmvc介绍

  1. MVC --- (属于表现层)三层中
  2. 开发的历程:Model1阶段 Model2阶段 mvc 三层架构 分布式 微服务
  3. Springmvc --- Spring-webmvc,是spring 框架的一个子模块,轻量级、开源的、应用于企业级 web 项目的开发的、表现层框架、底层封装了 servlet,基于 MVC 分层思想。
  4. springmvc 的执行流程(图为重点,虚框为mvc执行流程)

favicon

image-20210715095652702


前端控制器必须有。核心红色


映射器 适配器注释了也可以运行(框架可以自己找)

如果需求多了 需要使用了必须配置
映射器和适配器的替代品
mvc:annotation-driven标签(不能同时存在)

后端控制器自定义的类。绿色需要自定义实现,可以有很多


视图解析器,配置会产生变化


渲染不用配置


适配器模式

  1. springmvc 框架中涉及的模式

    适配器模式:接口、抽象类、实现类

  2. springmvc 流程中涉及的 springmvc组件(组成元件、组成元素)

    1)前端控制器

    前端控制器是执行流程的中心,也是执行流程的出入口,前端的控制中心,配置一次、加载 springmvc 配置文件,不处理请求。

    2)映射器

    可以不配置、框架底层到 properties 文件中自动加载,也可以使用注解驱动代替配置,查找映射关系(哪个后端控制器处理哪个请求)

    3)适配器

    可以不配置,框架底层到 properties 文件中自动加载,也可以使用注解驱动代替位置,起到适配的作用,可以调用不同的后端控制器(例如tpec口可以连接不同设备)

    4)后端控制器

    需要自定义,可以有很多,其中的方法是处理某个请求的具体位置,后端控制器可以和业务层交互,可以封装模型和视图名

    5)视图解析器

    可以不配置,框架到 properties 文件自动加载,也可以配置(其他配置需求),通过视图名查找视图文件(文件被封装到视图对象中 View 类型的对象)

    6)mvc 注解驱动

    代替上面的映射器和适配器,也可以提供其他相关配置

后端控制器类

  1. 类中方法可以设置的返回值类型有哪些?

    1)ModelAndView

    A、特点:使用 ModelAndView 作为方法返回值的类型,可以使用 ModelAndView 类型的对象设置模型数据和视图名;被设置到 ModelAndView 中的模型数据最后会转入 request 域对象;响应方式为转发方式;会经过流程中的视图解析器。

    2)void

    A、特点:使用void作为方法的返回值类型,那么通过原生的 request 和 session 设置数据;响应方式可以转发、重定向;不在经过视图解析器

    sendRedirect 重定向不能访问WEB-INF 路径,重定向 / 代表项目根目录。

    3)String

    A、默认

    可以通过 Model(接口)、ModelMap(实现类)、Map 设置模型数据;数据同样转入 request;视图名就是返回值;是转发响应方式;经过视图解析器

    B、关键字设置:forward(转发) redirect(重定向)【冒号分割】

    与原生redirect不同,带了项目名

    RedirectAttributes 重定向参数(底层还是 session 传递 参数),

    addFlashAttribute("name",xxx)可以重定向传递参,结合**@ModelAttribute**("name")注解用形参String xxx获取,

    可以通过 Model(接口)、ModelMap(实现类)、Map 设置模型数据;数据同样转入 request;关键字添加在返回值里面,返回值是视图名或者是URL;不经过视图解析器

    @ModelAttribute 从域对象获取值

    @ResponseBody 声明是异步请求和响应,框架底层会借助jackson实现对象转json串,前端jQuery中底层也有操作:json串转回对象

    jackson-databind 2.9.10版本

    高版本 springboot 需求

    4)实体类、集合等相关类型 -- 通常结合异步操作

    A、特点:和异步结合、传递过程中使用 json 串(表单、超链接传递、ajax接收)(从后端控制器向也面传数据和从页面向后端传数据)

    (原生异步请求JS对象XHR createXHR open、send、get

    responseText

    XMLHttpRequest)

    1. open(method, url, async) 方法需要三个参数:
    
      method:发送请求所使用的方法(GET或POST);与POST相比,GET更简单也更快,并且在大部分情况下都能用;然而,在以下情况中,请使用POST请求:
    
    无法使用缓存文件(更新服务器上的文件或数据库)
    向服务器发送大量数据(POST 没有数据量限制)
    发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
     url:规定服务器端脚本的 URL(该文件可以是任何类型的文件,比如 .txt 和 .xml,或者服务器脚本文件,比如 .asp 和 .php (在传回响应之前,能够在服务器上执行任务));
    
     async:规定应当对请求进行异步(true)或同步(false)处理;true是在等待服务器响应时执行其他脚本,当响应就绪后对响应进行处理;false是等待服务器响应再执行。
    
    2. send() 方法可将请求送往服务器。
    
    3. onreadystatechange:存有处理服务器响应的函数,每当 readyState 改变时,onreadystatechange 函数就会被执行。
    
    4. readyState:存有服务器响应的状态信息。
    
    0: 请求未初始化(代理被创建,但尚未调用 open() 方法)
    1: 服务器连接已建立(open方法已经被调用)
    2: 请求已接收(send方法已经被调用,并且头部和状态已经可获得)
    3: 请求处理中(下载中,responseText 属性已经包含部分数据)
    4: 请求已完成,且响应已就绪(下载操作已完成)
    5. responseText:获得字符串形式的响应数据。
    
    6. setRequestHeader():POST传数据时,用来添加 HTTP 头,然后send(data),注意data格式;GET发送信息时直接加参数到url上就可以,比如url?a=a1&b=b1。
    
    PS:Fetch polyfill 的基本原理是探测是否存在window.fetch方法,如果没有则用 XHR 实现。
    

    5)四种返回值类型的对比

    A、数据的处理:ModelAndView 直接封装数据;void 是使用原生 request 或者 session 封装数据;String 是 Model、ModelMap、Map 封装数据;实体类或者集合类型是直接返回数据

    B、视图处理:ModelAndView 直接封装视图名;void是使用 request 或者 response 封装视图;String 返回值就是视图名;实体类或者集合不需要设置页面

  2. 传参 -- 参数传递、参数绑定(从也面向后端控制器传递数据)

    1)主要介绍在页面把数据送到后端控制器之后,后端控制器如何接收数据

    2)方式:原生 request 方式、

    同名形参的方式

    (框架借助 ioc、di req.getParameterNames实现)、不同名形参方式、

    @RequestParam 实现名称匹配

    属性属性释义
    value请求参数名称(映射到参数)
    required是否必须包含参数,默认true
    defaultValue没有提供参数,使用指定的默认值

    使用实体类封装、使用数据封装、使用集合封装

    RequestMapping 默认可以缺省.do配置(会自动补齐)

传参 -- 参数绑定-- 重点

  1. 实体类

    1)实现

    同名形参,表单名和实体类字段名一致

    2)中文乱码处理方式

    超链接 get 请求方式中文没问题(Tomcat 版本问题)

    表单 post 请求方式 中文乱码

    过滤器配置,框架提供好

    <!-- 配置全局过滤Filter-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!-- 所有请求都被过滤-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    3)在参数传递过程中,可能发生日期类型转换问题,如何解决?

    局部和全局方式

    A、局部方式是框架提供的

    @DateTimeFormat(pattern="yyyy-MM-dd") 将指定格式转成日期格式,要求送来的格式正确。(缺点每个地方都要加入)

    (400 状态码 代表坏请求 请求参数有问题,在此是类型转换问题)

    B、全局方式是自定义的

    先自定义一个日期转换的类 实现接口 Converter

    public class DateConverter implements Converter<String, Date> {
        @Override
        public Date convert(String dateStr) {
            // 将日期字符串转换成日期对象 返回
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date date = null;
            try {
                date = format.parse(dateStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
    
        }
    }
    

    转换器工厂:可以包含多种,自定义、框架提供

    <bean id="conversionService" class="org.springframework.context.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.bh.converter.DateConverter"></bean>
            </set>
        </property>
    </bean>
    

    工厂注册:

    <mvc:annotation-driven conversion-service="conversionService"/>
    
  2. 数组

    同数组名即可(底层request.getParameterValues)

  3. 集合 -- list、set、map

    集合需要绑定在对象上,而不能直接写在Controller方法的参数中。

    1)List 集合接收数据

    taglib

    c 核心标签

    c:forEach 做便利输出

    items 结合 EL 表达式

    var

    varStatus 下标 借助EL表达式 .index 获取下标

    fmt 格式化标签

    fmt:formatDate

    value pattern,做日期格式化

    单双引号嵌套 防止错误

    PojoVO 设置 集合对象pojo 封装属性List<>,专门接收对象(前端加索引下标确定对象,动态下标)

    2)set 集合接收数据

    局限性 VO类 必须 newHashSet,并且构造方法add对象。

    3)map集合接收数据

    map[key名].对象属性

  4. 异步

    1)从页面向后台传递的数据以 json 串方式传递

    // 自定义json串
    var jsonData = "[{'uid':1003,'uname':'张飞','upwd':'123'},{......}]";
    
    // 异步请求
    $.ajax({
        url:"",
        type:"post",
        data:jsonData,
        dataType:"json",
        contentType:"application/json;charset=UTF-8",
        cache:false,
        success:function (obj) {
            console.log(obj);
        }  
    });
    

    @RequestBody 把 json 串转成对象 底层还是jackson

    异步加@ResponseBody

    // json串转对象
    public void xx(@RequestBody 对象) {
        xxxdo
    }
    

编程 -- 写项目的风格 -- restful

  1. REST 风格 (英文:Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

    直译:表现层状态转换

  2. 是指资源发生状态转换,在表现层发生;即资源在表现层发生状态转换。

  3. http://域名/xxxx

    http 协议 无状态协议(不知道从前、当前、未来的状态)

    1)网络上:URL对应资源,需要请求什么资源就对应URL,在资源请求过程中,会发生 由当前所处的状态转换成另一种状态,资源需要知道自己下一个要转换的状态是哪种状态,但是 URL 中 http 协议不带有状态信息,直接使用 http 协议不能告知资源要转换成哪种状态,解决?

    http 协议含有不同的请求方式,所以利用不同的请求方式来告知资源下一个要转换状态是什么

    2)请求方式和对应状态

    有不同的请求方式(8个?)

    Get 请求方式 查询状态 对应(资源变成查询状态、实际上就是实现资源的查询)

    Post 请求方式 增加状态 对应(资源变成增加状态,实际上对应就是资源的增加)

    Delete 请求方式 删除状态 对应(资源变成删除状态,实际上对应就是资源的删除)

    Put 请求方式 修改状态 对应(资源变成修改状态,实际上对应就是资源实现了修改)

    3)简而言之:如果采用 restful 风格来实现项目,那么设计 URL 的同时还要设计对应的请求方式

    使用"url+请求方式"表示一次请求目的

  4. restful 风格的 URL 样式

    1)传统 URL 和参数的格式

    http://localhost:8080/项目名/资源名

    http://localhost:8080/项目名/资源名.do

    http://localhost:8080/项目名/资源名?key1=value&k2=value2

    2)restful 风格的 URL 和参数的格式

    http://localhost:8080/项目名/资源名(一般不添加扩展名,多采用名词复数做资源名)

    http://localhost:8080/项目名/资源名/value1/value2/......

  5. 入门案例 -- springmvc 支持 result 风格

    *需要DispatcherServlet 路径由 .do 改为 /

    / 代表匹配所有(除了jsp页面请求)不能直接进入jsp页面

    1)使用 @GetMapping 只处理Get请求,表示资源要转为查询状态,资源查找

    405 请求不支持

    2)使用 @PostMapping 只处理Post请求

    @PathVariable("xx") 从URL中通过指定变量名找到值,并注入给形参

    @GetMapping("xxx/{id}/{name}")
    
    public String xxx(@PathVariable("id") int uid,@PathVariable("name") int uname,) {
    
    }
    

    3)post 请求 数据和 URL 分离 不用串入 URL

    put、delete http 没有真正意义上实现

    是spring模拟的 格式如下

    <!-- 固定格式-->
    <!-- 由post模拟put请求,put请求是被模拟-->
    <form action="xxx" method="post">
    <!-- 隐藏文本框-->
    <input type="hidden" name="_method" value="PUT">
    </form>
    

    @PutMapping 只处理Put请求

    加入过滤器在前端控制器上(HiddenHttpMethodFilter)

    <filter>
        <filter-name></filter-name>
        <filter-class>xxx.HiddenHttpMethodFilter</filter-class>
    </filter>
    

    4)@DeleteMapping 只处理Delete请求

    Tomcat maven插件方式没问题 Tomcat 原生方式会出错(jsp页面只能被get、post请求访问、put、delete不能请求jsp页面)

    类上加 RequestMapping 抽取方法相同的映射地址,框架自动将类片段和方法片段拼接匹配

    5)*DispatcherServlet 路径由 .do 改为 / 产生的问题

    • 静态资源也被后端控制器处理,倒置无法被读取

      正常情况不需要 Controller 去响应

    • 两种解决方式:

      <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
      
      <mvc:default-servlet-handler></mvc:default-servlet-handler>
      

注解的总结

  1. @Controller:IOC 实现

  2. @RequestMapping:实现 url 请求和方法匹配

  3. @GoMapping:实现请求的方法和匹配,只处理 get 请求方式

  4. @PostMapping:实现请求的方法和匹配,只处理 post 请求方式

  5. @DeleteMapping:实现请求的方法和匹配,只处理 delete 请求方式

  6. @PutMapping:实现请求的方法和匹配,只处理 put 请求方式

  7. @ResponseBody:声明是异步请求,对象转 json 串,返回

  8. @ModelAttribute:从域对象获取数据;可以把方法的返回值数据暴露给视图(注解在方法上,方法返回值会返回到所有的页面,数据统一管理思想)

  9. @RequestParam:传参时不同名实现匹配;默认值,是否必须传参

  10. @RequestBody:从页面向后台串 json 串时,将 json 串转对象

  11. @DatetimeFormat:实现局部的字符串类型转日期类型

  12. @PathVariable:实现 restful 风格中从 url 里面获取数据,注入给指定形参

  13. @CookieValue:从 cookie 中获取数据

  14. @SessionAttributes:将数据转存到 session,在类上加注解,键值对(value="xxx键值对名")或者实体类型

    (EL表达式${sessionScope.xxx}只从session拿数据)

注解的总结

  1. @CookieValue

    1)从 cookie 中通过指定的 key 获取数据

    2)cookie 会话跟踪 (请求时候电脑信息送到对方)sessionId 借用 cookie 送回服务器端

    3)使用

  2. @RequestHeader

    1)获取请求头中的信息

上传和下载

  1. 上传 -- 从用户端把文件上传到服务器端

    1)注意事项

    A、前端页面:必须是 post 请求;表单中添加input[type=file];form[encType=multipart/form-data] 默认键值对格式、改成字符串格式(同步上传方式),异步需要form-data

    B、上传解析器 -- 把用户端向服务器端发送的内容,进行字符串截取,截取之后注入到对应的位置。

    C、考虑重名位置、考虑上传文件保存位置问题

    2)实现

    A、创建项目,导入依赖

    (commons-io 会传递依赖)

    <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
    </dependency>
    

    B、springmvc 配置文件中添加上传解析器

    (id 名称是固定的)

    <!-- 配置文件上传解析器 -->
    <bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver
    ">
    <!-- 编码 -->
    <property name="defaultEncoding" value="utf-8"/>
    <!-- 上传文件总大小限制 的单位B -->
    <property name="maxUploadSize" value="5242800"/>
    </bean>
    

    String 只保存文件名称,不能同名;要保存文件使用字节数组。

    C、前端(表单)

    D、后端(controller)

    image-20210719103546560

    image-20210719104228401

    文件存储:本机(任意路径)、远程存储(自搭建、别人搭建)

    fastDFS(linux 分布式文件系统)

    阿里云(对象云存储OOS)

    文件解析器先存在c盘临时位置,在使用 transferTo 复制,存储位置

  2. 下载

    1)从服务器端向用户端下载文件

    2)实现

    A、准备下载列表

    B、点击链接,下载对应文件

    C、后端实现下载功能

    new File().list 文件名称列表展示

    下载 原生方案就可以:一个头、两个流:响应头、本地读取流、远程写出流

    response.setHeader("content-disposition","attachment;filename="+name)
    

    对字符二次编码 处理中文乱码

    name.getBytes("utf-8")
    new String(bytes,"iso8859-1")
    

统一异常处理

编译时异常 加 thorw、try catch

运行时错误

代码、前端(正则表达式约束)

不可控异常 运行逻辑异常

异常默认处理方式:向上抛出

抛给异常处理中心image-20210719141052635

  1. 是指:在项目中没有进行异常处理的其他处理,采用 java 默认 异常处理方式, 即向上抛出的方式,你如由持久层抛给业务层,由业务层抛给控制层,控制层抛给异常处理中心;在异常处理中心进行异常的统一处理。

  2. 实现:

    1)关注异常处理中心的实现

    A、自定义异常处理的类 -- 进而创建对象 -- 由容器管理即可

    实现 HandlerExceptionResolver

    实现的方法 resolveException 即为异常处理中心

    返回值 ModelAndView

    实现给运维保留信息:采用 Tomcat 自带的日志记录方式(log);向数据库中保存;自定义日志;日志服务器等等;

    Exception e 就是抛出的异常对象

    e.printStackTrace() 可以使用流

    e.getMessage() 获取异常信息

    image-20210719144623930

拦截器

  1. 介绍

    1)对于静态资源不拦截的;对于向 controller 的请求都会先拦截(然后可以在程序中在进一步判断)

  2. 和过滤器对比

    1)过滤器 依赖于 web 容器(servlet 容器 Tomcat造)(类加载造、方法调用造 load-on-startup)

    // 非静态方法 servlet 对象 调用
    UserServlet{
    
    Init();
    
    Destroy();
    
    Service();
    
    }
    

    拦截器 依赖于 springmvc 容器

    2)过滤器采用函数回调方式实现过滤器功能;拦截器采用反射方式实现拦截功能,基于 AOP 思想进行切入

    3)拦截过滤的顺序:请求时先过过滤器再过拦截器;响应时先过拦截器再过过滤器(先进后出)

    4)过滤器可以过滤所有请求,拦截器只可以拦截 controller 的请求

    image-20210719151738132

  3. 实现

    实现 HandlerInterceptor

    实现三个方法

    preHandler:请求处理之前调用

    postHandle:返回模型和视图名之前切入,可以获取到后端控制器向适配器返回的模型和视图名,通常在此方法中可以实现模型和视图名的统一设置

    afterCompletion:也没有拦截或者放行的功能,此方法的切入位置是在视图解析器向前端控制器返回视图文件时,可以获取到向 controller 发出请求时发生的异常。统一异常处理另一套方案,无法设置返回页面

    (不使用异常处理中心的方案时)

    image-20210719153829238

    <!-- 配置拦截器 -->
    <mvc:interceptors>
    <mvc:interceptor>
    <!-- 对那些资源执行拦截操作 /**代表对所有方法 -->
    <mvc:mapping path="/**"/>
    <bean class="com.bh.interceptor.Myinterceptor1"/>
    </mvc:interceptor>
    </mvc:interceptors>
    

    /** 表示一级多级都可以拦截

拦截器的使用案例

  1. 需求:登录拦截

    有些请求不需要登录就可以直接访问;但是还有些请求是需要登录才可以访问的;当用户请求需要登录才可以访问的连接,使用拦截器拦截,进行登录验证(验证用户是否登录),登录则放行,反之则登录

  2. 拦截器获取当前请求 url

    request.getRequestURI()

    if endsWith() 判断后缀是什么

    1)需要登录才可以访问的

    判断是否有登陆...

    2)不需要登录就可以访问的

    注意:url 片段前面是否有/,如果没有,则默认当前 url 统计目录下;如果有/,则代表当前根目录,端口后,不带项目名称

SSM 整合

  1. 整合

    SSM -- SpringMVC、Spring、MyBatis

    协作:共同实现项目功能、完成项目的需求;

    SpringMVC 负责表现层的实现

    Spring 负责 IOC、DI、AOP 实现

    MyBatis 负责持久层的实现

  2. 步骤:

    1. 创建项目、导入依赖

      image-20210720095211162

    2. SpringMVC 整合 Spring

      1)web.xml 中配置前端控制器、过滤器

      2)SpringMVC 配置文件(扫描包、注解驱动、视图解析器、类型转换工厂、上传解析器)

      3)测试

    3. Spring 和 MyBatis 整合

      1)Spring 配置

      扫描包、数据源、事务管理对象、事务注解驱动、MyBatis工厂、代理对象

      2)准备 MyBatis 映射文件

      增删改查、动态SQL 相关配置

      3)测试

    4. 把整合结果整合到项目中

      加载 Spring 配置文件

      等同于

      ApplicationContext context = new XmlClasspathApplicationContext("applicationContext.xml");
      
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:applicationContext.xml</param-value>
      </context-param>
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      

      Spring 容器和 SpringMVC 容器,父子容器,Spring 是父,SpringMVC 是子;SpringMVC 可以调用父容器对象,反之不可以。

      image-20210720105507966

      image-20210720105616712

      1)web.xml 添加配置

      A、加载文件配置

      B、监听器配置

    5. 整体测试


标题:SpringMVC框架的学习
作者:HB2Ocean
地址:http://future-hb.top:8080/articles/2021/07/18/1626602146504.html