Skip to content
目录概览

StringBoot 的请求与响应

前面的第一个 SpringBoot 项目,我们实现了一个最简单的 hello world 接口;

业务开发中,最常用的HTTP请求方式有四种:GetPOSTPUTDELETE

而 SpringBoot 要想创建这4中类型的接口非常的简单,下面就一起来实现一下这4种不同的请求方式;

在写代码之前,我们需要先了解一下这4种请求方式以及 Spring 中相关的注解

请求方式

Get

Get 请求,字面意思是:获取;这种方式通常用来获取服务端的数据;对应数据库一般就是 selete 操作,支持单纯的查看,一般不会进行做增删改的操作;

特点:

  • Get 请求的参数都是跟着 Url 后面

    如:https://www.yhjava.com?name=ehang&age=18

  • 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注解;

这个注解可以加在类上,也可以加在方法上面;加在方法上,表示这个方法访问时的路径;当注解加在类上面时,这个类里面的所有方法的访问路径前面,都需要加上这个注解里面的这里配置的路径;

注解中的各个参数都是用来细化请求,下面就逐一来演示一下

最基本用法

java
@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参数进行指定

java
/**
 * 处理多种请求方式
 * RequestMethod.GET
 * RequestMethod.POST
 * RequestMethod.PUT
 * RequestMethod.DELETE
 * ... 等等更多其他方式
 *
 * @return
 */
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String add2() {
    // ...
    return "add2";
}

多地址

上面的方式,为add2指定了一个路径,RequestMapping是支持多个路径的,如下示例;其中*代表通配符

java
@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/*" 匹配

参数限制请求

通过请求参数,匹配方法,用来更精准的缩小范围

java
@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 是不固定的,那么就可以按下面的方式来写:

java
@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

正则动态路径

在动态路径基础上,路径还可以通过正则表达式进一步约束:

java
@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 请求的接口

@PostMapping

@PutMapping

@DeleteMapping