SpringMVC学习笔记

文章目录

1. SpringMVC概述

1.1 MVC思想

MVC是一种软件架构的思想, 将软件按照模型、视图、控制链来划分

  • M: model,模型层,指工程中的JavaBean,作用是处理数据
  • V: View,视图层,指工程中的jsp或html页面,作用是与用户进行交互,展示数据
  • C:Controller,控制层,指工程中的Servlet,作用是接收请求和响应浏览器

JavaBean分为两类

  • 一类是实体bean, 专门存储业务数据
  • 一类为业务处理bean, 指Service或dao对象, 专门助理业务逻辑和数据访问

MVC的工作流程
用户通过视图层发送请求到服务器, 在服务器中请求被Controller接收, Controller调用相应的Model层处理请求, 处理完毕后将结果返回到Controller, Controller再根据请求处理的结果找到相应的View视图, 渲染数据后最后响应给浏览器。

1.2 SpringMVC简述

  • Spring的后续产品, 是Spring的一个子项目
  • 是Spring为表述层(前台页面和后台Servlet)提供的一套完备的解决方案。

1.3 SpringMVC特点

  • 基于原生Servlet, 通过了功能强大的前端控制器DispatcherServlet, 对请求和响应进行统一处理
  • Spring家族原生产品, 与IOC容器等基础设备无缝对接
  • 性能卓越, 代码简洁

1.4 SpringMVC开发环境搭建

  1. 创建一个web工程

  2. 在Maven中引入依赖环境
    在这里插入图片描述

  3. 配置web.xml
    默认配置方式: 这种配置作用下, SpringMVC的配置文件位于WEB-INF下默认名称为< serlvet-name >-servlet.xml, 例如下图: SpringMVC-servlet.xml
    在这里插入图片描述
    扩展配置方式(最优):使用这种方式可以将配置文件移动至想要的路径下
    在这里插入图片描述

  4. 创建请求控制器
    在这里插入图片描述

  5. 配置SpringMVC文件(注意引入名称空间)
    Thymeleaf的写法在这里插入图片描述
    普通写法
    在这里插入图片描述

  6. 编写请求匹配
    在这里插入图片描述
    当我访问资源路径为"/"时, 浏览器请求会和这个方法匹配返回字符串index到Spring配置文件中进行解析,
    在这里插入图片描述
    经过解析, 结果为 "/WEB-INF/templates/index.html"并自动跳转。
    访问资源路径为target.html的文件
    在这里插入图片描述

2. @RequestMapping

2.1 RequestMapping的基本介绍

RequestMapping(请求映射), 将请求和处理请求的控制器方法关联起来, 建立映射关系, SpringMVC接受到请求, 来映射关系中找到对应的方法来处理

2.2 RequestMapping的基本位置

  • 当映射地址有多个控制方法会报错

  • 标识一个类, 设置映射请求的请求路径的初始信息
    在这里插入图片描述

  • 标识一个方法, 设置映射请求的请求路径的具体信息
    在这里插入图片描述

2.3 RequestMapping的属性

  • value

    1. 该值必须设置, 至少通过请求地址匹配请求映射。
    2. String[]类型数组, 表示可以有多个请求地址来匹配这个映射。
      在这里插入图片描述
  • method: 可选项, 不设置的话任何形式的请求都能匹配

    1. method属性是一个RequestMapping类型的数组, 表示这个请求映射可以有多个请求方式。
      在这里插入图片描述
      在这里插入图片描述

    2. 如果请求地址满足value, 但是请求方式不满足method, 则浏览器报405错误。
      在这里插入图片描述

    3. 对于指定请求方式的控制器方法, SpringMVC提供了@RequestMapping的派生注解。
      (1) @GetMapping
      (2) @PostMapping
      (3) @PutMapping
      (4) @DeleteMapping
      注意: 目前浏览器只能处理get和post请求, 表单提交时如果设置了其他请求方式的字符串则默认为get请求, 处理put和delete看后面的restful部分的笔记。

  • params(了解)

    1. 通过请求参数匹配映射。

    2. params属性是一个String[] 数组, 可以通过四种表达式设置请求参数和请求映射的匹配关系
      (1) param
      (2) !param
      (3) param=“value”
      (4) param!=“value”

      当username = admin password = 123456时, 匹配成功
      在这里插入图片描述 在这里插入图片描述

  • headers(了解)

    1. 根据请求头匹配映射。

    2. 是一个String[] 数组, 可以通过类似params的四种表达式来进行设置请求头和请求映射关系的匹配关系。
      在这里插入图片描述

    3. 当满足value和method, 但是不满足headers, 浏览器报404。

2.5 ant风格的路径设置

   ? : 表示任意的单个字符
   * : 表示任意的0个或多个字符
   ** : 表示任意的一层或多层目录
   注意: 使用**时, 只能使用/**/xxx的方式。

演示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
演示**
在这里插入图片描述

2.6 SpringMVC支持路径中的占位符(重要)

SpringMVC路径中的占位符常用于restful风格中, 当请求路径中将某些数据通过路径的方式传输到服务器中, 就可以在相应的@RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据, 再通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3. Spring获取请求参数

3.1 通过Servlet方式

SpringMVC可以使用原生Servlet方式来获取请求参数
在这里插入图片描述
在这里插入图片描述

3.2 通过控制器的形参

在这里插入图片描述
当有多个同名参数的情况, 可以通过使用字符串形参或字符串数组形参来获取, 若使用的是字符串形参, 多值之间通过,拼接起来

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

也可以通过原生Servlet的getParams()特定方法返回一个数组, 该数组就是参数数组
在这里插入图片描述

3.3 @RequestParam

@RequestParam是将请求参数和控制器方法的形参创建映射关系
@RequestParam有三个属性

  • value :指定为形参赋值的请求参数的参数名
  • required :是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。
  • defaultValue:默认参数值,如果设置了该值,required=true将失效
    自动为false,如果没有传该参数,就使用默认值

在这里插入图片描述
注意: 当设置required为true时, 没有传输该请求参数, 也没有设置默认值, 页面报错400, 对于默认值来说, 不管required怎么设置, 有请求参数就用请求参数, 没有就用默认值为形参赋值。

3.4 @RequestHeader、@CookieValue

  • @RequestHeader是将请求头信息和控制器方法的形参创建映射关系
  • @CookieValue是将Cookie数据和控制器方法的形参创建映射关系
  • 有三个属性基本同@RequestParam
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3.5 通过POJO获取请求参数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6 解决获取请求参数的乱码问题

SpringMVC已经提供好了字符编码的过滤器
在这里插入图片描述

4. 域对象共享数据

4.1 通过Servlet向request域对象共享数据

在这里插入图片描述

4.2 通过ModelAndView向request域对象共享数据

在这里插入图片描述

4.3 使用Model向request域对象共享数据

在这里插入图片描述

4.4使用Map向request域对象共享数据

在这里插入图片描述

4.5 使用ModeMap向request域对象共享数据

在这里插入图片描述

4.6 向Session域中共享数据

直接使用Servlet原生方式
在这里插入图片描述

4.7 向Application域共享数据

直接使用Servlet原生方式
在这里插入图片描述

4.8 Model、ModelMap、Map的关系

model、modelMap、map类型的参数其实本质都是BindingAwareModelMap类型的

5. SpringMVC视图

  • SpringMVC的视图是View接口, 视图的作用渲染数据, 将模型model中的数据展示用户
  • SpringMVC视图的种类很多, 默认有转发视图和重定向视图, 当工程引入jstl的依赖, 转发视图会自动转换为jstlView
  • 若使用的视图技术为thymeleaf, 在SpringMVC的配置文件中配置了thymeleaf的视图解析器, 由此视图解析器解析之后得到的是ThymeleafView

5.1 ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时, 此时的视图名称会被springMVC配置文件中所配置的视图解析器解析, 视图名称拼接视图前缀好后缀所得到的最终路径, 会通过转发的方式实现跳转

在这里插入图片描述

5.2 转发视图

SpringMVC中默认的转发视图是InternalResourceView

SpringMVC中创建转发视图的情况

当控制器方法中所设置的视图名称以“forward”为前缀时, 创建InternalResourceView视图,
此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析, 而是会将前缀"forward"去掉,
剩余部分作为最终路径通过转发的方式实现跳转。

在这里插入图片描述
转发, 地址栏无变动
在这里插入图片描述

5.3 重定向视图

SpringMVC中默认的重定向视图是RedirectView

当控制器方法中所设置的视图名称以"redirect"为前缀时, 创建RedirectView视图,

此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析, 而是会将前缀"redirect"去掉, 剩余部分作为最终路径通过重定向的方式实现跳转
在这里插入图片描述
重定向, 地址栏变化
在这里插入图片描述

5.4 视图控制器View - Controller

当控制器方法中, 只实现页面跳转功能, 即只需要设置视图名称时, 可以将处理器方法使用view-controller标签进行表示

注意引入mvc名称空间
在这里插入图片描述
注意: 当使用mvc:view-controller标签在springMVC文件中配置时, 控制器中所有的请求映射全部失效, 需要在springMVC文件中加入一个配置来避免这种情况

开启mvc的注解驱动, 开启后便可同时使用两种方式来配置请求映射
在这里插入图片描述

6. RESTFul

6.1 RESTFul简介

Representational State Transfer 表现层资源状态转移

6.2 RESTFul的实现

具体来说, 就是HTTP协议里面, 4个表示操作方式的动词: GET、POST、PUT、DELETE
分别对应4种操作, GET用来获取资源, POST用来新建资源, PUT用来更新资源, DELETE用来删除资源
REST风格提倡URL地址使用统一的风格设计, 从前到后各个单词之间用\分开, 不使用问号键值对方式携带请求参数, 而是将要发送给服务器的数据作为URL地址的一部分, 以保证整体风格的一致性

模拟RESTFul模拟用户资源的增删改查

路径方式作用
/userGET查询所有用户信息
/user/1GET根据用户id查询用户信息
/userPOST添加用户信息
/user/1DELETE删除用户信息
/userPUT修改用户信息

模拟GET和POST请求做查询、添加操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

HiddenHttpMetHodFilter处理PUT和DELETE做修改、删除操作

这一段看后面的RESTFul对员工信息的修改和删除操作, 这里只是一个简单介绍

  1. 首先配置HiddenHttpMetHodFilter过滤器在这里插入图片描述
  2. 前端通过隐藏域来设置PUT和DELETE请求
    3.

在这里插入图片描述

注意: 在配置web.xml时hiddenHttpMethodFilter应该在CharactorEncodingFilter之后写好, 否则是无效的, 因为在进行编码过滤前不能获取任何请求方式参数。

6.3 RESTFul案例

6.3.1 资源准备

  1. 准备dao测试数据(未使用数据库)
package com.atguigu.mvc.dao;

import com.atguigu.mvc.bean.Employee;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


 @Repository
public class EmployeeDao {
    /*
    *  准备了一些模拟数据用于RESTFul资源操作
    * */
    private static Map<Integer, Employee> employees = null;
    private static Integer initId = 1006;

    static{
        employees = new HashMap<>();

        employees.put(1001,new Employee(1001,"E-AA","aa@qq.com",1));
        employees.put(1002,new Employee(1002,"E-BB","bb@qq.com",2));
        employees.put(1003,new Employee(1003,"E-CC","cc@qq.com",1));
        employees.put(1004,new Employee(1004,"E-DD","dd@qq.com",2));
        employees.put(1005,new Employee(1005,"E-EE","ee@qq.com",1));
        employees.put(1006,new Employee(1006,"E-FF","ff@qq.com",2));
        employees.put(1007,new Employee(1007,"E-JJ","jj@qq.com",1));
        employees.put(1008,new Employee(1008,"E-HH","hh@qq.com",2));
        employees.put(1009,new Employee(1009,"E-II","ii@qq.com",1));
        employees.put(1010,new Employee(1010,"E-GG","gg@qq.com",2));
    }


    // 修改和增加数据
    public void save(Employee employee) {
        if (employee.getId() == null) {
            employee.setId(initId++);
        }
        employees.put(employee.getId(), employee);
    }

    // 获取所有数据
    public Collection<Employee> getAll(){
        return employees.values();
    }

    // 根据id查询数据
    public Employee get(Integer id){
        return employees.get(id);
    }

    // 根据id删除数据
    public void delete(Integer id){
        employees.remove(id);
    }
}
  1. 准备bean
package com.atguigu.mvc.bean;

public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;

    public Employee(){}

    public Employee(Integer id, String lastName, String email, Integer gender) {
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", gender=" + gender +
                '}';
    }
}

  1. 写控制层
package com.atguigu.mvc.controller;


import com.atguigu.mvc.dao.EmployeeDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class EmployeeController {

    @Autowired
    private EmployeeDao employeeDao;

}

6.3.2 功能清单

注: 这里发现个问题, 如果使用原始方式InternalResourceViewResolver加前后缀的话, html不太好使, jsp则没有问题
需要对代码做一些改进

功能URL地址请求方式
访问首页/GET
查询全部数据/employeeGET
删除/employee/1DELETE
跳转到添加数据页面/toAddGET
执行保存/employeePOST
跳转到更新数据页面/employee/1GET
执行更新/employeePUT
访问首页演示

访问首页只涉及到页面的跳转, 所以设置view-controller即可

  1. 写首页

  2. 配置view-controller
    在这里插入图片描述

  3. 开启注解驱动
    在这里插入图片描述

查询全部数据列表演示

控制层通过自动装配@AutoWired来装配Dao对象

在这里插入图片描述

在这里插入图片描述
前端
在这里插入图片描述

删除功能演示

删除是以超链接提交给表单的方式来发送请求, 而超链接的默认请求方式是GET, 我们需要把它转化成POST, 通过表单传过去DELETE属性才能完成删除功能

  1. 首先要在web.xml中配置HiddenHttpMethodFilter过滤器, 注意要在编码过滤器的下面写。
    在这里插入图片描述

  2. 在spring配置文件中配置对静态资源的访问, 注意:这个标签要配合mvc:annotion-driven一起使用。
    在这里插入图片描述

  3. 写控制层内容, 删除后重定向到员工列表页面
    在这里插入图片描述

  4. 通过Jquery来将超链接的GET方式修改为POST, 设置点击时提交表单, 注意这里表单中的隐藏域的name属性必须是_method, 否则HiddenHttpMethodFilter会无效

    超链接
    在这里插入图片描述
    表单
    在这里插入图片描述
    Jq
    在这里插入图片描述
    注意前端代码的书写顺序, 脚本内容写在后面。

修改功能演示
  1. 首先要获取修改的员工的ID在这里插入图片描述
  2. 控制层进行处理
    在这里插入图片描述
  3. 在empUpdate页面中进行修改操作
    在这里插入图片描述
  4. 提交表单后再次进行控制层操作, 最后重定向回员工列表
    在这里插入图片描述
  5. 修改完成
添加功能演示
  1. 首先是从员工列表页面跳转到添加页面, 这个过程除了跳转不涉及别的操作, 所以直接在spring配置文件中通过mvc:view-controller的方式实现跳转3.
    2.
  2. 添加员工信息的前端
    3.
  3. 控制层内容, 当表单提交后执行并重定向回员工列表
    4.

7. HttpMessageConverter

  • HttpMessageConverter, 报文信息转换器, 将请求报文转换为Java对象, 或将Java对象转换为响应报文
  • HttpMessageConverter提供了两个注解和两个类型: @RequestBody @ResponseBody RequestEntity ResponseEntity

7.1 @RequestBody注解

@RequestBody可以获取请求体, 需要在控制器方法设置一个形参, 使用@RequestBody进行标识, 当前请求体就会为当前注解所标注的形参赋值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.2 RequestEntity

RequestEntity封装请求报文的一种类型, 需要在控制器方法的形参中设置该类型的形参, 当前请求的请求报文就会赋值给该形参, 可以通过getHeader()获取请求头信息, 通过getBody()获取请求头信息
在这里插入图片描述
在这里插入图片描述

7.3 @ResponseBody注解

用于标识一个控制器方法, 可以将该方法的返回值直接作为响应报文的响应体响应到浏览器
在这里插入图片描述
在这里插入图片描述
ResponseBody处理Json数据
实体类Employee
在这里插入图片描述

  1. 首先要导入Jackson的依赖
    在这里插入图片描述

  2. 在SpringMVC的核心配置文件中开启MVC的注解驱动, 此时在HandlerAdaptor中会自动装配一个消息转换器, MappingJackson2HttpMessageConverter, 可以将响应到浏览器的java对象转换为json格式的字符串
    在这里插入图片描述

  3. 在处理器方法上使用@ResponseBody注解作为标识

  4. 将java对象直接作为控制器方法的返回值返回, 就会自动转换为json格式的字符串
    在这里插入图片描述

  5. 浏览器中的效果
    6.
    在这里插入图片描述
    在这里插入图片描述

7.4 ResponseEntity

ResponseEntity用于控制器方法的返回值类型, 该控制器方法的返回值就是响应到浏览器的响应报文

示例: 使用ResponseEntity实现文件下载功能

 @RequestMapping("/testDown")
 public ResponseEntity<byte[]> testResponseEntity(HttpSession httpSession) throws IOException {
        // 获取ServletContext对象
        ServletContext servletContext = httpSession.getServletContext();
        // 获取服务器中文件的真实路径
        String realPath = servletContext.getRealPath("/WEB-INF/static/img/1.jpg");
        // 创建输入流
        FileInputStream is = new FileInputStream(realPath);

        byte[] bytes = new byte[is.available()];

        // 将流读到字节数组中
        is.read(bytes);
        // 创建HttpHeaders对象设置响应头信息
        MultiValueMap<String,String> headers = new HttpHeaders();
        // 设置下载方以及下载文件的名字
        headers.add("Content-Disposition","attachment;filename=1.jpg");
        // 设置响应状态码
        HttpStatus statusCode = HttpStatus.OK;
        // 创建ResponseEntity对象
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,headers,statusCode);

        // 关闭输入流
        is.close();
        return responseEntity;
 }

效果
在这里插入图片描述
在这里插入图片描述

7.5 @RestController注解

@RestController注解是springMVC提供的一个符合注解, 标识在控制器的类上, 就相当于为类添加了@Controller注解, 并且为其中的每个方法添加了@ResponseBody注解

8. 文件的上传和下载

下载功能演示参考ResponseEntity

上传功能演示
需要先引入依赖
在这里插入图片描述
SpringMVC配置文件中的配置
在这里插入图片描述
前端
在这里插入图片描述
控制器方法

   @RequestMapping(value = "/textUp")
    public String textUp(MultipartFile photo,HttpSession httpSession) throws IOException {
        String fileName = photo.getOriginalFilename();
        // 上传的文件名

        ServletContext servletContext = httpSession.getServletContext();
        // 获取上下文对象

        String photoPath = servletContext.getRealPath("photo");
        // 上传的文件的文件路径

        File file = new File(photoPath);

        // 判断photoPath路径是否真实存在
        if(!file.exists()){
            file.mkdirs();
            // 不存在创建目录
        }
        String finalPath = photoPath + File.separator+ fileName;

        photo.transferTo(new File(finalPath));

        return "login";
        // 上传完成后跳转到登录页面
    }

文件上传成功后会存储在这里
在这里插入图片描述

解决文件的重名问题

   String fileName = photo.getOriginalFilename();
   // 上传的文件名

   String suffixName = fileName.substring(fileName.lastIndexOf("."));
   // 获取文件的后缀名

   String uuid = UUID.randomUUID().toString();
   // 获取UUID来作为上传后的文件名前缀  UUID是一堆混乱的字母数字来防止重名

   fileName = uuid + suffixName;

   System.out.println(fileName);

上传的都是2.jpg, 使用这串代码前和使用后进行对比
在这里插入图片描述

9. 拦截器

9.1 拦截器的配置

  • SpringMVC中的拦截用于拦截控制器方法的执行, 不会拦截JS、JSP、Html、CSS、Image等等
  • SpringMVC中的拦截器需要实现HandlerInterceptor或者继承HandlerInterceptorAdapter
  • SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置

9.2 创建拦截器

写自定义类实现实现HandlerInterceptor或者继承HandlerInterceptorAdapter

  • 实现HandlerInterceptor
public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 控制器方法执行前执行

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 控制器方法执行后执行

        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 渲染视图后执行

        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
  • 继承HandlerInterceptorAdapter
public class TestInterceptor2 extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }

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

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
}

9.3 配置拦截器

在这里插入图片描述

<!--配置拦截器-->
    <mvc:interceptors>
        <!--<bean class="com.ma.interceptor.CustomeInterceptor" />-->
        <!--拦截器1-->
        <!--<ref bean="customInterceptor">-->
        <!--拦截器2-->
        <mvc:interceptor>
            <!--配置拦截器的作用路径-->
            <mvc:mapping path="/**"/>
            <!--配置不需要拦截的请求路径-->
            <mvc:exclude-mapping path=""/>
            <!--定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截-->
            <bean class="com.ma.interceptor.Intercptor1"/>
        </mvc:interceptor>
        <!--拦截器2-->
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean class="com.ma.interceptor.Interceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>
  • mvc:interceptors元素用于配置一组拦截器,基子元素中定义的是全局拦截器,它会拦截所有的请求;而mvc:interceptor元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。
  • mvc:interceptor元素的子元素mvc:mapping用于配置拦截器作用的路径,该路径在其属性path
    中定义。如上述代码中 path 的属性值“/**” 表示拦截所有路径,“/hello” 表示拦截所有以 “/hello”
    结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过mvc:exclude-mapping元素进行配置。
  • 注意:mvc:interceptor中的子元素必须按照上述代码中的配置顺序进行编写,即mvc:mapping
    mvc:exclude-mapping ,否则文件会报错。

9.4 拦截器的三个抽象方法和多个拦截器之间的执行顺序

  • preHandle() 方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;
    当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。
  • postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
  • afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

配置多个拦截器
在这里插入图片描述
执行代码, 拦截结果如下
在这里插入图片描述
可以看到对于preHandle, 拦截器方法的执行顺序是正向的, 而对于postHandle和afterCompletion来说, 是反向的

  • 如果每个拦截器的preHandler()都返回true, 此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关, preHandler()会按照配置的顺序执行, 而postHandler()和afterComplation()会按照配置的反序执行
  • 若某个拦截器的preHandler()返回了false, preHandler()返回false和它之前的拦截器的preHandler()都会执行, postHandler()都不执行, 返回false的拦截器之前的拦截器的afterComplation()会执行

10. 异常处理器

10.1 基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口: HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有: DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver
演示

 <!--配置异常处理-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!--配置可能会出现的异常-->
        <property name="exceptionMappings">
            <props>
                <!--
                    当出现了异常, 跳转到error这个视图
                    可以配置多个
                -->
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>

        <property name="exceptionAttribute" value="ex">
        </property>
        <!--将异常信息存到请求域中  通过value取出-->
    </bean>

取出效果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

10.2 基于注解的异常处理器

使用 @ControllerAdvice 实现全局异常处理, 该注解除了异常处理, 还可以实现全局数据绑定等功能

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
    // 设置处理的异常
    public String testExcetion(Exception ex, Model model){
        // Exception ex 异常对象信息
        // Model model 请求域

        model.addAttribute("ex",ex);

        return "error";
    }
}

出现异常时页面效果
在这里插入图片描述

11. 使用注解配置SpringMVC

使用配置类和注解来代替Web.xml和SpringMVC配置文件的作用
Spring3.2开始引入了一个便利的WebapplicationInitializer基础实现, 名为abstractAnnotationConfigDispatcherServletInitializer, 当我们的类扩展了这个基础实现并部署到Servlet3中, 容器会自动发现它, 并用它来配置Servlet的上下文

Web工程的初始化类WebInit

package com.atguigu.mvc.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;


// Web工程的初始化类, 用来代替Web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    // 方法较多, 注意重写以下的方法    


    // 获取Spring配置类
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    // 获取SpringMVC配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    // 获取DispatcherServlet的映射路径
    // 同Web.xml中的ServletMapping中的url-pattern
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    // 注册过滤器

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        // 设置过滤器的初始化参数
        characterEncodingFilter.setEncoding("utf-8");
        characterEncodingFilter.setForceResponseEncoding(true);

        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();

        return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
    }
}

SpringMVC配置类(这里是使用的Thymela)

12. SpringMVC执行流程

12.1 SpringMVC的常用组件

  • DispatcherServlet:前端控制器,不需要工程师开发,由框架提供
    作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求

  • HandlerMapping:处理器映射器,不需要工程师开发,由框架提供
    作用:根据请求的url、method等信息查找Handler,即控制器方法

  • Handler:处理器,需要工程师开发
    作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理

  • HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供
    作用:通过HandlerAdapter对处理器(控制器方法)进行执行

  • ViewResolver:视图解析器,不需要工程师开发,由框架提供
    作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、
    RedirectView

  • View:视图
    作用:将模型数据通过页面展示给用户

12.2 DispacherServlet的初始化过程

DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet
生命周期来进行调度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值