在 Spring Boot 项目开发中,我们常常会在 拦截器 中进行登录校验,并在未登录时直接返回 JSON 提示信息。但很多同学会遇到一个问题:中文提示信息出现乱码 (如 ???
或乱码字符)。
一、问题原因
根源在于:
HTTP 响应的字符编码(Charset)未正确设置,导致前端解析中文失败。
- 拦截器中直接使用
response.getWriter().write(...)
输出字符串; - Tomcat 默认使用
ISO-8859-1
编码,不支持中文; - 前端一般默认用
UTF-8
解析,编码不一致 → 乱码。
二、临时方案:手动设置响应编码
这是最快速见效的办法。在 response.getWriter().write(...)
之前,明确设置字符编码和 Content-Type:
java
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":401,\"msg\":\"请先登录!\"}");
修改拦截器示例:
java
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader(jwtProperties.getTokenName());
if (StringUtils.isBlank(token)) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":401,\"msg\":\"请先登录!\"}");
return false;
}
return true;
}
👉 这样可以立刻解决乱码问题,但存在硬编码 JSON、不可复用的问题。
三、优雅方案:使用统一的 Result
类
如果项目里已经有统一的返回对象(如 Result
),建议复用,避免硬编码 JSON。
1. 注入 ObjectMapper
Spring Boot 默认集成了 Jackson,可直接注入:
java
@Autowired
private ObjectMapper objectMapper;
2. 生成统一响应
用 Result
封装后,再转成 JSON 输出:
java
Result<?> result = Result.fail(401, "请先登录!");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(result));
这样既能保证编码正确,又能保持返回格式一致。
四、根治方案:全局配置响应编码
如果你不想每次都手动设置编码,可以通过全局配置彻底解决。
方式 1:在 application.yml
配置
yaml
spring:
http:
encoding:
force: true
charset: UTF-8
enabled: true
方式 2:全局配置消息转换器
在 WebMvcConfig
中统一设置编码:
java
@Bean
public StringHttpMessageConverter stringHttpMessageConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
return converter;
}
这样项目中所有返回字符串的响应都会默认使用 UTF-8。
五、验证效果
- 启动项目后,访问需要登录的接口(不带 Token);
- 查看返回结果:
json
{"code":401,"msg":"请先登录!"}
若能正常显示中文而不是乱码,说明问题已解决 ✅。