概述
最近在开发小程序登录的后端时写了一个登录拦截器,在拦截请求之后设置响应状态和响应信息之后直接返回response,结果前端迟迟收不到响应。
问题
我们先来看一下代码
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 过滤管理端接口请求
//...
// 对客户端请求进行验证,AUTHORIZATION为“authorization”字符串
String jwtToken = request.getHeader(AUTHORIZATION);
if (jwtToken == null || jwtToken.isEmpty()) {
// 设置响应格式(根据前端需求调整,通常为JSON)
response.setContentType("application/json;charset=UTF-8");
response.setStatus(Integer.parseInt(ResponseCode.LOGIN_FAIL.getCode()));
// 获取输出流并写入响应
PrintWriter writer = response.getWriter();
writer.println("{\"message\":\"请先登录\"}"); // 建议返回JSON格式
writer.flush(); // 强制刷新缓冲区
writer.close(); // 关闭输出流,确保响应发送
return false;
}
JWTDTO jwtdto = null;
try {
jwtdto = jwtUtils.parseJWT(jwtToken);
BaseContext.setCurrentUserId(jwtdto.getUserId());
// todo 滑动刷新 jwt
} catch (Exception e) {
e.printStackTrace();
// 设置响应格式(根据前端需求调整,通常为JSON)
response.setContentType("application/json;charset=UTF-8");
response.setStatus(Integer.parseInt(ResponseCode.LOGIN_FAIL.getCode()));
// 获取输出流并写入响应
PrintWriter writer = response.getWriter();
writer.println("{\"message\":\"请先登录\"}"); // 建议返回JSON格式
writer.flush(); // 强制刷新缓冲区
writer.close(); // 关闭输出流,确保响应发送
return false;
}
return true;
}
一开始是这样写的,大家可以看看是否有哪里不对劲。
没错,后端接口请求响应状态码定义多了,这边我自然的就用了自定义的状态码
ResponseCode.LOGIN_FAIL.getCode()中的值为"0001",就这样前端发送完请求就迟迟不能收到后端的响应,让我疑惑了好一会。
解决
后来我把response.setStatus(Integer.parseInt(ResponseCode.LOGIN_FAIL.getCode()));
修改成了response.setStatus(401);就解决了问题
原因
为啥嘞
因为在拦截器中设置响应状态码时,必须遵循 HTTP 协议规范,否则会导致客户端(浏览器 / 前端)无法正确处理响应,甚至出现 “迟迟收不到响应” 的问题。
HTTP 协议对状态码有明确的规定:
- 状态码是 3 位数字(范围
100-599
),且每类数字有固定含义(如2xx
表示成功、4xx
表示客户端错误、5xx
表示服务器错误); - 每个状态码的语义由 IETF 规范(如 RFC 7231)定义,例如
200
表示成功、401
表示未授权、403
表示禁止访问等; - 不允许自定义超出规范的状态码(比如
600
、1000
或非数字码),这类 “自定义码” 本身不符合 HTTP 协议格式,属于无效状态码。
前端(浏览器或前端框架)接收响应时,会先校验状态码是否符合 HTTP 规范:
- 对于合法的标准状态码(如
401
、403
),客户端会正常解析响应体; - 对于无效状态码(如
600
、1234
),客户端会认为这是 “畸形响应”,可能直接忽略该响应,或进入 “等待有效响应” 的超时状态(表现为 “迟迟收不到响应”); - 部分浏览器会将无效状态码的响应视为 “网络错误”,触发
error
事件但不返回具体内容,前端无法获取响应体。