Chiriri's blog Chiriri's blog
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)

Iekr

苦逼后端开发
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)
  • JavaSE

  • JavaEE

    • MyBatis
    • Jackson
    • Jedis
    • Maven
    • POI
    • Spring
    • Spring MVC
      • 三层架构
      • MVC
      • 项目构建 xml
      • 技术架构图
      • 注解驱动
        • 扫描包含Controller注解的类
        • 注解配置指定放行的资源
        • 注解配置放行所有静态资源
        • servlet扫描mvc配置文件
      • 请求
        • 请求参数
        • 普通类型
        • POJO类型
        • POJO类型与普通类型同时存在
        • 复杂POJO类型 嵌套
        • 复杂POJO类型 集合
        • 复杂POJO类型 集合对象
        • 复杂POJO类型 Map集合
        • 数组类型
        • 集合类型
        • 类型转换器
        • xml 日期类型格式转换
        • 注解版 日期类型格式转换
        • 自定义类型转换器
        • 请求映射
      • 响应
        • 页面跳转方式
        • request传递数据
        • Model 类型形参进行数据传递
        • ModelAndView 类型传递
        • 重定向
        • 返回JSON数据
      • Servlet相关接口
        • Head数据获取
        • Cookie 数据获取
        • Session 数据获取和设置
      • 发送异步请求
      • 异步请求响应
      • 跨域访问
      • 拦截器
        • 拦截器参数
        • 多个拦截器
        • 责任链模式
      • 异常处理
        • 注解版异常处理
      • 文件上传下载
      • Restful
        • PathVariable
        • RestController
        • XXXMapping
      • 表单验证框架
        • 分组校验
      • SSM
    • Maven 高级
    • Dubbo
    • Zookeeper
    • Spring Security
    • Spring Boot
    • Spring Boot 高级
    • RabbitMQ
    • RabbitMQ 高级
    • Spring Cloud
    • Docker
    • ElasticSearch
    • ElasticSearch 高级
  • Linux

  • MySQL

  • NoSQL

  • Python

  • Python模块

  • 机器学习

  • 设计模式

  • 传智健康

  • 畅购商城

  • 博客项目

  • JVM

  • JUC

  • Golang

  • Kubernetes

  • 硅谷课堂

  • C

  • 源码

  • 神领物流

  • RocketMQ

  • 短链平台

  • 后端
  • JavaEE
Iekr
2021-09-10
目录

Spring MVC

# Spring MVC

# 三层架构

image-20210910202125058

# MVC

MVC (Model View Controller) 设计创建 Web 应用程序表现层的模式

  • Model 模型:数据模型,用于封装数据
  • View 视图:页面视图,用于展示数据
    • jsp
    • html
  • Contoller 控制器:处理用户交互的调度器,用于根据用户需求处理程序逻辑
    • Servlet

# 项目构建 xml

导入坐标

         <!-- servlet3.1规范的坐标 -->
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
      </dependency>
      <!--jsp坐标-->
      <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
      </dependency> 
		<!--spring web的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!--springmvc的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

spring-mvc.xml

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

    <context:component-scan base-package="com.itheima">
        <!-- 包含以下注解则加载 -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>


    <!--放行指定类型静态资源配置方式-->
<!--    <mvc:resources mapping="/img/**" location="/img/"/>-->
<!--    <mvc:resources mapping="/js/**" location="/js/"/>-->
<!--    <mvc:resources mapping="/css/**" location="/css/"/>-->

    <!--SpringMVC提供的通用资源放行方式 释放所有静态资源-->
    <mvc:default-servlet-handler/>

</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!--乱码处理过滤器,与Servlet中使用的完全相同,差异之处在于处理器的类由Spring提供-->
    <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>
	<!-- 扫描mvc配置文件 -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 技术架构图

image-20210910205148859

# 注解驱动

# 扫描包含 Controller 注解的类

在 springmvc 配置类中

@ComponentScan(value = "com.itheima",includeFilters =
    @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class})
    )
1
2
3

# 注解配置指定放行的资源

实现 WebMvcConfigurer 接口 重写 addResourceHandlers 方法

public class SpringMVCConfiguration implements WebMvcConfigurer{
    //注解配置放行指定资源格式
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        			  registry.addResourceHandler("/img/**").addResourceLocations("/img/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    }
}
1
2
3
4
5
6
7
8
9

# 注解配置放行所有静态资源

实现 WebMvcConfigurer 接口 重写 configureDefaultServletHandling 方法

public class SpringMVCConfiguration implements WebMvcConfigurer{
	@Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();;
    }
}
1
2
3
4
5
6

# servlet 扫描 mvc 配置文件

继承 AbstractDispatcherServletInitializer 类 重写里面的 createServletApplicationContext createRootApplicationContext 和 getServletMappings 方法

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.EnumSet;

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //创建Servlet容器时,使用注解的方式加载SPRINGMVC配置类中的信息,并加载成WEB专用的ApplicationContext对象
    //该对象放入了ServletContext范围,后期在整个WEB容器中可以随时获取调用
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        //需要一个MVC配置类
        ctx.register(SpringMVCConfiguration.class);
        return ctx;
    }

    //注解配置映射地址方式,服务于SpringMVC的核心控制器DispatcherServlet
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    //乱码处理作为过滤器,在servlet容器启动时进行配置,相关内容参看Servlet零配置相关课程
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        CharacterEncodingFilter cef = new CharacterEncodingFilter();
        cef.setEncoding("UTF-8");
        FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
        registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD,DispatcherType.INCLUDE),false,"/*");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 请求

# 请求参数

SpringMVC 将传递的参数封装到处理器方法的形参中,达到快速访问参数的目的

只需在形参上与请求地址上的参数名字一致 即可获取到请求参数的值

    //请求参数  http://localhost/requestParam1?name=hello
    @RequestMapping("/requestParam1")
    public String requestParam1(String name){
        System.out.println(name);
        return "index.jsp";
    }
1
2
3
4
5
6

# 普通类型

参数名与处理器方法形参名保持一致 否则无法获取对应的值

如果想要绑定具体的请求名 则需要使用 @RequestParam

  • @RequestParam
    • value 请求属性名
    • required 不允许为空 默认为 true
    • defaultValue 为空时默认值
    //请求参数形参绑定名  http://localhost/requestParam2?username=hello&age=10
    @RequestMapping("/requestParam2")
    public String requestParam2(@RequestParam(value = "username",required = true,defaultValue = "zhangsan") String name, int age){
        System.out.println(name);
        System.out.println(age);
        return "index.jsp";
    }
1
2
3
4
5
6
7

# POJO 类型

如果形参为一个对象 则请求参数会将值 一一对应为对象中属性值

    //POJO类型参数  http://localhost/requestParam3?username=zhangsan&age=10
    @RequestMapping("/requestParam3")
    public String requestParam3(User user){
        System.out.println(user.toString());
        return "index.jsp";
    }
1
2
3
4
5
6
# POJO 类型与普通类型同时存在

将会被同时赋值 如果想进行区分 建议使用 @RequestParam 进行绑定

    //POJO类型参数与普通类型同时存在  http://localhost/requestParam4?name=zhangsan&age=10
    @RequestMapping("/requestParam4")
    public String requestParam4(User user,String age){
        System.out.println(user.toString());
        System.out.println(age);
        return "index.jsp";
    }
1
2
3
4
5
6
7
# 复杂 POJO 类型 嵌套

如果 POJO 中嵌套 POJO 则 需要请求地址 需要按照层次结构要书写

    //复杂POJO类型  http://localhost/requestParam5?address.city=shanghai
    @RequestMapping("/requestParam5")
    public String requestParam5(User user){
        System.out.println(user.getAddress().getCity());
        return "index.jsp";
    }
1
2
3
4
5
6
# 复杂 POJO 类型 集合

如果 POJO 中出现集合 保存简单数据 使用多个相同名称的参数为其进行赋值


    //复杂POJO类型 集合  http://localhost/requestParam6?nick=zhangsan&nick=lisi&nick=wangwu
    @RequestMapping("/requestParam6")
    public String requestParam6(User user){
        System.out.println(user);
        return "index.jsp";
    }
1
2
3
4
5
6
7
# 复杂 POJO 类型 集合对象

集合对象 以索引形式的请求地址

    //复杂POJO类型 集合对象  http://localhost/requestParam7?addresses[0].province=bj&addresses[1].province=gd
    @RequestMapping("/requestParam7")
    public String requestParam7(User user){
        System.out.println(user.getAddresses());
        return "index.jsp";
    }
1
2
3
4
5
6
# 复杂 POJO 类型 Map 集合

Map 集合 在请求地址中以 key 的形式赋值

    //复杂POJO类型 集合对象  http://localhost/requestParam8?addressMap['home'].province=bj&addressMap['job'].province=gd
    @RequestMapping("/requestParam8")
    public String requestParam8(User user){
        System.out.println(user.getAddressMap());
        return "index.jsp";
    }
1
2
3
4
5
6

# 数组类型

请求参数名与数组名一致 并请求参数数量大于 1 个

    //数组类型  http://localhost/requestParam9?nick=abc&nick=def
    @RequestMapping("/requestParam9")
    public String requestParam9(String[] nick) {
        System.out.println(nick[0] + " " + nick[1]);
        return "index.jsp";
    }
1
2
3
4
5
6

# 集合类型

MVC 默认将 list 作为对象处理 赋值前先创建对象 然后将 nick 作为对象的属性赋值 但 list 是接口 无法创建对象 和 有此属性值 所以报错

我们通过 @RequestParam 将请求参数打包成数组

    //集合类型  http://localhost/requestParam10?nick=abc&nick=def
    @RequestMapping("/requestParam10")
    public String requestParam10(@RequestParam("nick") List<String> nick) {
        System.out.println(nick);
        return "index.jsp";
    }
1
2
3
4
5
6

# 类型转换器

MVC 对接受的数据进行自动类型转换 通过 Converter 接口实现

# xml 日期类型格式转换

spring 默认的日期格式为 2021/09/11 如果我们传递为 2021-09-11 则会报错 我们需要自定义日期格式转换

    <!--    自定义转换格式-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!--    注册bean 让spring管理-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="org.springframework.format.datetime.DateFormatter">
                    <property name="pattern" value="yyyy-MM-dd"/>
                </bean>
            </set>
        </property>
    </bean>
1
2
3
4
5
6
7
8
9
10
11
12

# 注解版 日期类型格式转换

    //日期类型 自定义格式转换  http://localhost/requestParam11?date=2021-09-11
    @RequestMapping("/requestParam11")
    public String requestParam11(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date) {
        System.out.println(date);
        return "index.jsp";
    }
1
2
3
4
5
6

并开启 mvc 注解驱动

<mvc:annotation-driven />
1

# 自定义类型转换器

实现 Converter 接口 泛型 1 为原始数据类型 泛型 2 为返回的数据类型 并实现 convert 方法

    <!--    自定义类型转换器-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!--    注册bean 让spring管理-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.itheima.converter.MyDateConverter">
                </bean>
            </set>
        </property>
    </bean>
1
2
3
4
5
6
7
8
9
10
11

处理类


import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return date;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 请求映射

  • @RequestMapping 设置在方法上则是方法体的请求映射 定义在类上则是整个类的访问前缀
  • value 请求路径
  • method = RequestMethod.GET 请求方式
  • params = "name" 请求地址必须传递此属性才能访问
  • headers = "content-type=text/*" 请求头条件
  • consumes = "text/*" 可以接受的请求正文类型
  • produces = "text/*" 可以生成的响应正文类型

# 响应

# 页面跳转方式

  • 转发 (默认)

    @RequestMapping("/showPageAndData1")
        public String showPageAndData1(HttpServletRequest request){
            return "forward:success.jsp";
        }
    
    1
    2
    3
    4
  • 重定向

        @RequestMapping("/showPageAndData7")
        public String showPageAndData7(){
            return "redirect:index.jsp";
        }
    
    1
    2
    3
    4
  • 页面访问快捷设定 设置了快捷访问 后默认访问是设定的路径下制定的后缀文件 默认为转发跳转 无法重定向

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/page/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    
    1
    2
    3
    4

    如果方法体没有返回值 也配置了快捷方式 则自动跳转到指定的路径下 访问路径 + 后缀 的文件

    image-20210911152718177

# request 传递数据

@RequestMapping("/showPageAndData1")
public String showPageAndData1(HttpServletRequest request){
    request.setAttribute("name","hello");
    return "success.jsp";
}
1
2
3
4
5

# Model 类型形参进行数据传递

    @RequestMapping("/showPageAndData2")
    public String showPageAndData2(Model model){
        model.addAttribute("name","hello");
        User user =new User();
        user.setAge(156);
        //可以传递对象
        model.addAttribute("user",user);  
        return "success.jsp";
    }
1
2
3
4
5
6
7
8
9

# ModelAndView 类型传递

    @RequestMapping("/showPageAndData3")
    public ModelAndView showPageAndData3(ModelAndView modelAndView){
        modelAndView.addObject("name","hello");
        User user =new User();
        user.setAge(156);
        //添加属性
        modelAndView.addObject("user",user);
        //跳转页面
        modelAndView.setViewName("success.jsp");
        return modelAndView;
    }
1
2
3
4
5
6
7
8
9
10
11

# 重定向

    @RequestMapping("/showPageAndData5")
    public ModelAndView showPageAndData5(ModelAndView modelAndView){
        //重定向
        modelAndView.setViewName("redirect:index.jsp");
        return modelAndView;
    }

    @RequestMapping("/showPageAndData6")
    public ModelAndView showPageAndData6(ModelAndView modelAndView){
        //跳转
        modelAndView.setViewName("forward:index.jsp");
        return modelAndView;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13

# 返回 JSON 数据

响应方法体 返回的数据默认会直接跳转到 返回值对应的页面文件

我们可以在方法体上 加上 @ResponseBody 注解 来声明为一个响应体

    @RequestMapping("showData1")
    @ResponseBody
    public String showData1() throws JsonProcessingException {
        User user = new User();
        user.setAge(15);
        user.setName("zhangsan");
        ObjectMapper om = new ObjectMapper();
        return om.writeValueAsString(user);
    }
1
2
3
4
5
6
7
8
9
  • 返回一个对象或者集合 Jackson 已经帮我们做好了 自定义类型转换了 我们只需要在 spring 配置中开启注解驱动 即可

     <mvc:annotation-driven />
    
    1

    注解版 开启注解驱动 为 @EnableWebMvc

        @RequestMapping("showData2")
        @ResponseBody
        public User showData2() throws JsonProcessingException {
            User user = new User();
            user.setAge(15);
            user.setName("zhangsan");
            return user;
        }
    
    1
    2
    3
    4
    5
    6
    7
    8

# Servlet 相关接口

原始的 request response 和 session 提供给我们使用但是不太推荐使用原生的功能

image-20210911160243790

# Head 数据获取

  • @RequestHeader 获取头中指定的值

        @RequestMapping("/headApi")
        public String headApi(@RequestHeader("Accept-Language") String head){
            System.out.println(head);
            return "index.jsp";
        }
    
    1
    2
    3
    4
    5

# Cookie 数据获取

  • @CookieValue 获取 cookie 指定 key 的值

        @RequestMapping("/cookieApi")
        public String cookieApi(@CookieValue("_xsrf") String cookie){
            System.out.println(cookie);
            return "index.jsp";
        }
    
    1
    2
    3
    4
    5

# Session 数据获取和设置

  • 设置 只有在类注解上方标记的变量名称才会被放到 session 中

    • image-20210911161133474
  • 获取

    •     @RequestMapping("/sessionApi")
          public String sessionApi(@SessionAttribute("name") String session){
              System.out.println(session);
              return "index.jsp";
          }
      
      1
      2
      3
      4
      5

# 发送异步请求

通过 ajax 发送的异步请求 是无法直接被赋值给形参的 需要在形参前面 加上 @RequestBody

    @RequestMapping("/ajax1")
    public String ajax1(@RequestBody String data) {
        System.out.println(data);
        return "index.jsp";
    }
1
2
3
4
5
  • JSON 转 POJO 会自动赋值给 POJO 中属性

    •     @RequestMapping("/ajax2")
          public String ajax2(@RequestBody User user) {
              System.out.println(user);
              return "index.jsp";
          }
      
      1
      2
      3
      4
      5
  • 集合

    •     @RequestMapping("/ajax3")
          public String ajax3(@RequestBody List<User> user) {
              System.out.println(user);
              return "index.jsp";
          }
      
      1
      2
      3
      4
      5

# 异步请求响应

  • 返回字符串

    •     @RequestMapping("/ajax4")
          @ResponseBody
          public String ajax4() {
              return "hello";
          }
      
      1
      2
      3
      4
      5
  • 返回对象

    •     @RequestMapping("/ajax5")
          @ResponseBody
          public User ajax5() {
              User user = new User();
              user.setName("hhh");
              user.setAge(13);
              return user;
          }
      
      1
      2
      3
      4
      5
      6
      7
      8
  • 返回集合

    •     @RequestMapping("/ajax6")
          @ResponseBody
          public List ajax6() {
              User user = new User();
              User user2 = new User();
              user.setName("hhh");
              user.setAge(13);
              user2.setName("qqqq");
              user2.setAge(17);
              ArrayList<User> arrayList = new ArrayList<>();
              arrayList.add(user);
              arrayList.add(user2);
              return arrayList;
          }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14

# 跨域访问

当通过 A 域名下的操作访问 域名 B 下的资源时 称为跨域访问

我们可以通过设置头信息 开启跨域访问限制

但 spring 帮我完成这个操作 我们只需要添加 @CrossOrigin 就可以解决 定义在方法体或类上

    @RequestMapping("/cross")
    @ResponseBody
    @CrossOrigin
    public void cross() {

    }
1
2
3
4
5
6

# 拦截器

拦截器 (Interceptor) 是一种动态拦截方法调用的机制

  1. 在指定的方法调用前后执行预先设定后的代码
  2. 阻止原始方法的执行

核心原理:AOP 思想

拦截器链:多个拦截器按照一定的顺序 对原始被调用功能进行增强

实现 HandlerInterceptor 接口 重写需要的方法

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置运行");
        //如果为false 则直接拦截业务处理器不放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置运行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("完成运行");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/handleRun"/>
            <bean class="com.itheima.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
1
2
3
4
5
6

image-20210911201245600

# 拦截器参数

  • request 请求对象
  • response 响应对象
  • handler 被调用的处理器对象,对反射中的 method 对象进行了包装
  • ModelAndView 可以读取或者修改 页面信息和对应数据
  • Exception 如果处理器执行中出现异常 如何处理

# 多个拦截器

多个拦截器执行顺序与 xml 配置有关

但多个拦截器中的前置运行 后置运行 都会同时启用

按照链式 执行顺序

image-20210911201959609

# 责任链模式

image-20210911202501014

# 异常处理

类注解 @Component 绑定 Bean 为 并实现 HandlerExceptionResolver 接口 实现方法

此 bean 会拦截 mvc 上请求的异常

@Component
public class ExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {

        System.out.println("发生异常了");

        ModelAndView modelAndView =new ModelAndView();

        if(e instanceof NullPointerException){
            //添加错误信息
            modelAndView.addObject("msg","空指针异常");
        }else if (e instanceof ArithmeticException){
            //添加错误信息
            modelAndView.addObject("msg","算术异常");
        }else {
            //添加错误信息
            modelAndView.addObject("msg","未知异常");
        }

        //转发页面
        modelAndView.setViewName("error.jsp");
        return modelAndView;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 注解版异常处理

  • @ExceptionHandler 注解 标记要捕抓的异常
@Component
@ControllerAdvice
public class ExceptionAdivce {

    //异常 的类
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public String doNullException(Exception e){
        System.out.println("空指针异常");
        return "空指针异常";
    }

    //异常 的类
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public String doArithmeticException(Exception e){
        System.out.println("算术异常");
        return "算术异常";
    }

    //异常 的类
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public String doException(Exception e){
        System.out.println("all");
        return "all";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

注意事项:

@ExceptionHandler 注解 会比 HandlerExceptionResolver 运行早

HandlerExceptionResolver 无法捕抓到参数异常 而注解可以捕抓到

# 文件上传下载

坐标

  <!--文件上传下载-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>
1
2
3
4
5
6

image-20210911224634780

上传文件传递的 name 要与 形参的名称一致

# Restful

image-20210911225842650

image-20210911225850101

# PathVariable

@PathVariable 为 Restful 规范的请求路径 赋值给指定形参

并且在 @RequestMapping 的 method 指定请求方式

    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public String restLocation(@PathVariable Integer id){
        System.out.println(id);
        return "page.jsp";
    }
1
2
3
4
5

# RestController

@RestController 结合了 @Controller 和 @ResponseBody 两个注解的功能

绑定为 bean 并且 所有返回内容都不会解析为网页结构

# XXXMapping

如 @GetMapping @PostMapping 请求等等

我们不用在 @RequestMapping 中定义指定的请求方式 和 请求路径

只需在方法体加上指定请求方式的注解即

    @PostMapping("{id}")
    public String postrestLocation(@PathVariable Integer id){
        System.out.println(id);
        return "page.jsp";
    }
1
2
3
4
5

# 表单验证框架

Hibernate 框架

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.1.0.Final</version>
    </dependency>
1
2
3
4
5
  • @Valid 形参注解 开启此形参的验证
  • @Valid 属性注解 开启此对象或属性验证 对象校验在对象内部属性定义规则
  • @NotBlank (message = "提醒信息") 属性验证规则 不能为 null 并且长度必须大于 0 和不全为空格 则不能为空
  • @NotNull (message = "提醒信息") 不能为 null 可以为空
  • @NotEmpty (message = "") 不能为空和 null
  • @Max (value = "", message =" ") 限定最大值
  • @Min (value = "", message ="") 最小值
  • @Range (max = ,min = ,message =) 最大最小值
 @RequestMapping(value = "/addemployee2")
    //使用@Valid开启校验,使用@Validated也可以开启校验
    //Errors对象用于封装校验结果,如果不满足校验规则,对应的校验结果封装到该对象中,包含校验的属性名和校验不通过返回的消息
    public String addEmployee2(@Valid Employee employee, Errors errors, Model m){
        //判定Errors对象中是否存在未通过校验的字段
        if(errors.hasErrors()){
            //获取所有未通过校验规则的信息
            List<FieldError> fieldErrors = errors.getFieldErrors();
            System.out.println(fieldErrors.size());
            for(FieldError error : fieldErrors){
                System.out.println(error.getField());
                System.out.println(error.getDefaultMessage());
                //将校验结果信息添加到Model对象中,用于页面显示,后期实际开发中无需这样设定,返回json数据即可
                m.addAttribute(error.getField(),error.getDefaultMessage());
            }
            //当出现未通过校验的字段时,跳转页面到原始页面,进行数据回显
            return "addemployee.jsp";
        }
        return "success.jsp";
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @NotBlank(message = "姓名不能为空")
    private String name;//员工姓名

    //一个属性可以添加多个校验器
    @NotNull(message = "请输入您的年龄")
    @Max(value = 60,message = "年龄最大值不允许超过60岁")
    @Min(value = 18,message = "年龄最小值不允许低于18岁")
    private Integer age;//员工年龄

    //实体类中的引用类型通过标注@Valid注解,设定开启当前引用类型字段中的属性参与校验
    @Valid
    private Address address;
1
2
3
4
5
6
7
8
9
10
11
12

# 分组校验

如果不开启分组校验 则会校验当前全部开启校验的属性 / 对象

在属性 / 对象校验注解中 加上 groups 属性 并给予一个 用于标识的字节码文件

//设定校验器,设置校验不通过对应的消息,设定所参与的校验组
    @NotBlank(message = "姓名不能为空",groups = {GroupA.class})
    private String name;//员工姓名
1
2
3

拦截校验器 开启校验注解要改为 @Validated 并加上标识字节码文件

    @RequestMapping(value = "/addemployee")
    public String addEmployee(@Validated({GroupA.class}) Employee employee, Errors errors, Model m){
        if(errors.hasErrors()){
            List<FieldError> fieldErrors = errors.getFieldErrors();
            System.out.println(fieldErrors.size());
            for(FieldError error : fieldErrors){
                System.out.println(error.getField());
                System.out.println(error.getDefaultMessage());
                m.addAttribute(error.getField(),error.getDefaultMessage());
            }
            return "addemployee.jsp";
        }
        return "success.jsp";
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# SSM

Spring + SpringMVC + MyBatis

编辑 (opens new window)
上次更新: 2023/12/06, 01:31:48
Spring
Maven 高级

← Spring Maven 高级→

最近更新
01
k8s
06-06
02
进程与线程
03-04
03
计算机操作系统概述
02-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Iekr | Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式