[框架]Spring MVC框架
目录
@RequestParam注解是添加在方法的参数上的,它的作用主要有:
关于Spring MVC框架
MVC:Model + View + Controller
Spring MVC框架主要解决了接收请求、响应结果及相关问题(例如处理异常等),即主要关注C的问题,在不是前后端分离的项目,还关心V的问题,但是,并不关心M的问题。
Model:模型,数据处理的流程和规则。具体表现为service和mapper的整合。
Spring MVC框架的依赖项
Spring MVC框架的基础依赖项是:spring-webmvc
在Spring Boot中,使用Spring MVC框架应该添加依赖项:spring-boot-starter-web
使用Spring MVC框架接收请求
应该创建控制器类,并在控制器类上添加@Controller
注解,在Spring MVC框架中,只有添加此注解的类才是控制器类!
默认情况下,在Spring MVC框架中,控制器处理请求的结果(方法的返回值)将被视为“视图组件的名称”,当在处理请求的方法上添加@ResponseBody
注解后,返回的结果才会被视为“响应到客户端的数据”,@ResponseBody
注解还可以添加在控制器类上,表示此类中所有处理请求的方法的返回结果都是“响应到客户端的数据”,这种做法称之为“响应正文”,或者,也可以将控制器类上的注解改为@RestController
,它是@Controller
和@ResponseBody
的组合注解!
包括处理异常的“全局异常处理器类”,需要添加的其实是@ControllerAdvice
注解,添加此注解的类中的特定方法(例如处理异常的方法)将可以作用于每次处理请求的过程中,但是,默认情况下,仍不是“响应正文”的,所以,当处理异常需要响应正文时,需要在处理异常的方法上添加@ResponseBody
注解,或在全局异常处理器的类上添加@ResponseBody
注解,或将@ControllerAdvice
改为@RestControllerAdvice
。
在控制器类上,可以自定义方法用于处理请求,关于这些方法:
-
访问权限:应该是
public
-
返回值类型:当响应正文时,可自行将需要响应的数据属性封装在自定义类中,使用自定义类作为返回值类型
-
当使用自定义类型进行响应正文时,需要:
-
需要添加
jackson-databind
依赖项,在spring-boot-starter-web
中已经包含 -
需要启用Spring MVC的注解增强,如果使用XML配置(早些年用的多),需要添加
<annotation-driven/>
,如果使用配置类进行配置,需要在配置类上添加@EnableWebMvc
注解,否则,响应时会出现406
错误,在Spring Boot项目不需要手动配置
-
-
-
方法名称:自定义
-
参数列表:按需添加,且各参数不区分先后顺序,可以将各请求参数逐一作为参数列表中的参数,也可以将多个请求参数封装到自定义类型中,使用自定义类型作为方法参数列表中的参数,还可以按需添加
HttpServletRequest
、HttpServletResponse
、HttpSession
等,在使用其它技术框架后,还可以按需添加其它参数,例如结合@AuthenticationPrincipal
注解添加Spring Security的当事人 -
抛出异常:理论上,处理请求的方法不应该处理异常,而应该抛出,进而交由全局异常处理器进行处理
所有处理请求的方法都必须添加@RequestMapping
系列(还有GetMapping,PostMapping等)的某个注解,通过这些注解来配置请求路径。
关于@RequestMapping
注解
@RequestMapping
注解的主要作用是配置请求路径,通常,在类上应该配置此注解,例如:
@RestController
@RequestMapping("/admin")
public class AdminController {}
在方法上,建议使用限制了请求方式的某个基于@RequestMapping
的注解,例如:
@RestController
@RequestMapping("/admin")
public class AdminController {
@PostMapping("/login")
public JsonResult login() {
// ...
}
@GetMapping("/list")
public JsonResult list() {
// ...
}
}
如果响应可能出现乱码,建议在类上的@RequestMapping
上配置produces
属性,以指定响应的文档类型,例如:
@RestController
@RequestMapping(value = "/admin", produces = "application/json; charset=utf-8")
public class AdminController {}
关于RESTful
RESTful是一种软件设计的风格(并不是规则或规范)。
RESTful的典型特征包括:
- 将某些具有“唯一性”的参数值作为URL的一部分,例如:
http://localhost:9080/album/9527/delete
https://gitee.com/chengheng2022/jsd2302-csmall-server-teacher
-
是前后端分离的,即:是响应正文的
-
根据处理数据的方式来选择请求方式
-
增加新的数据时,应该提交
POST
类型的请求 -
修改数据时,应该提交
PUT
类型的请求 -
删除数据时,应该提交
DELETE
类型的请求 -
获取数据时,应该提交
GET
类型的请求 -
通常不照做(因为业务的复杂性很难去界定具体使用哪一个)
-
Spring MVC框架很好的支持了RESTful风格,当设计URL时,如果URL中包含参数值,可以使用{自定义名称}
进行占位,例如:
// http://localhost:9180/album/9527/delete
@PostMapping("/{id}/delete")
// ↑↑↑↑ 占位符
然后,在处理请求的方法上,在对应的参数上添加@PathVariable
注解,表示此参数值来自URL中同名占位符对应的值,例如:
@PostMapping("/{id}/delete")
public JsonResult delete(@PathVariable Long id) {
// ...
}
如果占位符中的名字与参数的变量名不同,需要在@PathVariable
注解上指定参数,例如:
@PostMapping("/{id}/delete")
public JsonResult delete(@PathVariable("id") Long albumId) {
// ↑↑↑↑↑↑ 指定注解参数,与占位符名称一致,则方法参数的变量名已经不重要了
// ...
}
在配置占位符名称时,可以在自定义名称的右侧添加冒号,然后,在冒号右侧添加正则表达式,以限制URL传入的值的格式,例如:
@PostMapping("/{id:[0-9]+}/delete")
经过以上配置,只有占位符位置是纯数字的请求才可以匹配上,如果占位符位置不是纯数字的请求(例如/abc/delete
)则会响应404
。
注意:多不冲突的正则表式达的占位设计是允许共存的,例如:
@PostMapping("/{id:[0-9]+}/delete")
public JsonResult delete1() {}
@PostMapping("/{xx:[a-z]+}/delete")
public JsonResult delete2() {}
9527/delete的请求就走delete1,abcd/delete的请求就走delete2,彼此不冲突。
另外,如果还有某个配置没有使用占位符的设计,也是允许与以上设计共存的,例如:
@PostMapping("/test/delete")
public JsonResult deleteTest() {}
关于RESTful风格的URL设计,如果你没有更好的选择,可以参考:
-
查询数据列表,格式为:
/数据类型的复数
-
例如:
/albums
-
-
获取某类型的1个数据,格式为:
/数据类型的复数/{数据ID}
-
例如:
/albums/{id:[0-9]+}
-
-
对某类型的1个数据执行某个数据管理操作,格式为:
/数据类型的复数/{数据ID}/命令
-
例如:
/albums/{id:[0-9]+}/delete
-
关于@RequestParam
注解
@RequestParam
注解是添加在方法的参数上的,它的作用主要有:
- 配置请求参数的名称(用于请求参数的名称与方法参数不同时),例如:
// http://localhost:8080/login?username=root
public JsonResult login(@RequestParam("username") String xxx) {
// ...
}
-
配置必须提交某个请求参数,因为此注解
required
属性默认值为true
-
此功能可以通过Validation框架来实现
-
- 配置某个请求参数的默认值,例如:
// http://localhost:8080/list
public JsonResult list(@RequestParam(defaultValue = "1") Integer page) {
// ...
}
其它
例如全局异常处理器等