Spring-boot请求与响应
请求实现
简单参数请求
原始方式
// 原始方式
@RequestMapping("/simpleParam")
public String simpleParam(HttpServletRequest request) {
//获取请求参数
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
System.out.println(name + ":" + age);
return name + ":" + age;
}
SpringBoot方式
// spring-boot方式
@RequestMapping("/simpleParam1")
public String simpleParam1(String name, Integer age) {
System.out.println("这是spring-boot请求方式");
System.out.println(name + ":" + age);
return name + ":" + age;
}
在使用SpringBoot方式及进行请求与响应时 步骤如下
- 注解将类表示为请求处理类
- 注解指定当前请求路径
- 改变以往方法括号内参数
request
和response
直接传递参数(注意是引用数据类型)
参数名不一致情况
在使用SpringBoot方式时 尽量使方法的形参名与传递参数名保持一致 否则会出现不会报错也接收不到参数值的情况。
在这个时候可以使用Spring提供的@RequesrParam
注解实现映射
在方法的形参上面加上@RequesrParam
然后通过value属性执行请求参数名,从而完成映射。
@RestController
public class RequestController {
// http://localhost:8080/simpleParam?name=Tom&age=20
// 请求参数名:name
//springboot方式
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam("name") String username , Integer age ){
System.out.println(username+" : "+age);
return "OK";
}
}
注意事项
由于@RequestParam中的required属性默认为true(默认值也是true),代表该请求参数必须传递,如果不传递将报错
所以在参数是可选的时候将 required 属性设置为false
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam(name = "name", required = false) String username, Integer age){
System.out.println(username+ ":" + age);
return "OK";
}
实体参数传递
顾名思义就是将请求参数封装到一个实体类对象中 因为在实际开发中 会遇到很多请求参数 在括号内逐一书写 比较麻烦 此时就用到了实体参数传递
注意事项
请求参数名与实体类名 逐一对应
简单实体参数传递
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//实体参数传递
//在前端有多个请求参数时 为避免书写多个参数 可以将数据封装到一个实体类对象中
//注意实体类中属性名 需要与前端参数名保持一致
@RequestMapping("/simple1")
public User simple1(User user) {
System.out.println(user);
return user;
}
复杂实体参数传递
在实体类中有一个或多个属性也是实体对象类型的
如:User类中有一个Address类型的属性(Address是一个实体类)
复杂实体类对象封装遵循规则
请求参数名与形参对象属性名相同、按照层级对象层次结构关系即可接收
Address实体类
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}
User实体类
public class User {
private String name;
private Integer age;
private Address address; //地址对象
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
}
与前端交互方法
@RestController
public class RequestController {
//实体参数:复杂实体对象
@RequestMapping("/complexPojo")
public String complexPojo(User user){
System.out.println(user);
return "OK";
}
}
数组&集合参数
适用场景-------一次性选择多个值
数组
***请求参数名与形参数组名称相同***且请求参数为多个
定义数组类型形参即可接收参数
@RestController
public class RequestController {
//数组集合参数
@RequestMapping("/arrayParam")
//这里的方法形参名需要与前端参数名保持高度一致
public String arrayParam(String[] hobby){
System.out.println(Arrays.toString(hobby));
return "OK";
}
}
在前端请求时,有两种传递形式:
- 方式一: xxxxxxxxxx?hobby=game&hobby=java
- 方式二:xxxxxxxxxxxxx?hobby=game,java
集合
请求参数名与形参集合对象名相同且请求参数为多个
默认情况下 请求参数名相同的多个值是封装到数组中
如果要封装到集合中就需要@RequestParam
绑定参数关系
@RequestMapping("/arrayParam2")
public String arrayParam2(@RequestParam List<String> hobby) {
System.out.println(hobby);
return "ok";
}
日期参数
@DataTimeFormat
注解的pattern
属性指定了哪种日期格式、前端的日期参数就必须按照指定格式传递
后端:需要使用Date 类型或者LocaDateTime类型来封装传递的参数
@RestController
public class RequestController_4 {
// 日期时间类型请求参数
@RequestMapping("/dateParam")
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime dateTime) {
System.out.println(dateTime);
return "ok";
}
}
JSON参数
传递JSON格式的参数 需要使用实体类进行封装
封装规则:
JSON数据键名与形参对象属性名相同、定义POJO类型形参即可接收参数。需要使用 @RequestBody
标识
@RequestBody
将json数据映射到形参的实体类对象中
JSON中Key的实体类中的属性名保持一致
@RestController
public class RequestController {
//JSON参数
@RequestMapping("/jsonParam")
public String jsonParam(@RequestBody User user){
System.out.println(user);
return "OK";
}
}
路径参数
适用于在请求的URL中传递参数
http://localhost:8080/user/1
http://localhost:880/user/1/0
单个路径参数传递
路径参数:
- 前端:通过请求URL直接传递参数
- 后端:使用{…}来标识该路径参数,需要使用
@PathVariable
获取路径参数
@RestController
public class RequestController {
//路径参数
@RequestMapping("/path/{id}")
public String pathParam(@PathVariable Integer id){
System.out.println(id);
return "OK";
}
}
传递多个路径参数
@RestController
public class RequestController {
//路径参数
@RequestMapping("/path/{id}/{name}")
public String pathParam2(@PathVariable Integer id, @PathVariable String name){
System.out.println(id+ " : " +name);
return "OK";
}
}
响应
实现方式
使用@ResponseBody注解
在实际开发中很少见到@ResponseBody
但是还是可以响应给浏览器
原因:在类上添加的@RestController注解,是一个组合注解。
- @RestController = @Controller + @ResponseBody
当类上添加了@RestController
或者ResponseBody注解时
表示当前类下所有返回方法返回值作为响应数据
方法的返回值如果是一个POJO对象或者集合时、会先转为JSON数据格式、然后响应给浏览器
@RestController
public class ResponseController {
//响应字符串
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World ~");
return "Hello World ~";
}
//响应实体对象
@RequestMapping("/getAddr")
public Address getAddr(){
Address addr = new Address();//创建实体类对象
addr.setProvince("广东");
addr.setCity("深圳");
return addr;
}
//响应集合数据
@RequestMapping("/listAddr")
public List<Address> listAddr(){
List<Address> list = new ArrayList<>();//集合对象
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陕西");
addr2.setCity("西安");
list.add(addr);
list.add(addr2);
return list;
}
}
统一响应数据
在上一个案例可以看出来响应数据各种各样不利于开发
在真实的项目开发中,无论是哪种方法,我们都会定义一个统一的返回结果。
统一的返回结果使用类来描述,在这个结果中包含:
- 响应状态码:当前请求是成功,还是失败
- 状态码信息:给页面的提示信息
- 返回的数据:给前端响应的数据(字符串、对象、集合)
定义在一个实体类Result来包含以上信息。
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应码 描述字符串
private Object data; //返回的数据
public Result() { }
public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
//增删改 成功响应(不需要给前端返回数据)
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应(把查询结果做为返回数据响应给前端)
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
改造交互方法
@RestController
public class ResponseController {
//响应统一格式的结果
@RequestMapping("/hello")
public Result hello(){
System.out.println("Hello World ~");
//return new Result(1,"success","Hello World ~");
return Result.success("Hello World ~");
}
//响应统一格式的结果
@RequestMapping("/getAddr")
public Result getAddr(){
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
return Result.success(addr);
}
//响应统一格式的结果
@RequestMapping("/listAddr")
public Result listAddr(){
List<Address> list = new ArrayList<>();
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陕西");
addr2.setCity("西安");
list.add(addr);
list.add(addr2);
return Result.success(list);
}
}
addr.setCity("深圳");
return Result.success(addr);
}
//响应统一格式的结果
@RequestMapping("/listAddr")
public Result listAddr(){
List<Address> list = new ArrayList<>();
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陕西");
addr2.setCity("西安");
list.add(addr);
list.add(addr2);
return Result.success(list);
}
}