SpringMVC介绍
什么是SpringMVC
SpringMVC=Spring+MVC。
SpringMVC是一个Spring内置的MVC Web框架,英文缩写(Model-View-Controller)。
MVC框架解决了Web开发中常见的问题(参数接收、文件上传、表单验证、国际化等等),而且使用简单,与Spring无缝集成,支持RESTful风格而的URL请求。采用了松散耦合可插播组件结构,比其他MVC框架更具有扩展性和灵活性。
SpringMVC的作用
MVC模式(Model-View-Controller):解决页面代码和后台代码的分离。
MVC模型
通常情况下,一个完整的 Java Web 应用程序,其结构如下图所示。

MVC 模式将应用程序划分成模型(Model)、视图(View)、控制器(Controller)等三层,如下图所示。

| 分层 | 描述 |
|---|---|
| Model(模型) | 它是应用程序的主体部分,主要由以下 2 部分组成: 实体类 Bean:专门用来存储业务数据的对象,它们通常与数据库中的某个表对应,例如 User、Student 等。 业务处理 Bean:指 Service 或 Dao 的对象,专门用于处理业务逻辑、数据库访问。 一个模型可以为多个视图(View)提供数据,一套模型(Model)的代码只需写一次就可以被多个视图重用,有效地减少了代码的重复性,增加了代码的可复用性。 |
| View(视图) | 指在应用程序中专门用来与浏览器进行交互,展示数据的资源。在 Web 应用中,View 就是我们常说的前台页面,通常由 HTML、JSP、CSS、JavaScript 等组成。 |
| Controller(控制器) | 通常指的是,应用程序的 Servlet。它负责将用户的请求交给模型(Model)层进行处理,并将 Model 层处理完成的数据,返回给视图(View)渲染并展示给用户。 在这个过程中,Controller 层不会做任何业务处理,它只是 View(视图)层和 Model (模型)层连接的枢纽,负责调度 View 层和 Model 层,将用户界面和业务逻辑合理的组织在一起,起粘合剂的效果。 |
MVC模式 VS 三层架构
和 MVC 模式类似,三层架构同样将系统划分成了 3 层:
- 表示层(UI):用来实现与用户的交互,接收用户请求,并将请求交给业务逻辑层(BLL)和数据访问层(DAL)进行处理,最后将处理结果返回给用户。
- 业务逻辑层(BLL):起到承上启下的作用,接收表示层传递来的请求,并针对业务对数据进行处理,以实现业务目标。
- 数据访问层(DAL):用于实现与数据库的交互和访问,例如从数据库中获取数据、保存或修改数据库中的数据等。
虽然三层架构和 MVC 模式一样,都是将应用划分成了 3 层,但它们的划分方式是不同的。
下图展示了三层架构的划分方式,我们可以很清楚地分辨出它与 MVC 模式的不同。

从上图可以看出,三层架构是由表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三个层次构成的,而 MVC 则是由视图(View)层、控制(Controller)层以及模型(Model)层,且它们之间并不是一一对应的。
三层架构和 MVC 模式中各层对应关系如下:
- 三层架构中的表示层(UI)包含 HTML、JSP 等前台页面以及后台的 Servlet,即它相当于 MVC 模式中的 View 层 + Controller 层。
- 三层架构中的业务逻辑层(BLL),则只包含了 Service 接口及其实现类(Servicelmpl)的代码,即它相当于 MVC 模式中 Model 层的一部分,并不包含 Dao 和实体类。
- 三层架构中的数据访问层(DAL),则只包含了 Dao 接口及其实现类(DaoImpl)的代码,即它相当于 MVC 模式中 Model 层的一部分,并不包含 Service 和实体类。
三层架构将应用中的各个模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)等三层,各层之间采用接口相互访问,并通过实体类作为数据传递的载体。不同的实体类一般对应于数据库中不同的数据表,且实体类的属性与数据库表的字段名一一对应 。
{% note pink ‘fas fa-virus’ flat %}
从上面的划分方式来看,三层架构和 MVC 模式确实是不一样的,但从它们的核心来看,两者又是一样的,它们的核心都是“分层、解耦”。
{% endnote %}
MVC的工作流程
MVC 的工作流程如下:
- 用户发送请求到服务器;
- 在服务器中,请求被控制层(Controller)接收;
- Controller 调用相应的 Model 层处理请求;
- Model 层处理完毕将结果返回到 Controller;
- Controller 再根据 Model 返回的请求处理结果,找到相应的 View 视图;
- View 视图渲染数据后最终响应给浏览器。
MVC 的优点
MVC 模式具有以下优点:
- 降低代码耦合性:在 MVC 模式中,三层之间相互独立,各司其职。一旦某一层的需求发生了变化,我们就只需要更改相应层中的代码即可,而不会对其他层中的代码造成影响。
- 有利于分工合作:在 MVC 模式中,将应用系统划分成了三个不同的层次,可以更好地实现开发分工。例如,网页设计人员专注于视图(View)层的开发,而那些对业务熟悉的开发人员对 Model 层进行开发,其他对业务不熟悉的开发人员则可以对 Controller 层进行开发。
- 有利于组件的重用:在 MVC 中,多个视图(View)可以共享同一个模型(Model),大大提高了系统中代码的可重用性。
MVC 的不足
MVC 模式存在以下不足之处:
-
增加了系统结构和实现的复杂性:对于简单的应用,如果也严格遵循 MVC 模式,按照模型、视图与控制器对系统进行划分,无疑会增加系统结构的复杂性,并可能产生过多的更新操作,降低运行效率。
-
视图与控制器间的联系过于紧密:虽然视图与控制器是相互分离的,但它们之间联系却是十分紧密的。视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了它们的独立重用。
-
视图对模型数据的低效率访问:视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
MVC 并不适合小型甚至中型规模的项目,花费大量时间将 MVC 应用到规模并不是很大的应用程序中,通常会得不偿失,因此对于 MVC 设计模式的使用要根据具体的应用场景来决定。
SpringMVC入门案例
创建项目顺序
- 创建项目
- 导入jar包
- 创建控制器(Controller),控制URL的走向。
- 创建SpringMVC配置类(类似Spring配置类),目的是为了加载bean对象。
- 初始化SpringMVC环境
- 测试结果
创建Tomcat项目
创建一个Tomcat的项目,我这里使用JDK11,Tomcat9、

导入jar包
SpringMVC基于springframework扩展,我们导入spring-webmvc包和servlet包就可以了。在pom.xml文件导入以下坐标
<!-- 1. 导入springmvc和servlet坐标-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
创建Controller类
创建controller控制器类,类似jsp中的servlet类一样。在jsp中,我们需要创建多个servlet的类,就比较复杂,但在springmvc中,一个controller中可以有多个servlet,用注解简化servlet类。
比如,以下,我们在访问http://localhost:8080/springmvc_01_demo_war_exploded/find和http://localhost:8080/springmvc_01_demo_war_exploded/save都可以访问到指定的路径。
package site.hikki.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
//2. 定义controller
//2.1使用controller定义bean
@Controller
public class UserController {
// 2.2设置当前操作的访问路径
@RequestMapping("/save")
// 2.3 设置当前操作的返回类型
@ResponseBody
public String save(){
System.out.println("UserController save ...");
return "{'name':'blog.hikki.site'}";
}
@RequestMapping("/find")
@ResponseBody
public String find(){
System.out.println("UserController find ...");
return "{'name':'https://blog.hikki.site'}";
}
}
加载SpringMVC的bean对象
加载SpringMVC对应的bean,使用@ComponentScan注解扫描bean,和Spring一样,都需要扫描bean的对象。
{% folding blue , 回顾Spring的知识点 %}
回顾Spring的知识点
{% note pink ‘fas fa-bullhorn’ simple %}
配置当前类是bean对象,有三个注解都可以实现,三个注解表示的意思是一样的,我们常常将他们区分开始为了更好的理解代码,理解当前的bean是作用,提高开发效率。
@Controller:控制器(注入服务)。@Repository:dao持久层(实现dao访问),标注数据访问组件。@Service:service服务层(注入dao),处理业务逻辑。@component: 标注一个类为Spring容器的Bean,(把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)
{% endnote %}
{% endfolding %}
使用@Controller表示当前类是bean对象
package site.hikki.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 1.创建springmvc的额配送至文件吗,加载controller对应的bean
@ComponentScan("site.hikki.controller")
@Configuration
public class SpringMvcConfig {
}
初始化SpringMVC环境
{% tabs %}
- 初始化Servlet容器
- 加载SpringMVC环境
- 设置SpringMVC请求拦截的路径
package site.hikki.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
//4.定义一个servlet容器启动的配置类,在里面加载spring的配置
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
// 加载springmMVC容器配置
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
// 设置哪些请求归属springMVC处理
protected String[] getServletMappings() {
return new String[]{"/"}; //表示所有请求都归springmvc管
}
// 加载spring容器配置
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
简洁的写法可以快速配置,提高开发效率,我们一般在使用熟悉后,在开发中用下面这张简洁的写法较多,但对于初学者理解Spring不太友好。
package site.hikki.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
//web配置类简化开发,仅设置配置类类名即可
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
// 加载spring容器配置
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
// 加载springmMVC容器配置
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
// 设置哪些请求归属springMVC处理
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
{% endtabs %}
测试
打开http://localhost:8080/springmvc_01_demo_war_exploded/find,查看结果。

{% note blue ‘fas fa-download’ flat %}
项目下载地址:https://rookie1679.lanzoum.com/iJJCm0m7vdyd
{% endnote %}
总结
注解总结
上面我们使用了几个新的注解,分别是@Controller、@RequestMapping、@ResponseBody。
{% tabs %}
-
名称:@Controller
-
类型:类注解
-
位置:SpringMVC控制器类定义上方
-
作用:设定SpringMVC的核心控制器bean
-
案例:
java@Controller public class UserController { }
- 名称:@RequestMapping
- 类型:方法注解
- 位置:lSpringMVC控制器方法定义上方
- 作用:设置当前控制器方法请求访问路径
- 案例:
@RequestMapping("/save")
public void save(){
System.out.println("user save ...");
}
- 相关属性
- value(默认):请求访问路径
-
名称:@ResponseBody
-
类型:方法注解
-
位置:SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法响应内容为当前返回值,无需解析
-
案例:
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'info':'springmvc'}";
}
{% endtabs %}
方法总结
1. 加载springmMVC容器配置
-
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
-
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
- createServletApplicationContext()方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围。
// 加载springmMVC容器配置
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
2. 设置哪些请求归属springMVC处理
-
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
-
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
- getServletMappings()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理
// 设置哪些请求归属springMVC处理
protected String[] getServletMappings() {
return new String[]{"/"}; //表示所有请求都归springmvc管
}
3. 加载spring容器配置
-
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
-
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
- createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext()
// 加载spring容器配置
protected WebApplicationContext createRootApplicationContext() {
return null;
}
SpringMVC工作流程
容器初始化工作流程
{% hideToggle 1.初始化web容器 %}
1. 服务器启动,执行ServletContainersInitConfig类,初始化web容器
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
}
{% endhideToggle %}
{% hideToggle 2.创建了WebApplicationContext对象 %}
2. 执行createServletApplicationContext方法,创建了WebApplicationContext对象
// 加载springmMVC容器配置
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
{% endhideToggle %}
{% hideToggle 3.加载SpringMvcConfig %}
3. 加载SpringMvcConfig
在上一步中,创建Web专用的Ioc容器中,注册了SpringMvcConfig类的配置。
// 1.创建springmvc的额配送至文件吗,加载controller对应的bean
@ComponentScan("site.hikki.controller")
@Configuration
public class SpringMvcConfig {
}
{% endhideToggle %}
{% hideToggle 4.加载bean对象 %}
4. 执行@ComponentScan加载对应的bean
加载site.hikki.controller包下的对bean象。
@ComponentScan("site.hikki.controller")
{% endhideToggle %}
{% hideToggle 5.加载每一个URL控制器 %}
5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法
每一个URL控制器,都使用@RequestMapping控制着URL执行对应的方法。
// 2.2设置当前操作的访问路径
@RequestMapping("/save")
// 2.3 设置当前操作的返回类型
@ResponseBody
public String save(){
System.out.println("UserController save ...");
return "{'name':'blog.hikki.site'}";
}
@RequestMapping("/find")
@ResponseBody
public String find(){
System.out.println("UserController find ...");
return "{'name':'https://blog.hikki.site'}";
}
{% endhideToggle %}
{% hideToggle 6.设置URL请求走向 %}
6. 执行getServletMappings方法,定义所有的请求都通过SpringMVC
return new String[]{"/"}定义全部URL都归springmvc管。
// 设置哪些请求归属springMVC处理
protected String[] getServletMappings() {
return new String[]{"/"}; //表示所有请求都归springmvc管
}
{% endhideToggle %}

单次请求工作流程
- 发送请求localhost/save
- web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
- 解析请求路径/save
- 由/save匹配执行对应的方法save()
- 执行save()
- 检测到有@ResponseBody直接将save()方法的返回值作为响应求体返回给请求方

Spring & SpringMVC对应Bean加载
疑问:因为功能不同,如何避免Spring错误的加载到SpringMVC的bean?
在项目中,我们会有多个Bean,比如表现层的bean,控制层的bean,数据层的bean。我们如何控制Spring在加载bean的时候,不加载SpringMVC的bean呢?
Controller加载控制与业务Bean加载控制
-
SpringMVC相关bean(表现层bean)
-
Spring控制的bean
-
业务bean(Service)
-
功能bean(DataSource等)
-
-
SpringMVC相关bean加载控制
- SpringMVC加载的bean对应的包均在com.itheima.controller包内
-
Spring相关bean加载控制
- 方式一:
Spring加载的bean设定扫描范围为site.hikki,排除掉controller包内的bean - 方式二:
Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等 - 方式三:
不区分Spring与SpringMVC的环境,加载到同一个环境中
- 方式一:
代码实现
{% tabs %}
我们可以指定扫描范围,精准指定扫描不含controller的包,需要注意的是,我们在使用mybatis时,是总自定义的bean,但还是建议在扫描时,也将dao的包添加到扫描范围内,因为可能在某时候,你会重写一些方法时,需要添加到bean对象,就容易报错找不到bean对象,所以,建议除了controller控制器,其他都添加到扫描范围内。
package site.hikki.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"site.hikki.dao","site.hikki.service"}) // 方法一
public class SpringConfig {
}
指定整个项目的包都添加到扫描范围内,其中在整个包的扫描范围排除带有@controller注解的bean。
package site.hikki.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
@Configuration
@ComponentScan(value="site.hikki", // 方法二
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
{% endtabs %}
{% note blue ‘fas fa-download’ flat %}
项目下载地址:https://rookie1679.lanzoum.com/iYCkX0md2zkd
{% endnote %}
SpringWeb映射路径
{% note blue ‘fas fa-volume-up’ flat %}
以下实验使用的是Apifox客户端进行调试,当然,你用Postman也可以,取决于你的使用习惯。
{% endnote %}
我们以前在学JSP时,我们每一个映射路径都要用一个Servlet类来表示,这样做让开发效率很低,也很繁琐,SpringMVC中,有给我们提供很好用的映射路径方式,只需要一个注解即可,并且不需要创建多个Servlet类就可以实现,可以在一个类中,设置多个映射路径。
代码实现
我们在之前的学习中,我们也有写过映射路径,如下就是一个简单的映射路径的例子,在方法名上面添加@RequestMapping注解,值就是映射的路径。
package site.hikki.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ControllerStudent {
@RequestMapping("find")
@ResponseBody
public String findAll(){
System.out.println("ControllerStudent findAll..");
return "return ControllerStudent findAll..";
}
@RequestMapping("add")
@ResponseBody
public String add(){
System.out.println("ControllerStudent add..");
return "return ControllerStudent add..";
}
}
我们访问一下上面的路径试一下,运行项目:

我们仔细观察一下代码,我们设置的映射路径和方法名是可以不一样。
进阶
我们如果想给这些映射路径添加一个前缀怎么实现?
在SpringMVC控制器类名上方添加@RequestMapping("student")就可以了。
package site.hikki.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("student")
public class ControllerStudent {
@RequestMapping("find")
@ResponseBody
public String findAll(){
System.out.println("ControllerStudent findAll..");
return "return ControllerStudent findAll..";
}
@RequestMapping("add")
@ResponseBody
public String add(){
System.out.println("ControllerStudent add..");
return "return ControllerStudent add..";
}
}

总结
-
名称:@RequestMapping
-
类型:方法****注解 类注解
-
位置:SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
-
属性
- value(默认):请求访问路径,或访问路径前缀
-
案例:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
}
参数传递
我们常用的请求参数方式有两种,GET、POST请求。
- GET请求
- POST请求
代码实现
{% tabs %}
我们使用findByNum方法来测试接收一个参数打印并返回到客户端。
package site.hikki.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("student")
public class ControllerStudent {
@RequestMapping("findByNum")
@ResponseBody
public String findByNum(Integer num){
System.out.println("findByNum===>"+num);
return "findByNum===>"+num;
}
@RequestMapping("find")
@ResponseBody
public String findAll(){
System.out.println("ControllerStudent findAll..");
return "return ControllerStudent findAll..";
}
@RequestMapping("add")
@ResponseBody
public String add(){
System.out.println("ControllerStudent add..");
return "return ControllerStudent add..";
}
}
我们在方法的形参中定义与实参变量名相同,即可接收到参数。
如果定义的形参与实参变量名不相同,则接受到的值为null,接受参数失败。
这里使用普通的参数传递。

我们在add方法中,在形参中接收了多个参数并打印出来。
package site.hikki.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("student")
public class ControllerStudent {
@RequestMapping("findByNum")
@ResponseBody
public String findByNum(Integer num){
System.out.println("findByNum===>"+num);
return "findByNum===>"+num;
}
@RequestMapping("find")
@ResponseBody
public String findAll(){
System.out.println("ControllerStudent findAll..");
return "return ControllerStudent findAll..";
}
@RequestMapping("add")
@ResponseBody
public String add(Integer num,String name,String age,String major){
System.out.println("findByNum===>"+num);
System.out.println("name===>"+name);
System.out.println("age===>"+age);
System.out.println("major===>"+major);
return "return ControllerStudent add..";
}
}
传递多个参数时,我使用from表单模拟传输参数

结果如下:

结果看到,带有中文的都乱码了,在以前我们学习的JSP中,我们在Servlet接收参数前都会定义字符集,防止数据乱码,在SpringMVC中,也有这样的一种方法。
POST中文乱码问题
在Servlet容器初始化类中重写getServletFilters方法,设置字符集为UTF-8就可以避免中文乱码了。
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}

GET请求中文乱码问题
- 原因:tomcat 8.5版本之后GET请求就不再出现中文乱码问题,但是我们使用的是tomcat7插件,所以会出现GET请求中文乱码问题。
- 解决:在pom.xml添加tomcat7插件处配置UTF-8字符集,解决GET请求中文乱码问题。
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>9090</port>
<path>/</path> <!--项目访问路径。当前配置的访问是localhost:9090/, 如果配置是/aa,则访问路径为localhost:9090/aa -->
<uriEncoding>UTF-8</uriEncoding><!--访问路径编解码字符集-->
</configuration>
</plugin>
</plugins>
{% endtabs %}
五种类型参数
- 普通参数【重点】
- POJO类型参数(重点)
- 嵌套POJO类型参数(重点)
- 数组类型参数
- 集合类型参数
{% tabs %}
普通参数:当请求参数名与形参变量名不同,使用@RequestParam绑定参数关系。

//普通参数:请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系
@RequestMapping("findByNum")
@ResponseBody
public String findByNum(@RequestParam("num") Integer Studentnum){
System.out.println("findByNum===>"+Studentnum);
return "findByNum===>"+Studentnum;
}
| 名称 | @RequestParam |
|---|---|
| 类型 | 形参注解 |
| 位置 | SpringMVC控制器方法形参定义前面 |
| 作用 | 绑定请求参数与处理器方法形参间的关系 |
| 参数1:required | 是否为必传参数 |
| 参数2:defaultValue | 参数默认值 |
POJO类型参数【重点】
POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数。
新建一个Student实体类:
package site.hikki.entity;
public class Student {
private Integer num;
private String name;
private String age;
private String major;
@Override
public String toString() {
return "Student{" +
"num=" + num +
", name='" + name + '\'' +
", age='" + age + '\'' +
", major='" + major + '\'' +
'}';
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
}

在SpringMVC控制器下新建一个pojo方法,并设置路径映射,形参使用Student接收,Student中定义了四个属性,分别为num、name、age、major,设置get、set方法,并重写toString方法。
//POJO参数传递
//嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递
@RequestMapping("pojo")
@ResponseBody
public String pojo(Student student){
System.out.println(student);
return "student===>"+student;
}
结果:
在请求参数中,使用Student一样的变量名就可以自动将参数接收到Student实体类中,如果在请求的参数中缺少实体类Student中的哪一个属性,则该属性的值为null

- 嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
1. 新建Grade实体类:
package site.hikki.entity;
public class Grade {
private String discipline;
private double score;
@Override
public String toString() {
return "Grade{" +
"discipline='" + discipline + '\'' +
", score=" + score +
'}';
}
public String getDiscipline() {
return discipline;
}
public void setDiscipline(String discipline) {
this.discipline = discipline;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
2. 在Student中添加Grade属性:
添加属性后并设置set和get方法,并重写toString方法。
private Grade grade;
@Override
public String toString() {
return "Student{" +
"num=" + num +
", name='" + name + '\'' +
", age='" + age + '\'' +
", major='" + major + '\'' +
", grade=" + grade +
'}';
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
3. 在SpringMVC添加方法
//POJO嵌套POJO参数传递
@RequestMapping("pojoinpojo")
@ResponseBody
public String pojoinpojo(Student student){
System.out.println(student);
return "student===>"+student;
}
在添加变量时,嵌套的实体类的变量,需要添加前缀,grade.discipline,前缀grade为Student实体类的变量名

**结果:**嵌套POJO可以完全接收,SpringMVC自动将我们的参数自动注入到Grade实体类中。

- 数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型即可接收参数

在SpringMVC控制器下新建一个array方法,并设置路径映射。形参使用字符数组接收。
//数组类型参数传递
//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
@RequestMapping("/array")
@ResponseBody
public String arrayParam(String[] likes){
System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));
return "{'likes':'"+ Arrays.toString(likes) +"'}";
}
结果:

- 集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系

//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/list")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'likes':'"+ likes +"'}";
}

{% endtabs %}
JSON对象传递
JSON数据参数介绍
- json普通数组([“”,“”,“”,…])
- json对象({key:value,key:value,…})
- json对象数组([{key:value,…},{key:value,…}])
JSON有多种数据类型,但数据传输的方式都是差不多的。
json数据接收步骤
- 添加依赖
- 开启json数据类型自动转换(
@EnableWebMvc) - 数据实参构造JSON格式
- 在SpringMVC控制器下方法形参添加
@RequestBody注解
代码实现
{% tabs %}
1. 添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
2. 开启自动转换json数据的支持(@EnableWebMvc)
注意事项:@EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
package site.hikki.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan(value = "site.hikki")
@EnableWebMvc //开启自动转换json数据的支持
public class SpringMvcConfig {
}
3. 数据实参构造JSON格式

4. 在SpringMVC控制器下方法形参添加@RequestBody注解
//集合参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
@RequestMapping("/json")
@ResponseBody
public String json(@RequestBody List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'likes':'"+ likes +"'}";
}
- POJO参数:json数据与形参对象属性名相同,定义POJO类型形参即可接收参数
- 添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
2. 开启自动转换json数据的支持(@EnableWebMvc)
注意事项:@EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
package site.hikki.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan(value = "site.hikki")
@EnableWebMvc //开启自动转换json数据的支持
public class SpringMvcConfig {
}
3. 构造json对象实体类
我这里嵌套了实体类,在Student中嵌套了Grade。

我们在嵌套POJO时,使用{}括上被嵌套的实体类即可。
4. 在SpringMVC控制器下方法形参添加@RequestBody注解
@RequestMapping("/jsonobject")
@ResponseBody
public String jsonObject(@RequestBody Student student){
System.out.println("json参数传递 student ==> "+ student);
return "{'student':'"+ student +"'}";
}
结果:

- 添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
2. 开启自动转换json数据的支持(@EnableWebMvc)
注意事项:@EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
package site.hikki.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan(value = "site.hikki")
@EnableWebMvc //开启自动转换json数据的支持
public class SpringMvcConfig {
}
3. 构造json对象数组实体类

在构造json数组时,使用[]括住数组。
4. 在SpringMVC控制器下方法形参添加@RequestBody注解
//3. json数组对象嵌套
@RequestMapping("/jsonobjectarray")
@ResponseBody
public String jsonObjectArray(@RequestBody List<Student> student){
System.out.println("json参数传递 student ==> "+ student);
return "{'student':'"+ student +"'}";
}
结果:
运行结果显示如下:
json参数传递 student ==> [Student{num=2040811177, name='小码同学', age='20', major='计算机科学与技术', grade=Grade{discipline='Java程序设计', score=90.5}}, Student{num=2040811178, name='吴小白', age='20', major='计算机科学与技术', grade=Grade{discipline='Java程序设计', score=60.5}}]
{% endtabs %}
总结
@EnableWebMvc注解介绍
- 名称:@EnableWebMvc
- 类型:==配置类注解==
- 位置:SpringMVC配置类定义上方
- 作用:开启SpringMVC多项辅助功能
- 范例:
@Configuration
@ComponentScan("site.hikki.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
@RequestBody注解介绍
- 名称:@RequestBody
- 类型:==形参注解==
- 位置:SpringMVC控制器方法形参定义前面
- A作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法
只能使用一次 - 范例:
@RequestMapping("/json")
@ResponseBody
public String json(@RequestBody List<String> likes){
System.out.println("json参数传递 likes ==> "+ likes);
return "{'likes':'"+ likes +"'}";
}
@RequestBody与@RequestParam区别
- 区别
@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
@RequestBody用于接收json数据【application/json】 - 应用
后期开发中,发送json格式数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数
日期参数传递
日期参数传递和其他参数传递类似的,只是日期参数传递要处理一下日期的格式。
请求参数

接收参数
一样是在COntroller下编写方法,使用形参接收。
其中,接受的日期格式默认是“2023/02/01”这种格式,则需要使用@DateTimeFormat注解。
//4. 日期转换
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2){
System.out.println("参数传递 date ==> "+date);
System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);
System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
return "{'module':'data param'}";
}
@DateTimeFormat注解介绍
-
名称:@DateTimeFormat
-
类型:==形参注解==
-
位置:SpringMVC控制器方法形参前面
-
作用:设定日期时间型数据格式
-
属性:pattern:指定日期时间格式字符串
3.3 工作原理
- 其内部依赖Converter接口
public interface Converter<S, T> {
@Nullable
T convert(S var1);
}
- 请求参数年龄数据(String→Integer)
- json数据转对象(json → POJO)
- 日期格式转换(String → Date)
传递日期类型参数必须在配置类上使用@EnableWebMvc注解。其功能之一:根据类型匹配对应的类型转换器。
{% note blue ‘fas fa-download’ flat %}
项目下载地址:https://rookie1679.lanzoum.com/iUaRD0mdxnkh
{% endnote %}
响应数据
响应数据一般有多种类型,分别是以下三种:
- 响应页面
- 响应文本数据
- 响应json数据
{% tabs 响应数据 %}
//1. 响应页面
@RequestMapping("/toStudent")
public String toPage(){
System.out.println("响应student.jsp页面");
return "student.jsp";
}
//2. 响应文本数据
@RequestMapping("/toText")
@ResponseBody
public String toText(){
System.out.println("响应文本数据");
return "response Text";
}
1. 实体类就哈好比一个json数据,实体类会自动转换成json格式,他依赖于jackson-databind模块的作用。
2. 并且需要开启json自动转化功能,在SpringMvcConfig添加@EnableWebMvc注解
1. 响应POJO对象
//3. 响应POJO类型数据
@RequestMapping("/toPOJO")
@ResponseBody
public Student toEntity(){
System.out.println("响应实体类,也就是POJO");
Student student=new Student();
student.setName("小码同学");
student.setAge("20");
student.setMajor("计算机科学与技术");
student.setNum(2040811177);
return student;
}
2. 响应POJO列表
//4. 响应POJO集合对象
@RequestMapping("/toEntityList")
@ResponseBody
public List<Student> toEntityList(){
Student student = new Student();
student.setNum(2040811177);
student.setName("小码同学");
student.setAge("20");
student.setMajor("计算机科学与技术");
Student student1 = new Student();
student1.setNum(2040800000);
student1.setName("吴小白");
student1.setAge("28");
student1.setMajor("物联网");
ArrayList<Student> list = new ArrayList<>();
list.add(student);
list.add(student1);
return list;
}
{% endtabs %}
{% note blue ‘fas fa-download’ flat %}
项目下载地址:https://rookie1679.lanzoum.com/ilRqD0me2a5e
{% endnote %}
Apifox请求接口文件下载:https://rookie1679.lanzoum.com/iiLGE0me39ze

