SpringMVC 数据json字符串(String)响应乱码问题

本文介绍了解决SpringMVC框架中JSON响应乱码的四种方法,包括自定义StringHttpMessageConverter、配置默认Converter、使用@RequestMapping的produces属性及直接设置response编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在我们解决问题前,先来查看这样一张图 

由此可知SpringMVC接收和响应数据时都会经过HttpMessageConverter接口类

而我们的问题是响应json字符串(String),那么自然会调用HttpMessageConverter的某一实现类来完成相关数据的编码转换。

可以发现在org.springframework.http.converter.StringHttpMessageConverter是实现此过程的实现类。因此我们如要解决乱码问题需要从此处下手。

解决方案1

public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");

我们发现StringHttpMessageConverter类里面默认编码是ISO-8859-1,所以我们在返回json串时会乱码,因此我们可以重写一个类继承自StringHttpMessageConverter,重写其内部方法,并且设置默认编码为UTF-8

public class UTF8StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private volatile List<Charset> availableCharsets;
    private boolean writeAcceptCharset;

    public UTF8StringHttpMessageConverter() {
        this(DEFAULT_CHARSET);
    }

    public UTF8StringHttpMessageConverter(Charset defaultCharset) {
        super(defaultCharset, new MediaType[]{MediaType.TEXT_PLAIN, MediaType.ALL});
        this.writeAcceptCharset = true;
    }

    public void setWriteAcceptCharset(boolean writeAcceptCharset) {
        this.writeAcceptCharset = writeAcceptCharset;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return String.class == clazz;
    }

    @Override
    protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
        Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
        return StreamUtils.copyToString(inputMessage.getBody(), charset);
    }

    @Override
    protected Long getContentLength(String str, MediaType contentType) {
        Charset charset = this.getContentTypeCharset(contentType);

        try {
            return (long)str.getBytes(charset.name()).length;
        } catch (UnsupportedEncodingException var5) {
            throw new IllegalStateException(var5);
        }
    }

    @Override
    protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
        if (this.writeAcceptCharset) {
            outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
        }

        Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
        StreamUtils.copy(str, charset, outputMessage.getBody());
    }

    protected List<Charset> getAcceptedCharsets() {
        if (this.availableCharsets == null) {
            this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
        }

        return this.availableCharsets;
    }

    private Charset getContentTypeCharset(MediaType contentType) {
        return contentType != null && contentType.getCharset() != null ? contentType.getCharset() : this.getDefaultCharset();
    }
}

然后只需要将该类,注册到Spring的annotaion 处理序列中即可,下次SpringMVC返回json数据时会自动调用用户自定义的converter

<mvc:annotation-driven>
      <mvc:message-converters register-defaults="true">
            <bean class="com.javazhan.controller.UTF8StringHttpMessageConverter"/>
      </mvc:message-converters>
</mvc:annotation-driven>

解决方案2

对springMVC框架内默认的Converter进行重新配置,配置其对于UTF-8等编码的支持

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/html;charset=UTF-8</value>
                    <value>application/json;charset=UTF-8</value>
                    <value>text/plain;charset=UTF-8</value>
                    <value>application/xml;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

解决方案3

使用produces属性

在RequestMapping使用(produces = “text/html; charset=utf-8”)produces 作用根据请求头中的Accept进行匹配,如请求头“Accept:text/html”时即可匹配。

如果类型是:application/json ,设置为:produces = “application/json; charset=utf-8”


解决方案4

在以前学servlet过程中,记得是可以设置响应的数据编码格式的,这样也可以完成乱码问题的解决

    response.setContentType("text/html;charset=utf-8");
    PrintWriter out=response.getWriter();
    out.println(data.toString());
    out.flush();
    out.close();

 

 

 

 

 

 

 

<think>嗯,用户想了解Spring MVC响应数据方式。我得先回忆一下Spring MVC处理响应的各种方法。首先,控制器返回字符串通常用于视图名称,但用户可能更关心数据绑定,比如@ResponseBody和@RestController的区别。还有ModelAndView对象,这个可能比较基础,但需要提到。 然后,返回对象或集合,配合@ResponseBody自动转JSON或XML,这部分很重要,特别是现在RESTful API流行。可能需要解释消息转换器的工作原理,比如HttpMessageConverter接口,以及如何根据Content-Type处理不同格式。 还有直接写回HttpServletResponse的情况,比如用OutputStream手动输出,虽然不常用,但在特定场景下有用。比如文件下载或者需要细粒度控制响应时。 可能用户还会关心视图技术,比如JSP、Thymeleaf,虽然现在前后端分离多了,但传统方法还是有必要提一下。此外,ResponseEntity可以自定义状态码和头信息,适合需要更多控制的场景。 别忘了@RestController是组合了@Controller和@ResponseBody,简化了REST控制器的编写。另外,路径变量@PathVariable和请求参数@RequestParam如何绑定到响应数据里,可能需要举例说明。 还要注意不同的内容类型,比如JSON和XML的配置,可能需要依赖如Jackson或JAXB库。消息转换器的配置方法,比如WebMvcConfigurer里添加转换器。 可能用户在实际开发中会遇到乱码问题,所以需要提到produces属性设置charset=UTF-8,或者在配置中统一设置消息转换器的字符编码。 最后,总结各种方式的适用场景,帮助用户根据需求选择合适的方法。比如前后端分离常用@RestController返回JSON,传统应用可能用ModelAndView结合模板引擎。</think>Spring MVC 提供了多种响应数据的方式,以下是核心方法分步详解: 1. **返回视图名称(传统模式)** ```java @Controller @RequestMapping("/demo") public class DemoController { @GetMapping("/view") public String showView(Model model) { model.addAttribute("message", "Hello Thymeleaf"); return "demoPage"; // 对应src/main/resources/templates/demoPage.html } } ``` - 配合视图解析器(如Thymeleaf、JSP) - 数据通过Model对象传递 2. **返回字符串内容** ```java @Controller public class TextController { @GetMapping(value = "/text", produces = "text/plain;charset=UTF-8") @ResponseBody public String getText() { return "直接文本响应"; } } ``` - 需要@ResponseBody注解 - 设置produces属性定义MIME类型 3. **返回JSON/XML(RESTful常用)** ```java @RestController // 组合了@Controller + @ResponseBody @RequestMapping("/api") public class ApiController { @GetMapping("/user/{id}") public User getUser(@PathVariable int id) { return new User(id, "张三", 25); } @GetMapping("/list") public List<User> getUsers() { return Arrays.asList( new User(1, "李四", 30), new User(2, "王五", 28) ); } } ``` - 自动通过Jackson库转换对象为JSON - 需要配置消息转换器: ```xml <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> ``` 4. **ModelAndView 对象** ```java @Controller public class MavController { @GetMapping("/mav") public ModelAndView getMAV() { ModelAndView mav = new ModelAndView("viewName"); mav.addObject("key", "value"); return mav; } } ``` - 可同时控制视图和数据 - 适合需要灵活设置响应头的场景 5. **ResponseEntity 精控响应** ```java @GetMapping("/custom") public ResponseEntity<Map<String, Object>> customResponse() { Map<String, Object> body = new HashMap<>(); body.put("status", 200); body.put("data", "自定义响应"); return ResponseEntity.status(HttpStatus.ACCEPTED) .header("X-Custom-Header", "value") .body(body); } ``` - 可设置状态码、响应头、内容类型 - 适用于需要精确控制HTTP响应的场景 6. **直接操作HttpServletResponse** ```java @GetMapping("/manual") public void manualResponse(HttpServletResponse response) throws IOException { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter writer = response.getWriter(); writer.write("<h1>手动输出</h1>"); writer.flush(); } ``` - 完全控制响应对象 - 适用于文件下载等特殊需求 **配置关键点:** 1. 消息转换器配置(WebMvcConfigurer): ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new MappingJackson2HttpMessageConverter()); converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); } } ``` 2. 常见注解: - `@ResponseBody`:方法返回值直接作为响应体 - `@RestController`:类级别组合注解 - `@RequestMapping(produces = "application/json")`:指定输出格式 **选择策略:** - 前后端分离:优先使用@RestController + JSON - 传统Web应用:视图名称 + 模板引擎 - 特殊需求:ResponseEntity或直接操作HttpServletResponse 这些方式覆盖了从传统Web应用到现代RESTful服务的各种场景,开发者可根据具体需求灵活选择组合使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值