spring mvc @ResponseStatus 注解 注释返回中文乱码的问题
前言
前文中讲到,使用@ResponseStatus注解,可以修饰一个异常类,在发生异常的时候返回指定的错误码和消息,在返回的 reason中包含中文的时候,就会出现中文乱码的问题
现象
reason中包含中文的时候,前端返回为乱码
/**
* 自定义异常类
*
* @author Administrator
*
*/
@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "没有权限")
public class TestException extends RuntimeException {
private static final long serialVersionUID = 5759027883028274330L;
}
调用代码
/**
* 测试抛出异常乱码
*
* @return
*/
@RequestMapping(value = "/say", produces = "text/html;charset=UTF-8")
@ResponseBody
String say2() {
throw new TestException();
}
访问 http://localhost:8080/say2 返回乱码

原因
通过查看spring mvc 源码发现,解析这个 注解的类为 ResponseStatusExceptionResolver 主要是在resolveResponseStatus 中解析并 调用 response sendError 方法来想客户端发送 html 格式的异常消息,产生乱码的原因是因为编码格式不匹配,而这里明显没有 调用 response.setCharacterEncoding 方法。
public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver implements MessageSourceAware {
private MessageSource messageSource;
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
{
ResponseStatus responseStatus = (ResponseStatus)AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);
if (responseStatus != null);
try {
return resolveResponseStatus(responseStatus, request, response, handler, ex);
}
catch (Exception resolveEx) {
this.logger.warn("Handling of @ResponseStatus resulted in Exception", resolveEx);
break label81:
if (ex.getCause() instanceof Exception) {
ex = (Exception)ex.getCause();
return doResolveException(request, response, handler, ex); }
}
label81: return null;
}
protected ModelAndView resolveResponseStatus(ResponseStatus responseStatus, HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) throws Exception {
int statusCode = responseStatus.code().value();
String reason = responseStatus.reason();
if (this.messageSource != null) {
reason = this.messageSource.getMessage(reason, null, reason, LocaleContextHolder.getLocale());
}
if (!(StringUtils.hasLength(reason))) {
response.sendError(statusCode);
} else {
response.sendError(statusCode, reason);
}
return new ModelAndView();
}
}
spring 是通过 CharacterEncodingFilter来设置 request 和 response 的编码格式的,查看代码如下,走到这一步,就要查看 spirng boot 是在哪里定义这个过滤器的
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}
查看代码,是在 HttpEncodingAutoConfiguration 这个配置类中设置的,代码如下 ,这里就用到一个属性类 HttpEncodingProperties 查看代码,调用的是 shouldForce 方法,所以只需一个设置,就可以让他强制设置编码格式 spring.http.encoding.force=true
public class HttpEncodingAutoConfiguration {
private final HttpEncodingProperties properties;
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean({ CharacterEncodingFilter.class })
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(HttpEncodingProperties.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(HttpEncodingProperties.Type.RESPONSE));
return filter;
}
@Bean
public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
return new LocaleCharsetMappingsCustomizer(this.properties);
}
private static class LocaleCharsetMappingsCustomizer implements EmbeddedServletContainerCustomizer, Ordered {
private final HttpEncodingProperties properties;
LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
this.properties = properties;
}
public void customize(ConfigurableEmbeddedServletContainer container) {
if (this.properties.getMapping() != null)
container.setLocaleCharsetMappings(this.properties.getMapping());
}
public int getOrder() {
return 0;
}
}
}
boolean shouldForce(Type type) {
Boolean force = (type == Type.REQUEST) ? this.forceRequest : this.forceResponse;
if (force == null) {
force = this.force;
}
if (force == null) {
force = Boolean.valueOf(type == Type.REQUEST);
}
return force.booleanValue();
}
解决办法

spring.http.encoding.force=true
结果
再次访问刷新,显示正常。

spring mvc @ResponseStatus 注解 注释返回中文乱码的问题的更多相关文章
- spring mvc 文件下载 get请求解决中文乱码问题
方案简写,自己或有些基础的可以看懂,因为没时间写的那么详细 方案1 spring mvc解决get请求中文乱码问题, 在tamcat中server.xml文件 URIEncoding="UT ...
- Spring MVC 结合Velocity视图出现中文乱码的解决方案
编码问题一直是个很令人头疼的事,这几天搭了一个Spring MVC+VTL的web框架,发现中文乱码了,这里记录一种解决乱码的方案. 开发环境为eclipse,首先,检查Window->pref ...
- Spring MVC的Post请求参数中文乱码的原因&处理
一.项目配置: Spring 4.4.1-RELEASE Jetty 9.3.5 JDK 1.8 Servlet 3.1.0 web.xml文件中没有配置编解码Filter 二.实际遇到的问题:客户端 ...
- spring ajax以及页面返回中文乱码问题解决
在spring配置文件中添加 <!--返回中文乱码--> <mvc:annotation-driven > <!-- 消息转换器 --> <mvc:messa ...
- ajax提交 返回中文乱码问题
接口返回数据相关 使用@ResponseBody后返回NUll 说明:刚把后台运行起来,兴高采烈的测试接口数据,结果无论如何都是返回null, 最终通过各种百度,发现原来是没有引入关键的Jar包. 解 ...
- Springboot @ResponseBody返回中文乱码
最近我在把Spring 项目改造Springboot,遇到一个问题@ResponseBody返回中文乱码,因为response返回的content-type一直是application/json;ch ...
- springmvc配置一:ajax请求防止返回中文乱码配置说明
Spring3.0 MVC @ResponseBody 的作用是把返回值直接写到HTTP response body里. Spring使用AnnotationMethodHandlerAdapter的 ...
- 解决SpringMVC的@ResponseBody返回中文乱码
SpringMVC的@ResponseBody返回中文乱码的原因是SpringMVC默认处理的字符集是ISO-8859-1,在Spring的org.springframework.http.conve ...
- SpringMVC @ResponseBody返回中文乱码
SpringMVC的@ResponseBody返回中文乱码的原因是SpringMVC默认处理的字符集是ISO-8859-1, 在Spring的org.springframework.http.conv ...
随机推荐
- ASP.NET MVC IOC 之AutoFac
ASP.NET MVC IOC 之AutoFac攻略 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天, ...
- readonly和const的区别
readonly与const的区别1.const常量在声明的同时必须赋值,readonly在声明时可以不赋值2.readonly只能在声明时或在构造方法中赋值(readonly的成员变量可以根据调用不 ...
- 基于.NET的微信SDK
超级懒汉编写的基于.NET的微信SDK 一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发“框架”,但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的 ...
- Vijos1055 奶牛浴场(极大化思想求最大子矩形)
思路详见 王知昆<浅谈用极大化思想解决最大子矩形问题> 写得很详细(感谢~....) 因为不太会用递推,所以用了第一种方法,时间复杂度是O(n^2),n为枚举的点数,对付这题绰绰有余 思路 ...
- Day2:T4求逆序对(树状数组+归并排序)
T4: 求逆序对 A[I]为前缀和 推导 (A[J]-A[I])/(J-I)>=M A[j]-A[I]>=M(J-I) A[J]-M*J>=A[I]-M*I 设B[]=A[]-M*( ...
- [置顶] Android事件—单选按键和下拉按键
在平常的开发中单选按键和下拉按键是非常常用的2个点击事件.首先介绍下单选按键 1:单选按键,单选的主键是radiogroup 这个主键也是很重要的 首先介绍下主键的布局 <?xml versio ...
- DDD社区官网
DDD社区官网上一篇关于聚合设计的几个原则的简单讨论: 聚合是用来封装真正的不变性,而不是简单的将对象组合在一起 聚合应尽量设计的小 聚合之间通过ID关联 聚合内强一致性,聚合之间最终一致性 从聚合和 ...
- 如何理解signal函数声明
Signal函数用起来其实很简单,但是回头看看他的声明,相信会有很多人表示费解.自己也在这个问题中纠结了好几年了,今天终于弄明白,很是兴奋,一起分享一下. 先看函数原型:void (*signal(i ...
- Oracle用脚本语言导入SCOTT用户
许多Oracle新手都遇到这样的问题,安装Oracle之后没有SCOTT用户,那就自己加入吧,打开Oracle 命令窗口复制下面SQL脚本直接输入就行了,包含了测试学习的DEPT.EMP.BONUS. ...
- Newlife商业源码分享
[商业源码]生日大放送-Newlife商业源码分享 今天是农历六月二十三,是@大石头的生日,记得每年生日都会有很劲爆的重量级源码送出,今天Newlife群和论坛又一次疯狂了,吃水不忘挖井人,好的东西肯 ...