简介
主要记录了使用 spring 重定向时遇到的问题,以及重新熟悉 HTTP 3xx 中重定向状态码的意义。
前言
最近接手的一个项目需要在 POST 接口中处理逻辑,完成后让浏览器重定向到首页,请求方式需要变成 GET 。
结果一直提示 405 方法不支持。折腾了个把都没找到问题原因,没想到是重定向的状态码有问题。
问题
一般情况下,在 Spring下重定向到页面时会使用 ModelAndView,也就是这样:
    @PostMapping("handle")
    public String handle(){
        // do something ...
        return "redirect:/";
    }
这种类似的情况下返回的是:
POST http://localhost:8080/tdh-portal/cas
HTTP/1.1 302 Found
Content-Language: zh-CN
Location: http://localhost:8080/
Content-Length: 0
Server: Jetty(9.4.z-SNAPSHOT)
<Response body is empty>
Response code: 302 (Found); Time: 119ms; Content length: 0 bytes
也不知道从哪里复制了一段代码 😂 ,主要部分如下:
    @PostMapping("handle")
    public ResponseEntity<?> handle(){
        // do something ...
        return ResponseEntity
            .status(HttpStatus.TEMPORARY_REDIRECT)
            .header(HttpHeaders.LOCATION, "/")
            .build();
    }
响应信息则是这样
POST http://localhost:8080/handle
HTTP/1.1 307 Temporary Redirect
Set-Cookie: JSESSIONID=node0123krmz4upibb18jz7ov4us1pw1.node0;Path=/
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Location: /
Content-Length: 0
Server: Jetty(9.4.z-SNAPSHOT)
<Response body is empty>
Response code: 307 (Temporary Redirect); Time: 4916ms; Content length: 0 bytes
可以看到两种方式主要响应码不同 302 与 307。经过查阅相关文档发现意义大不相同:
| 编码 | 含义 | 处理方法 | 
|---|---|---|
| 302 | Found | GET 方法不会发生变更,其他方法有可能会变更为 GET 方法。1 | 
| 307 | Temporary Redirect | 方法和消息主体都不发生变化。 | 
典型应用场景:
302:由于不可预见的原因该页面暂不可用。在这种情况下,搜索引擎不会更新它们的链接。
307:由于不可预见的原因该页面暂不可用。在这种情况下,搜索引擎不会更新它们的链接。当站点支持非 GET 方法的链接或操作的时候,该状态码优于 302 状态码。
302 与 307 最主要的不同点在于方法和消息体是否发生变化。所以导致用POST方法请求接口时无法重定向到使用GET方法的页面。
经过查看重定向相关的响应码规范,修改代码:
    @PostMapping("handle")
    public ResponseEntity<?> handle(){
        // do something ...
        return ResponseEntity
            .status(HttpStatus.SEE_OTHER)
            .header(HttpHeaders.LOCATION, "/")
            .build();
    }
这里使用 303 主要是为了验证成功跳转防止重复触发。
HTTP 的重定向
不同类型的重定向映射可以划分为三个类别:
- 永久重定向
 - 临时重定向
 - 特殊重定向
 
永久重定向意味着原来的URL不应再被使用,而应优选用新的URL,这种关系是永久性的,通常应用于网站重构,301,308。
临时重定向顾名思义这种关系是临时性的,有时候请求的资源无法从其标准地址访问,但是却可以从另外的地方访问,302,303,307。
特殊重定向是指 300 和 304,不同于其他方式直接给定url跳转重定向,没有特定的处理方式,也可能返回多个能重定向的url供手动选择。
常见重定向响应码:
| 编码 | 含义 | 说明 | 
|---|---|---|
| 300 | Multiple Choice | 不常用:所有的选项在消息主体的 HTML 页面中列出。 | 
| 301 | Moved Permanently | GET 方法不会发生变更,其他方法有可能会变更为 GET 方法。2 | 
| 302 | Found | GET 方法不会发生变更,其他方法有可能会变更为 GET 方法。3 | 
| 303 | See Other | GET 方法不会发生变更,其他方法会变更为 GET 方法(消息主体会丢失)。 | 
| 304 | Not Modified | 发送用于重新验证的条件请求。表示缓存的响应仍然是新鲜的并且可以使用。 | 
| 307 | Temporary Redirect | 方法和消息主体都不发生变化。 | 
| 308 | Permanent Redirect | 方法和消息主体都不发生变化。 |