前言

前文中讲到,使用@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 注解 注释返回中文乱码的问题的更多相关文章

  1. spring mvc 文件下载 get请求解决中文乱码问题

    方案简写,自己或有些基础的可以看懂,因为没时间写的那么详细 方案1 spring mvc解决get请求中文乱码问题, 在tamcat中server.xml文件 URIEncoding="UT ...

  2. Spring MVC 结合Velocity视图出现中文乱码的解决方案

    编码问题一直是个很令人头疼的事,这几天搭了一个Spring MVC+VTL的web框架,发现中文乱码了,这里记录一种解决乱码的方案. 开发环境为eclipse,首先,检查Window->pref ...

  3. Spring MVC的Post请求参数中文乱码的原因&处理

    一.项目配置: Spring 4.4.1-RELEASE Jetty 9.3.5 JDK 1.8 Servlet 3.1.0 web.xml文件中没有配置编解码Filter 二.实际遇到的问题:客户端 ...

  4. spring ajax以及页面返回中文乱码问题解决

    在spring配置文件中添加 <!--返回中文乱码--> <mvc:annotation-driven > <!-- 消息转换器 --> <mvc:messa ...

  5. ajax提交 返回中文乱码问题

    接口返回数据相关 使用@ResponseBody后返回NUll 说明:刚把后台运行起来,兴高采烈的测试接口数据,结果无论如何都是返回null, 最终通过各种百度,发现原来是没有引入关键的Jar包. 解 ...

  6. Springboot @ResponseBody返回中文乱码

    最近我在把Spring 项目改造Springboot,遇到一个问题@ResponseBody返回中文乱码,因为response返回的content-type一直是application/json;ch ...

  7. springmvc配置一:ajax请求防止返回中文乱码配置说明

    Spring3.0 MVC @ResponseBody 的作用是把返回值直接写到HTTP response body里. Spring使用AnnotationMethodHandlerAdapter的 ...

  8. 解决SpringMVC的@ResponseBody返回中文乱码

    SpringMVC的@ResponseBody返回中文乱码的原因是SpringMVC默认处理的字符集是ISO-8859-1,在Spring的org.springframework.http.conve ...

  9. SpringMVC @ResponseBody返回中文乱码

    SpringMVC的@ResponseBody返回中文乱码的原因是SpringMVC默认处理的字符集是ISO-8859-1, 在Spring的org.springframework.http.conv ...

随机推荐

  1. Date的使用

    方法 说明 Date() 返回当日的日期和时间 getDate() 获取当天(1-31) getDay() 获取当天的星期(0-6) getMonth() 获取月份(0-11) getFullYear ...

  2. .NET MVC学习之模型绑定

    ASP.NET MVC学习之模型绑定(2)   继ASP.NET MVC学习之模型绑定继续 3.手工调用模型绑定 很多情况下我们都是通过形参的方式接收来自http流中的数据,这看似是完美的,但是缺少了 ...

  3. .NET/Mono

    C#(或者说.NET/Mono)能做的那些事 不做语言之争,只陈述事实: 1.桌面软件 不仅是在Windows上,有了开源的Mono,在Apple Mac和Linux(如:Ubuntu)上也有C#的施 ...

  4. 仿async/await(一)and Gulp:新一代前端构建利器

    NET 4.5的async/await真是个神奇的东西,巧妙异常以致我不禁对其实现充满好奇,但一直难以窥探其门径.不意间读了此篇强文<Asynchronous Programming in C# ...

  5. Fiddler工具

    Fiddler初探 我们知道监视Http和Https请求的工具有多种,例如:HttpWatch,FireBug等.但是今天接触到一种新的工具Fiddler.Fiddler能记录所有客户端和服务器的ht ...

  6. [原]iOS中 Web 页面与 Native Code 的一种通信方式

    在 iOS 开发中,Web 页面与 Native Code 通信可以分为两个方面: 1.Native Code 调用 Web 页面的方法:主要是调用页面中的 Javascript 函数. 2.Web ...

  7. in和exists哪个效率高本人测试证明

    in和exists哪个效率高本人测试证明 SQLSERVR语句 in和exists哪个效率高自己测试本人测试证明 最近很多人讨论in和exists哪个效率高,今天就自己测试一下 我使用的是客户的数据库 ...

  8. 我的Emacs折腾经验谈(四) 也谈Yasnippet

    又是好久没更新了,不过还好,现在慢慢有点感觉了,好长时间不写博客会心里有点感觉欠一点什么东西.觉得每次写了东西都往主页推搞得压力好大,以后就不往网站首页推了,纯留下来供参考,另外就是主要方便从搜索找过 ...

  9. JAVA多线程经典问题 -- 生产者 消费者

    工作2年多来一直也没有计划写自己的技术博客,最近辞职在家翻看<thingking in JAVA>,偶尔看到了生产者与消费者的一个经典的多线程同步问题.本人在工作中很少使用到多线程以及高并 ...

  10. .Net程序员面试试题

    1:简述private protected public internal修饰符的访问权限? private:私有成员在类的内部可以访问: protected:受保护的成员,在类的内部和继承类中可以访 ...