SpringMVC入门案例
SpringMVC和Spring是父子关系,他是Spring中专门用于web开发的模块。
Spring框架主要有两种类型的容器:核心容器(Spring容器)和Web容器(Spring MVC容器)。
- Spring容器:也被称为IoC容器,它负责实现依赖注入以管理Beans。Spring容器负责创建Bean、装配Bean、管理Bean的生命周期等任务。它使用XML文件或者注解来配置并初始化应用对象及其关联。在Spring容器中,常见的组件包括Service层的服务组件、DAO层的数据访问组件等。
- Spring MVC容器:也叫做子容器或者Web容器,它是在Spring容器的基础上增加了对Web应用的支持,特别是MVC设计模式的支持。Spring MVC容器会管理控制器、视图解析器、处理器映射等Web相关的组件。但需要注意的是,Spring MVC容器能访问Spring容器的Beans,但反过来则不行。
流程
- 创建web工程(Maven结构)
- 设置tomcat服务器,加载web工程(tomcat插件)
- 导入坐标(SpringMVC+Servlet)
- 定义处理请求的功能类(UserController)
- 设置请求映射(配置映射关系【请求路径】)
- 将SpringMVC设定加载到Tomcat容器中

引入相关依赖
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<!--会关联Spring基本模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.9</version>
</dependency>
</dependencies>
分层
Controller
@Controller // 这是一个控制器类的标识,表示这是一个Spring MVC控制器
@RequestMapping("user") //所有球球路径的前缀
@ResponseBody // 此注解表示方法的返回值将作为响应的请求体,而不是视图名称【页面】
public class UserController {
@RequestMapping("/save") // 方法级别的路径映射,完整的访问路径是"user/save"
public String saveUser() {
String msg = "用户正在保存";
System.out.println(msg);
return msg; // 这个字符串会作为响应的请求体返回给客户端
}
}
Config
@Configuration
@ComponentScan("bid.simpleword.controller") //这里包扫描controller由SpringMVC管理,如果要配置Spring,SpringConfig应该扫描service和dao
public class SpringMvcConfig {
}
public class ServletConfig extends AbstractDispatcherServletInitializer {
//加载SpringMVC容器对象
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); //注意
ctx.register(SpringMvcConfig.class);
return ctx;
}
//哪些请求需要由SpringMVC处理
@Override
protected String[] getServletMappings() {
//配置请求交由MVC处理【这里配置所有】,还是tomact[默认]
return new String[]{"/"};
}
//加载Spring容器对象
@Override
protected WebApplicationContext createRootApplicationContext() {
//现在我们还不需要Spring
return null;
}
}
访问【启动tomcat】,访问:localhost:8080/user/save
启动流程


注意事项
- 有多个controller有相同的请求路径,应该设置父级访问路径
Post请求中文乱码处理
过滤器,设置编码格式是UTF-8
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
请求参数
-
基本类型参数
-
pojo类型
-
数组
-
集合
-
json
@Controller
@ResponseBody
public class UserController {
//普通参数:请求参数与形参名称对应即可完成参数传递
@RequestMapping("/commonParam")
public String commonParam(String name ,int age){
System.out.println("普通参数传递 name ==> "+name);
System.out.println("普通参数传递 age ==> "+age);
return "{'module':'common param'}";
}
//普通参数:请求参数名与形参名不同时,使用@RequestParam注解关联请求参数名称与形参名称之间的关系
@RequestMapping("/commonParamDifferentName")
public String commonParamDifferentName(@RequestParam("name") String userName , int age){
System.out.println("普通参数传递 userName ==> "+userName);
System.out.println("普通参数传递 age ==> "+age);
return "{'module':'common param different name'}";
}
//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
public String pojoParam(User user){
System.out.println("pojo参数传递 user ==> "+user);
return "{'module':'pojo param'}";
}
//嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递
@RequestMapping("/pojoContainPojoParam")
public String pojoContainPojoParam(User user){
System.out.println("pojo嵌套pojo参数传递 user ==> "+user);
return "{'module':'pojo contain pojo param'}";
}
//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
@RequestMapping("/arrayParam")
public String arrayParam(String[] likes){
System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));
return "{'module':'array param'}";
}
//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/listParam")
public String listParam(@RequestParam List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'module':'list param'}";
}
//集合参数:json格式【映入jackson依赖】
//1.开启json数据格式的自动转换,在MVC配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
@RequestMapping("/listParamForJson")
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("list common(json)参数传递 list ==> "+likes);
return "{'module':'list common for json param'}";
}
//POJO参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数据映射到形参的实体类对象中,要求属性名称一一对应
@RequestMapping("/pojoParamForJson")
public String pojoParamForJson(@RequestBody User user){
System.out.println("pojo(json)参数传递 user ==> "+user);
return "{'module':'pojo for json param'}";
}
//集合参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的保存实体类对象的集合对象中,要求属性名称一一对应
@RequestMapping("/listPojoParamForJson")
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("list pojo(json)参数传递 list ==> "+list);
return "{'module':'list pojo for json param'}";
}
//日期参数
//使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd
@RequestMapping("/dataParam")
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'}";
}
}

REST

请求格式都是/user,因为请求方式的不同而含义不同
@RestController //restbaoy+controller
@RequestMapping("/books")
public class BookController {
@PostMapping //增加
public String save(@RequestBody Book book){
System.out.println("book save ==> "+ book);
return "{'module':'book save success'}";
}
@GetMapping //查询
public List<Book> getAll(){
System.out.println("book getAll is running ...");
List<Book> bookList = new ArrayList<Book>();
Book book1 = new Book();
book1.setType("计算机");
book1.setName("SpringMVC入门教程");
book1.setDescription("小试牛刀");
bookList.add(book1);
Book book2 = new Book();
book2.setType("计算机");
book2.setName("SpringMVC实战教程");
book2.setDescription("一代宗师");
bookList.add(book2);
Book book3 = new Book();
book3.setType("计算机丛书");
book3.setName("SpringMVC实战教程进阶");
book3.setDescription("一代宗师呕心创作");
bookList.add(book3);
return bookList;
}
}
@RestController
@RequestMapping("/books")
public class BookController2 {
@PostMapping
public String save(@RequestBody Book book) {
System.out.println("book save..." + book);
return "{'module':'book save'}";
}
@DeleteMapping("/{id}") //删除,传入ID即可
public String delete(@PathVariable Integer id) {
System.out.println("book delete..." + id);
return "{'module':'book delete'}";
}
@PutMapping
public String update(@RequestBody Book book) {
System.out.println("book update..." + book);
return "{'module':'book update'}";
}
@GetMapping("/{id}")
public String getById(@PathVariable Integer id) {
System.out.println("book getById..." + id);
return "{'module':'book getById'}";
}
@GetMapping
public String getAll() {
System.out.println("book getAll...");
return "{'module':'book getAll'}";
}
}
统一格式返回
可以在Controller下【实际哪都行】创建
- Result类
- code类

每次返回都需要创建对象 new Result(code,msg,data)
code可以定义为新的类的静态常量或者枚举。
统一异常处理

使用Spring提供的异常处理器【基于AOP,不需要每个类的写相同的代码】
-
自定义注解
-
异常返回也要是和之前的一样统一格式
- 定义异常的code
//@RestControllerAdvice用于标识当前类为REST风格对应的异常处理器[不用REST方格可使用@ControllerAdvice] @RestControllerAdvice public class ProjectExceptionAdvice { //@ExceptionHandler用于设置当前处理器类对应的异常类型 @ExceptionHandler(SystemException.class) public Result doSystemException(SystemException ex){ //记录日志 //发送消息给运维 //发送邮件给开发人员,ex对象发送给开发人员 return new Result(ex.getCode(),null,ex.getMessage()); } @ExceptionHandler(BusinessException.class) public Result doBusinessException(BusinessException ex){ return new Result(ex.getCode(),null,ex.getMessage()); } //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常 @ExceptionHandler(Exception.class) public Result doOtherException(Exception ex){ //记录日志 //发送消息给运维 //发送邮件给开发人员,ex对象发送给开发人员 return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后再试!"); } }
public class SystemException extends RuntimeException{
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public SystemException(Integer code, String message) {
super(message);
this.code = code;
}
public SystemException(Integer code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
}
拦截器
拦截器是SpringMVC中的概念【基于AOP】

