StringBoot 的请求与响应
前面的第一个 SpringBoot 项目,我们实现了一个最简单的 hello world 接口;
业务开发中,最常用的HTTP请求方式有四种:Get
、POST
、PUT
、DELETE
而 SpringBoot 要想创建这4中类型的接口非常的简单,下面就一起来实现一下这4种不同的请求方式;
在写代码之前,我们需要先了解一下这4种请求方式以及 Spring 中相关的注解
请求方式
Get
Get 请求,字面意思是:获取;这种方式通常用来获取服务端的数据;对应数据库一般就是 selete 操作,支持单纯的查看,一般不会进行做增删改的操作;
特点:
Get 请求的参数都是跟着 Url 后面
Get 请求参数的长度限制
本身 HTTP 协议对Get请求是没有做长度限制的,但是特定的浏览器、服务器对其有一定的限制
- IE:最大限制为2083个字符
- Firefox:最大限制为65536个字符
- Safari:最大限制为80000个字符
- Opera:最大限制为190000个字符。
- Google(chrome):最大限制为8182个字符。
- Apache(Server):最大限制为8192个字符
- Microsoft Internet Information Server(IIS):最大限制为16384个字符
Get 请求的安全性较低
由于参数是直接跟在地址后面,可以直接看到,数据更容易暴露,如果要数据安全,需要对参数进一步加密来保证;
Post
Post 请求主要用于数据的提交数据;Post 不需要实现幂等,也就是说操作是不安全的,一般用来创建数据,数据的ID由后端返回;比如/user
,提交用户数据,用户保存到数据库之后,将ID返回给发起者;如果多次提交,会返回不同的用户ID;
PUT
Put 请求和Post一样,也是用来提交数据,但是不同于Post的是,Put需要保证幂等;也就意味着多次执行的操作和一次执行的操作是一样的,比如/user/123
,其中123一般指的是用户的ID,根据这个ID去更新数据,相同的请求不管请求多少次,返回的结果都是一样的;
DELETE
DELETE 字面意思就是删除,通常也是用来做删除操作的;
相关注解
@Controller
该注解在类上使用,用于声明该类是 Controller 层的 Bean,由 Spring 容器中进行管理
@ResponseBody
表明该类的所有方法的返回值都直接进行提交而不经过视图解析器,且返回值的数据自动封装为json的数据格式
@RestController
是 @Controller
和 @ResponseBody
二合一注解,一般用于 Restful 风格的 API 接口
@RequestMapping(重要)
后端开发的接口,都是通过结构地址来映射的,比如:http://www.yhjava.com/user/add
,其中/user/add
就是接口地址,那要如何才能将这个路径给映射到一个具体的方法呢?就可以用到@RequestMapping
注解;
这个注解可以加在类上,也可以加在方法上面;加在方法上,表示这个方法访问时的路径;当注解加在类上面时,这个类里面的所有方法的访问路径前面,都需要加上这个注解里面的这里配置的路径;
注解中的各个参数都是用来细化请求,下面就逐一来演示一下
最基本用法
@RestController
@RequestMapping("rm")
@Slf4j
public class AnnoRequestMappingController {
@RequestMapping("/add")
public String add(HttpServletRequest request) {
// ...
log.info("request.getMethod:{}", request.getMethod());
return "add";
}
}
以上代码在类和方法上面指定了路径,没有任何其他限制,那么http://127.0.0.1:8083/rm/add
就是他的请求地址,由于没有限制请求方式,那么这个方法是支持所有的请求方式,GET、POST、PUT、DELETE等所有的请求方式都能进入这个方法;
不同请求方式的输出
request.getMethod:GET
request.getMethod:POST
request.getMethod:PUT
request.getMethod:DELETE
request.getMethod:PATCH
.... 更多其他方式
指定请求方式
上面的测试用例由于没有指定请求方式,所以什么请求方式都是支持的,示例的业务中,一般都要限定某个接口的请求方式;可以用过method
参数进行指定
/**
* 处理多种请求方式
* RequestMethod.GET
* RequestMethod.POST
* RequestMethod.PUT
* RequestMethod.DELETE
* ... 等等更多其他方式
*
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String add2() {
// ...
return "add2";
}
多地址
上面的方式,为add2
指定了一个路径,RequestMapping是支持多个路径的,如下示例;其中*
代表通配符
@RequestMapping(value = {"/add3", "/addabc", "/addx*", "/add/*"}, method = RequestMethod.POST)
public String add3() {
// ...
return "add3";
}
以上方法能匹配上的地址示例:
http://127.0.0.1:8083/rm/add3
// 通过 "/add3" 匹配
http://127.0.0.1:8083/rm/addabc
// 通过 "/addabc" 匹配
http://127.0.0.1:8083/rm/addxa
// 通过 "/addx*" 匹配
http://127.0.0.1:8083/rm/addxbc
// 通过 "/addx*" 匹配
http://127.0.0.1:8083/rm/add/123
// 通过 "/add/*" 匹配
参数限制请求
通过请求参数,匹配方法,用来更精准的缩小范围
@RequestMapping(value = "/get", method = RequestMethod.GET, params = {
"id=1", "name=a"
})
public String get1() {
// ...
// http://127.0.0.1:8083/rm/get?id=1&name=a
return "get 1";
}
@RequestMapping(value = "/get", method = RequestMethod.GET, params = {
"id=2", "name=b"
})
public String get2() {
// ...
// http://127.0.0.1:8083/rm/get?id=2&name=b
return "get 2";
}
@RequestMapping(value = "/get", method = RequestMethod.GET)
public String get3() {
// ...
// 上面未匹配上的 都会走这个
// http://127.0.0.1:8083/rm/get?id=2&name=a
// http://127.0.0.1:8083/rm/get?id=1&name=c
// http://127.0.0.1:8083/rm/get?age=10
return "get 3";
}
get1 方法限定参数只有包含id=1&name=a
时,才能匹配上;
get2 方法限定参数只有包含id=2&name=b
时,才能匹配上,参数多了没有影响,但是不能少;
get3 由于没限制参数,当get1和get2方法没匹配上的请求 都会走get3
方法匹配示例:
http://127.0.0.1:8083/rm/get?id=1&name=a
// 匹配 get1
http://127.0.0.1:8083/rm/get?id=2&name=b&age=10
// 匹配 get2
http://127.0.0.1:8083/rm/get?id=2&name=a
// 匹配 get3
http://127.0.0.1:8083/rm/get?id=1&name=c
// 匹配 get3
http://127.0.0.1:8083/rm/get?age=10
// 匹配 get3
动态参数匹配
当特定场景下,需要动态指定并匹配,比如根据 id 获取用户信息,用户 id 是不固定的,那么就可以按下面的方式来写:
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public String get4(@PathVariable Integer id) {
// ...
// http://127.0.0.1:8083/rm/get/10
return "get4 " + id;
}
其中动态 id 可以使用@PathVariable
来获取
匹配示例:
http://127.0.0.1:8083/rm/get/1
http://127.0.0.1:8083/rm/get/10
http://127.0.0.1:8083/rm/get/9999
正则动态路径
在动态路径基础上,路径还可以通过正则表达式进一步约束:
@RequestMapping(value = "/get/{path:[a-z]+}/{name}", method = RequestMethod.GET)
public String get5(@PathVariable String path, @PathVariable String name) {
// ...
// http://127.0.0.1:8083/rm/get/abc/ehang
// path = abc
// name = ehang
return "get5 " + path + " -> " + name;
}
@RequestMapping(value = "/get/{path:[0-9]+}/{name}", method = RequestMethod.GET)
public String get6(@PathVariable Long path, @PathVariable String name) {
// ...
// http://127.0.0.1:8083/rm/get/123/ehang
// path = 123
// name = ehang
return "get6 " + path + " -> " + name;
}
其中[a-z]+
限定只能是字母,[0-9]+
限定只能是数字
匹配示例
http://127.0.0.1:8083/rm/get/abc/ehang
// 匹配 get5
http://127.0.0.1:8083/rm/get/123/ehang
// 匹配 get6
@RequestParam
用于获取在请求地址中的参数,如https://www.yhjava.com?name=ehang&age=18
,其中的name和age就可以通过这个注解获取:
@GetMapping()
public String get(@RequestParam("name") String userName, @RequestParam Integer age) {
// 在这里就能拿到userName 和 age 的值了
return "get request success!!!";
}
其中@RequestParam("name") String userName
表示将地址中的name值赋给变量userName;如果不指定,就直接拿着变量名去取,如age
@PathVariable
用于在Url地址中取值;具体用法可参考@RequestMapping的动态参数匹配
@RequestBody
用户获取请求 body 中的数据
@GetMapping
定义 Get 请求的接口