简介
主要记录了使用 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 | 方法和消息主体都不发生变化。 |