目录
- 前后端数据交互
- @RequestMapping注解
- 基于@RequestMapping注解设置接口的请求方式
- @RequestMapping注解的常用属性
- 一个方法配置多个接口
- method属性
- params属性
- headers属性
- consumes属性
- produces属性
- SpringMVC中的参数传递
- 默认单个简单参数
- 默认多个简单参数
- 默认参数中有基本数据类型
- @RequestParam注解设置参数
- @RequestParam注解设置参数非必传
- @RequestParam注解设置参数名称
- @RequestParam注解设置参数默认值
- 传对象/Map
- 传数组
- 传List集合
- 传JSON
- SpringMVC响应数据
- Spring MVC提供了多种方式输出模型数据
- 思考:如果是Ajax请求,期望服务端响应的不是页面而是数据,应该怎么处理?
- @ResponseBody生效范围
- RestController
- SpringMVC参数传递时的Rest风格
- REST(Representational State Transfer),表现形式状态转换
- 优点:
- 分类
- 代码示例
- 对应的访问方式
- 查询:
- 删除:
- 新增
- 修改
前后端数据交互
- Spring MVC框架是控制层框架,主要负责处理前后端之间的数据交互工作,包括从请求中获取入参数据,并向前端返回处理结果。
- Spring MVC框架是如何处理数据交互问题的?
@RequestMapping注解
- @RequestMapping注解负责把不同的请求映射到对应的控制器方法上。
- @RequestMapping注解不仅可以作用于控制器的方法上,还可以标注到控制器类上。
- @RequestMapping注解添加到Controller类上时,表示当前控制器下所有接口的访问路径有相同的前缀
基于@RequestMapping注解设置接口的请求方式
-
在Web项目开发中,通常会使用GET类型请求访问查询接口,使用POST类型请求访问保存方法,@RequestMapping注解可以为接口设置访问类型
@Controller public class HelloController {@RequestMapping(value = "/hello",method = {RequestMethod.GET,RequestMethod.POST})public String hello(){return "index";} }
-
除了使用method属性设置接口访问类型外,SpringMVC框架还提供了@GetMapping、@PostMapping等注解实现类似功能。如下接口如果使用POST以外的请求类型进行访问,就会报错
@Controllerpublic class HelloController {@PostMapping("/hello")public String hello(){return "index";}}
浏览器url访问默认是get请求的
@RequestMapping注解的常用属性
属性名 | 描述 |
---|---|
value | 指定请求的实际访问地址,默认@RequestMapping(“url”)的值url即为value的值。指定的地址可以是 URI Template 模式。 |
method | 指定请求的method类型,主要有 GET、POST、DELETE、PUT等; |
params | 指定request中必须包含某些参数值,包含才让该方法处理请求。 |
headers | 指定request中必须包含某些指定的header值,包含才能让该方法处理请求。 |
consumes | 指定处理请求的提交内容类型(Content-Type),例如:application/json, text/html; |
produces | 指定返回的内容类型,当且仅当request请求头中的(Accept)类型中包含该指定类型才返回; |
一个方法配置多个接口
访问/,/hello,/hi都是访问这个hello方法
@Controller
public class HelloController {@RequestMapping(value = {"/","/hello","/hi"})//@RequestMapping(path = {"/","/hello","/hi"})// path也可以public String hello(){return "index";}
}
method属性
- 如果没有指定method属性,则表示任何形式的请求都可以访问该接口
- 如果设置了method的值,就只能支持设置值的请求方式,其它请求方式不支持,就会报405错误 – Method Not Allowed
- 可以指定一种或者多种(数组形式)请求方式
//@RequestMapping(value = "/hello",method = {RequestMethod.POST,RequestMethod.GET})@RequestMapping(value = "/hello",method = RequestMethod.POST)public String hello(){return "index";}
params属性
指定request中必须包含某些参数值,包含才让该方法处理请求。
//请求中的参数who值为world才执行该方法//@RequestMapping(value = "/hello",params = {"who=world"})//请求中的参数who值不为world才执行该方法@RequestMapping(value = "/hello",params = {"who!=world"})public String hello(String who){System.out.println("hello" + who);return "index";}
headers属性
指定request请求作用域中必须包含某些指定的header值,包含才能让该方法处理请求。
@RequestMapping(value = "/hello",headers={"context-type=text/plain","context-type=text/html"})public String hello(){return "index";}
上述访问,如果请求头中不包含context-type=text/plain,context-type=text/html这两个属性,那么就不能访问到该方法,报404错误。
consumes属性
@RequestMapping(value = "/hello", method = RequestMethod.POST, consumes="application/json")public String hello(){return "index";}
方法仅处理request Content-Type为“application/json”类型的请求。
produces属性
@RequestMapping(value = "/hello", method = RequestMethod.GET, produces="application/json")@ResponseBodypublic String hello(){return "index";}
方法仅处理request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json;
SpringMVC中的参数传递
- 在前面的课程中,使用Servlet接收前端请求时,通常会用到HttpServletRequest对象接收参数,代码如下:
String realName=request.getParameter(“realName”); Integer id=request.getParameter(“id”);
- 每一个参数都需要编写代码进行接收,且需要手动转换参数的类型,判断参数值是否为空,给开发人员带来了很大的工作量。怎么解决?
- Spring MVC框架提供了@RequestParam注解,可以自动完成以上绝大部分工作。
默认单个简单参数
@RequestMapping(value = "/hello")public String hello(String who){System.out.println("hello" + who);return "index";}
此时who这个参数可传可不传,但如果传参参数名必须是who
默认多个简单参数
@RequestMapping(value = "/hello")public String hello(String who,String count){System.out.println("hello" + who + ","+ count);return "index";}
此时who、count都可传可不传,但如果传参参数名必须是who和count,顺序无所谓
默认参数中有基本数据类型
@RequestMapping(value = "/hello")public String hello(int count){System.out.println("hello,"+ count);return "index";}
- 按理说,count可传可不传,但是不传参数,则形参默认值为null,而这个count是几本数据类型,无法将null转换,因此就会报错。
- 因此,接口中不要用基本数据类型作为参数,尽量使用包装类
@RequestParam注解设置参数
@RequestMapping(value = "/hello")public String hello(@RequestParam String who){System.out.println("hello" + who);return "index";}
- 此时,访问这个接口时,就必须传参了,并且参数名只能是who
@RequestParam注解设置参数非必传
required属性,默认值true表示必传,false表示非必传
@RequestMapping(value = "/hello")public String hello(@RequestParam(required = false) String who){System.out.println("hello" + who);return "index";}
@RequestParam注解设置参数名称
name属性
@RequestMapping(value = "/hello")public String hello(@RequestParam(name = "paramName",required = false) String who){System.out.println("hello" + who);return "index";}
- 此时,访问这个接口时,就必须传参了,并且参数名只能是paramName
@RequestParam注解设置参数默认值
defaultvalue属性
@RequestMapping(value = "/hello")public String hello(@RequestParam(defaultValue = "springmvc") String who){System.out.println("hello" + who);return "index";}
- 此时,访问这个接口时,如果不传who,那么who就会用springmvc作为默认值
传对象/Map
通常传对象都是用Post请求或者Put请求
@PostMapping(value = "/hello")public String hello(User user){System.out.println("hello:" + user);return "index";}
- 此时传参时只需要让参数名与对象的属性名相同,就可以将参数映射到对象中
- 如果是form表单,只需要让表单各组件的name值与对象属性名相同即可
传数组
@GetMapping(value = "/hello")public String hello(String[] hobbys){for (String hobby : hobbys) {System.out.println(hobby);}return "index";}
- 此时传参时,直需要将多个参数值用逗号分割即可
传List集合
需要加上@RequestParam才行,否则报错
@GetMapping(value = "/hello")public String hello(@RequestParam List<String> hobbys){for (String hobby : hobbys) {System.out.println(hobby);}return "index";}
传JSON
示例
@GetMapping(value = "/hello")public String hello(@RequestBody List<User> userList){userList.forEach(System.out::println);return "index";}
配置转换适配器,否则会报错HttpMediaTypeNotSupportedException: Content type 'application/json' not supp
<!--处理器适配器 --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean></list></property></bean>
测试
SpringMVC响应数据
Spring MVC提供了多种方式输出模型数据
- 使用ModelAndView对象
@GetMapping(value = "/hello")public ModelAndView hello(){ModelAndView mv = new ModelAndView();mv.setViewName("index");//设置返回的逻辑视图名mv.addObject("msg","hello world");//设置后端向前端传递的数据return mv;}
- 使用Model对象(推荐)
在Model中增加模型数据,若不指定key,则默认使用对象的类型作为key@GetMapping(value = "/hello")public String hello(Model model){model.addAttribute("msg","Hello,SpringMVC");return "index";}
- 使用Map对象
Model其实就是一个Map的数据结构,可以使用Map作为处理方法入参
返回的Map必须放在参数中作为形参,可以改变内容,但不能指向新的Map@GetMapping(value = "/hello")public String hello(Map<String,Object> returnMap){returnMap.put("msg","Hello,SpringMVC");return "index";}
思考:如果是Ajax请求,期望服务端响应的不是页面而是数据,应该怎么处理?
使用@ResponseBody注解
@GetMapping(value = "/hello")@ResponseBodypublic User hello(){User user = new User();user.setUserName("周杰伦");user.setUserCode("zjl");return user;}
配置:添加消息转换器
<mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.StringHttpMessageConverter"><property name="supportedMediaTypes"><list><value>application/json;charset=UTF-8</value></list></property></bean><bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/html;charset=UTF-8</value><value>application/json</value></list></property><property name="features"><list><!-- Date的日期转换器 --><value>WriteDateUseDateFormat</value></list></property></bean></mvc:message-converters></mvc:annotation-driven>
@ResponseBody生效范围
- 加在方法上,只对该方法生效
- 加在Controller类上,则该Controller中的所有方法都不再返回页面,而是返回数据
@Controller @ResponseBody public class HelloController {... }
RestController
作用不再解释了,直接看源码,一目了然
SpringMVC参数传递时的Rest风格
REST(Representational State Transfer),表现形式状态转换
- 传统风格资源描述形式
- http://localhost/user/getById?id=1
- http://localhost/user/saveUser
- REST风格描述形式
- http://localhost/user/1
- http://localhost/user
优点:
- 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
- 书写简化
分类
method | 操作类型 |
---|---|
GET | 查询 |
POST | 新增 |
PUT | 修改 |
DELETE | 删除 |
代码示例
package cn.smbms.controller;import cn.smbms.pojo.User;
import org.springframework.web.bind.annotation.*;/*** @author: zjl* @datetime: 2024/4/19* @desc:*/
@RestController
@RequestMapping("/user")
public class UserController {@GetMapping("/{id}")public Integer getById(@PathVariable Integer id) {System.out.println("根据id查询" + id);return id;}@PostMapping("/change")public User insert(@RequestBody User user){System.out.println("新增用户" + user);return user;}@PutMapping("/change")public User update(@RequestBody User user){System.out.println("更新用户" + user);return user;}@DeleteMapping("/{id}")public Integer delete(@PathVariable Integer id){System.out.println("删除用户" + id);return id;}
}
对应的访问方式
查询:
http://localhost:9090/smbms/user/1
删除:
http://localhost:9090/smbms/user/1
新增
http://localhost:9090/smbms/user/change
修改
http://localhost:9090/smbms/user/change