前置知识要求:
Java基础
JavaWeb
MySQL
Mybatis
Spring基本原理
- SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
- 优点
- 使用简单,开发便捷(相比于Servlet)
- 灵活性强
入门案例
首先我们通过一个入门案例来快速了解SpringMVC的魅力
实现步骤
我们分为以下几个步骤来实现这个案例
注意:所用版本分别为jdk8, tomcat7, SpringMVC 5.2.10
- 创建maven工程,IDEA中点击新建项目,生成器选择Maven Archtype,之后Archtype选择webapp
- 设置tomcat服务器,加载web工程(tomcat插件)
- 导入坐标(SpringMVC+Servlet) 注意:因为SpringMVC基于Servlet实现,所以需要导入Servlet依赖
- 定义处理请求的控制类(UserController)
- 编写SpringMVC配置类,加载处理请求的Bean
- 加载SpringMVC配置,并设置SpringMVC请求拦截的路径为全部路径
代码实现
创建Maven工程
设置tomcat服务器
在项目中的pom.xml添加上下面这串代码
1 | <build> |
导入坐标
同样实在pom.xml配置如下代码
1 | <dependencies> |
注意版本问题
spring-webmvc坐标自动依赖spring相关坐标
定义控制类
在java中定义软件包,将控制类统一的放入controller包中
1 | //定义表现层控制器bean |
对于SpringMVC而言,Controller方法返回值默认表示要跳转的页面,没有对应的页面就会报错。如果不想跳转页面而是
响应数据,那么就需要在方法上使用@ResponseBody注解。
配置SpringMVC
在源代码目录中创建config包统一管理配置类,新建一个SpringMVCConfig
1 | //springmvc配置类,本质上还是一个spring配置类 |
加载SpringMVC配置
在config包中创建web容器的配置类
1 | //web容器配置类 |
简化格式:(AbstractAnnotationConfigDispatcherServletInitializer继承自AbstractDispatcherServletInitializer,对其方法进行简化封装)
1 | public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{ |
到此案例就结束了,点击IDEA,编辑配置, 在命令行中添加tomcat7: run,随后即可执行
分析案例类与注解
@Controller注解
- 名称:@Controller
- 类型:类注解
- 位置:SpringMVC控制器类定义上方
- 作用:设定SpringMVC的核心控制器bean
- 范例
1 |
|
@RequestMapping注解
- 名称:@RequestMapping
- 类型:方法注解, 类注解
- 位置:SpringMVC控制器方法或类定义上方
- 作用:设置当前控制器方法请求访问路径
- 范例
1 |
|
注意:其实@RequestMapping注解还可以写到类上面,代表统一的一个请求前缀
@ResponseBody注解
- 名称:@ResponseBody
- 类型:方法注解
- 位置:SpringMVC控制器方法定义上方
- 作用:设置当前控制器方法响应内容为当前返回值,无需解析(也就是只返回数据)
- 范例
1 |
|
AbstractDispatcherServletInitializer类
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
- createServletApplicationContext()方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围。
1
2
3
4
5
6//加载springmvc配置类,产生springmvc容器(本质还是spring容器)
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}- getServletMappings()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理。
1
2
3
4//设置由springmvc控制器处理的请求映射路径
protected String[] getServletMappings() {
return new String[]{"/"};
}- createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext()
1
2
3
4//加载spring配置类
protected WebApplicationContext createRootApplicationContext() {
return null;
}
案例工作流程分析
初始化流程
- 服务器启动,执行ServletContainersInitConfig类,初始化web容器
- 执行createServletApplicationContext方法,创建WebApplicationContext对象
- 加载SpringMVCConfig配置类
- 执行@ComponentScan加载对应的Bean
- 加载UserController,每个@RequestMapping的名称对应一个具体的方法
- 执行getServletMappings方法,定义所有的请求都通过SpringMVC
单次请求流程
- 发送请求localhost/save
- web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
- 解析请求路径/save
- 由/save匹配执行对应的方法save()
- 执行save()
- 检测到有@ResponseBody直接将save()方法的返回值作为响应求体返回给请求方
问题思考
因为各个bean的功能不同,我们怎么避免Spring错误的加载到SpringMVC的bean呢?
解决思路
- SpringMVC相关的bean在控制层,也就是controller中
- Spring所控制的bean在业务层service
- 解决方法
- 1:Spring加载的bean设定扫描范围为love.jiahao,排除掉controller包内的bean
- 2:Spring加载的bean设定扫描范围为精准范围,例如service包等
- 3:不区分Spring与SpringMVC的环境,加载到同一个环境中
方案一实现
在我们的Spring配置类中
1 |
|
方案二实现
在Spring配置类中@ComponentScan(“love.jiahao.service”)
在SpringMVC配置类中@ComponentScan(“love.jiahao.controller”)
请求与响应
请求参数
普通类型参数
直接在控制层的方法中,参数输入对应的参数类型和名称即可
如果参数名称和请求的一致,可以直接写
不一致,则需要进行映射,如:请求的参数是userName,接收的是name,需要进行@RequestParam(“userName”) String name
例如:
1 |
|
中文乱码解决
- Get请求乱码解决
tomcat 8.5版本之后GET请求就不再出现中文乱码问题,但是我们使用的是tomcat7插件,所以会出现GET请求中文乱码问
题。
解决:在pom.xml添加tomcat7插件处配置UTF-8字符集,解决GET请求中文乱码问题。
1 | <build> |
- Post请求乱码解决
解决:在加载SpringMVC配置的配置类中指定字符过滤器。
1 | public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { |
实体类接收参数
如果请求参数名和对象的属性名完全相同,我们定义一个POJO实体类,即可接收参数
例如请求参数为name和age,这时我们定义实体类来接收参数
1 |
|
控制层:
1 |
|
请求参数key的名称要和POJO中属性的名称一致,否则无法封装
===嵌套实体类参数===
- POJO对象中包含POJO对象
1 |
|
- 嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
1 | //嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递 |
请求参数key的名称要和POJO中属性的名称一致,否则无法封装。
数组与集合参数
- 数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型即可接收参数
1 | //数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中 |
- 集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,**@RequestParam绑定参数关系**
1 | //集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据 |
JSON参数
对于JSON类型的参数,我们想要接收,首先我们需要在项目中导入JSON数据转换的相关坐标
1 | <dependency> |
其次要开启一个配置,在SpringMVCConfig中加入注解@EnableWebMvc,该注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
1 |
|
所用到的注解解释
- 名称:@EnableWebMvc
- 类型:==配置类注解==
- 位置:SpringMVC配置类定义上方
- 作用:开启SpringMVC多项辅助功能
- 范例:
1 |
|
- 名称:@RequestBody
- 类型:==形参注解==
- 位置:SpringMVC控制器方法形参定义前面
- 作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
- 范例:
1 |
|
JSON普通数组
例如: [“”, “”, “”]
在Controller中编写方法接收json参数
1 |
|
JSON对象
例如: {“name”: “张三”, “age”: 18}
- 定义实体类进行接收
1 |
|
- 控制层编写方法
1 |
|
JSON对象数组
例如: [{“name”: “张三”, “age”: 18}, {“name”: “李四”, “age”: 20}]
控制层编写方法
1 |
|
POJO集合参数:json数组数据与集合泛型属性名相同,定义List类型形参即可接收参数
@RequestBody与@RequestParam区别
- 区别
@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
@RequestBody用于接收json数据【application/json】 - 应用
后期开发中,发送json格式数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数
日期类型参数
我们知道,平常使用的日期都由差异,但是对于程序来说,就要接收不同的日期类型,所以我们需要对此进行格式化
例如:接收到2088-08-18, 2088/08/18, 08/18/2088 需要我们将其分别接收
- 接收形参时,根据不同的日期格式设置不同的接收方式
- 控制层实现
1 |
|
@DateTimeFormat注解介绍
名称:@DateTimeFormat
类型:==形参注解==
位置:SpringMVC控制器方法形参前面
作用:设定日期时间型数据格式
属性:pattern:指定日期时间格式字符串
- 工作原理
- 其内部依赖Converter接口
1 | public interface Converter<S, T> { |
传递日期类型参数必须在配置类上使用@EnableWebMvc注解。其功能之一:根据类型匹配对应的类型转换器。
响应
响应页面[了解]
控制层
1 |
|
静态页面
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
文本数据[了解]
1 | //响应文本数据 |
JSON数据[重点]
1 | //响应POJO对象 |
1 | //响应POJO集合对象 |
==注意:需要添加jackson-databind依赖以及在SpringMvcConfig配置类上添加@EnableWebMvc
REST风格
REST(Representational State Transfer),表现形式状态转换,其实就是根据请求方式不同,进行不同的操作
优点:
- 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
- 书写简化
表现形式:
- 按照REST风格访问资源时使用==行为动作==区分对资源进行了何种操作
http://localhost/users 查询全部用户信息 (查询) GET
http://localhost/users/1 查询指定用户信息(查询) GET
http://localhost/users 添加用户信息(新增/保存) POST
http://localhost/users 修改用户信息(修改/更新) PUT
http://localhost/users/1 删除用户信息(删除) DELETE - 根据REST风格对资源进行访问称为RESTful
上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts……
快速入门:
做法:我们只需要把原来的@RequestMapping切换成对应的请求方式的注解(例如: GetMapping, PostMapping等),就可以设置当前路径的请求方式
1 | // 整合了RequestMapping(value = "/toText", method = RequestMethod.POST) |
注解解释:
@PathVariable
- 名称:@PathVariable
- 类型:形参注解
- 位置:SpringMVC控制器方法形参定义前面
- 作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
1 |
|