Spring MVC基础
- Spring MVC 是非常著名的 Web 应用框架,现在的大多数 Web 项目都采用 Spring MVC。它与 Spring 有着紧密的关系。是 Spring 框架中的模块,专注 Web 应用,能够使用 Spring 提供的强大功能,IOC、AOP等。
- Spring MVC 框架底层是基于 Servlct 技术。遵循 Servlet 规范,Web 组件 Servlet 、Filter、Listener在 Spring MVC 中都能使用。同时 Spring MVC 也是基于 MVC 架构模式的,职责分离,每个组件只负责自己的功能,组件解耦。
- Spring Boot 的自动配置、按约定编程极大简化,提高了 Web 应用的开发效率。
一、控制器 controller
- 控制器是一种由 Spring 管理的 Bean 对象,赋予角色是“控制器”。作用是处理请求,接收浏览器发送过来的参数,将数据或视图应答给浏览器或者客户端 App等。
- 创建一个控制器对象:创建普通 Java 类,其中定义 public 方法。类上注解 @Controller或者@RestController。
-
@Controller和@RestController注解的区别:
- @RestController包含了@Controller的功能,同时加入了@ResponseBody的注解。
- 表示当前控制器类中的方法,都会默认加入@ResponseBody的功能。方法的返回值是数据可以通过 HttpServletResponse 输出给浏览器。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { @AliasFor( annotation = Controller.class ) String value() default ""; }
-
@Controller注解有@Component的功能,控制器类对象是Spring容器管理的。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { @AliasFor( annotation = Component.class ) String value() default ""; }
-
1.定制控制器的方法
- Controller 类中的方法处理对应 URI 的请求,一个(或多个)URI 请求交给一个方法处理。就是一个普通的方法,方法有参数,返回值。方法上面加入@RequestMapping,说明这个 URI 由这个方法处理。
(1)接收请求
- @RequestMapping:用于将 Web 请求映射到控制器类的方法。此方法处理请求。可用作在类上或方法上。在类上和方法上同时使用。重要的属性如下:
- Value:别名 path 表示请求的 URI,在类和方法上同时使用 value,方法上的继承类上的 value。
- method:请求方式,支持 GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE。
- 值为:RequestMethod[] method(),RquestMethod 是 enum 类型。
- 快捷注解:
- @GetMapping: 表示 get 请求方式的@RequestMapping
- @PostMapping:表示 post 请求方式的@RequestMapping
- @PutMapping:表示 put 请求方式的@RequestMapping
- @DeleteMapping: 表示 delete 请求方式的@RequestMapping
- Spring MVC 支持多种策略,匹配请求路径到控制器方法。AntPathMatcher、PathPatternParser。Spring Boot3默认使用的是 PathPatterParser 策略。
- 可以通过 spring.mvc.pathmatch.matching-strategy 配置项来设置匹配的策略。
- PathPatternParser 中有关URI的定义:
- 通配符:
- ?:一个字符
- *:0个或多个字符。在一段路径中匹配字符。(不能匹配 /)
- **:匹配0个或多个路径段。(相当于所有)
- 正则表达式:支持正则表达式
- RESTFul 的支持路径变量
- {变量名}:只能在一段路径中匹配字符。(不能匹配 /)
- {myname:[a-z]+}:正则匹配 a-z 的多个字符,路径变量名称”myname“。结合@PathVariable(“myname”)使用。
- {*myname}:匹配多个路径一直到 URI 结尾。
- 注意:@GetMapping(“/user/{*id}/{*data}”)是无效的,{*XXX}后面不能再有匹配规则了。
- 当不使用通配符的时候,那么就是一个URI对应一个请求,实际项目中一般都是这样的。
- 通配符:
(2)接收请求参数
- 用户在浏览器中点击按钮,会发送一个请求给服务器,其中包含让服务器程序需要做什么的参数。这些参数发送给控制器方法。控制器方法的形参列表接收请求参数。
- 解析参数需要的值,
SpringMVC
中专门有一个接口来干这个事,这个接口就是:(处理器方法参数解析器)
HandlerMethodArgumentResolver,就是解析请求得到Controller
方法的参数的值。 - 参考===>[1]. 控制器方法参数类型看官方文档
①请求参数与形参一一对应,适用于简单类型。比如 String、int、double等。适用于参数个数比较少的情况。
- 前端传递过来的参数都是
字符串类型
的。类型的转化是由SpringMVC
框架来完成的,如果类型转化失败会报错的。
②对象类型,控制器方法参数是对象,请求的多个参数名与属性名相对应。
③@RequestParam注解
- 把请求中的指定名称的参数传递给控制器中的形参赋值。(将查询参数,form 表单数据解析到方法参数,解析 multipart 文件上传)。
// @RequestParam 注解源码 @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestParam { @AliasFor("name") String value() default ""; //请求参数中的名称 @AliasFor("value") String name() default ""; boolean required() default true; //请求参数中是否必须提供此参数 String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n"; }
@RequestParam()
注解的value
属性值没有对应的参数值则会直接报400
错误,因为required
属性默认为true
,如果加上required=false
,没对应上则不会报错,而是获取值为null
。- 如果参数前不写
@RequestParam(xxx)
的话,那么就前端可以有可以没有对应的xxx名字都行,如果有xxx名的话,那么就会自动匹配;没有的话,请求也能正确发送。
④HttpServletRequest
- 使用
request
对象接收参数,request.getParameter("XXX")
获取对应的值,原始的JavaWeb
中的方式。
⑤RequestBody接收请求体中的数据
@RequestBody
主要用来接收前端传递给后端的json
字符串中的数据的(请求体中的数据的
),有一个属性required
,表示参数是否必须要传,默认为true
。GET
方式无请求体
,所以使用@RequestBody
接收数据时,前端不能使用GET
方式提交数据,而是用POST
方式进行提交。- 在后端的同一个接收方法里,
@RequestBody
与@RequestParam()
可以同时使用,@RequestBody
最多只能有一个,而@RequestParam()
可以有多个。 - 当同时使用
@RequestParam()
和@RequestBody
时,@RequestParam()
指定的参数可以是普通元素、数组、集合、对象
等等(当,@RequestBody
与@RequestParam()
同时使用时,原SpringMVC
接收参数的机制不变,只不过@RequestBody
接收的是请求体里面的数据;而@RequestParam()
接收的是key-value
里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象
等接收)。 - 参考 ===> [2]. java接收注解@RequestBody的使用
- @RequestBody直接以String接收前端传过来的json数据:
- @RequestBody以List<简单对象>接收前端传过来的json数据:
- 如果后端参数是一个对象,且该参数前是以
@RequestBody
修饰的,那么前端传递json
参数时,必须满足以下要求:后端@RequestBody
注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody
后面的类)时,会根据json
字符串中的key
来匹配对应实体类的属性,如果匹配一致且json
中的该key对应的值符合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的setter
方法将值赋给该属性。
- 如果后端参数是一个对象,且该参数前是以
⑥@RequestHeader,从请求 header 中获取某些值
⑦数组参数接收多个值。
(3)返回值
- ① 不使用 @ResponseBody的 String 返回值,返回的是一个页面视图。
- ② 使用 @ResponseBody的 String 返回值,返回的是一个字符串。
- ③ ModelAndView 返回值,返回的是一个视图其中包含数据。(最后数据都是放到 Request 中的)
- ④ 返回自定义的对像,默认的返回格式是json字符串(有jackson工具)
- ⑤ 返回 Map,默认的返回格式是json字符串(有jackson工具)
- ⑥ ResponseEntity:包含数据和自定义的HttpStatus Code。(默认转为json格式的字符串)
二、模型 Modle
- 在许多实际项目需求中,后台要从控制层直接返回前端所需要的数据,这时 Model 大家族就派上用场了。
- Model Spring MVC 中的 ”M“,是用来传输数据的。从控制层直接返回数据给前端。内置的 JSP,模板技术能够展现 Model 中存储的数据。
- Model 可以是承载数据的,也可以是处理具体业务的类,这些都是指 Spring MVC 中的Model。
三、视图 View
- Spring MVC 中的 View(视图)用于展示数据的,视图技术的使用是可插拔的。无论选择使用 thymleaf、jsp 还是其他技术,classpath 有 jar 就能使用视图了。开发者主要就是更改配置。SpringBoot3 不推荐使用 FreeMarker、JSP 这些了。建议使用 Thymeleaf。
- org.springframework.web.servlet.View 视图的接口,实现此类的都是视图类,视图类作为 Bean 被 Spring 管理。当然这些都不需要开发者编写代码。
- Spring MVC 的 View(视图)与控制器方法的返回值有关。
- @ResponseBody,@RestController 适合前后端分离项目
- String:表示返回一个字符串。
- Object//map:如果有 Jackson 库,将其转为 Json 字符串。
- spring.thymeleaf.prefix = classpath:/templates/ =====> thymeleaf 页面视图默认存放的位置。
- spring.thtmeleaf.suffix = .html ===⇒ thymeleaf 页面视图默认的后缀名。
四、总结
- SpringMVC 处理请求都是围绕着控制器的方法的。
- public 方法。
- 方法名称自定义。
- 方法的形参表示接收的请求参数。
- 逐一按名称对应接收参数。String name, Integer age。
- 使用自定义对象,接收多个参数。User(name ,age, sex)。
- 接收json,使用@RequestBody注解,加上自定义对象。(也可以接收请求体中的json数据)
- 使用Reader、InputStream作为参数,读取Post请求体中的内容。
- 使用HttpServletRequest作为参数,调用getParameter()方法接收参数。
- 数组参数Integer[] id。
- @RequestParam
- @RequestHeader
- 控制器方法的返回值,表示给请求方的相应。响应内容。
- String,表示视图页面(xxxx.html …),没有使用@ResonseBody。
- ModelAndView:是数据和视图的结合体,包含了数据和视图。
- 自定义对象:默认将自定义对象转为json格式,输出给浏览器。
- ResponseEntity:包含数据和自定义的HttpStatus Code。
- Map:默认将key和Value转为json字符串。
五、参考
[1]. 控制器方法参数类型看官方文档
[2]. java接收注解@RequestBody的使用
[3]. SpringMVC @RequestBody 属性名大写字母注入失败解决方案