Spring MVC UTF-8 编码

Posted

技术标签:

【中文标题】Spring MVC UTF-8 编码【英文标题】:Spring MVC UTF-8 Encoding 【发布时间】:2011-08-21 03:30:42 【问题描述】:

目前我正在尝试开始使用 Spring MVC。在尝试时,我遇到了编码问题。

我想在我的 JSP 页面上显示 UTF-8 字符,所以我在我的 ModelAndView 中添加了一个带有 UTF-8 字符的字符串。它看起来像这样:

@Controller
public class HomeController 

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView home() 
        logger.info("Welcome home!");
        return new ModelAndView("home", "utftest", "ölm");
    


在 JSP 页面上,我只想显示带有 UTF-8 字符的字符串,如下所示:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Home</title>
</head>
<body>
    <h1>Hello world!</h1>
    <p><c:out value="ö" /></p>
    <p><c:out value="$utftest"></c:out></p>
</body>
</html>

结果我得到以下信息:

Hello world!

ö

ölm

请注意,以下代码 &lt;c:out value="ö" /&gt; 显示时没有编码错误。 我还在 Springsource Tool Suite 中将默认编码设置为 UTF-8,但我仍然收到错误的字符。

编辑:

也许我应该提到我正在使用装有 OS X 10.6 的 Mac。对于 Spring 开发,我使用 Spring (http://www.springsource.com/developer/sts) 的 Springsource Tool Suite。 希望这有助于找出我的设置有什么问题。

编辑 2:

感谢 McDwell,我刚刚尝试在我的控制器中使用 "\u00f6lm" 而不是 "ölm",并且 JSP 页面上的编码问题已经消失。

这是否意味着我的 .java 文件使用错误的字符集进行编码?在 Eclipse 中哪里可以更改?

谢谢。

【问题讨论】:

Springsource 工具套件,基本上是带有一些插件的 Eclipse 吗?您究竟是如何设置默认编码的? 是的,它只是带有一些用于 Spring 开发的预安装插件的 Eclipse (springsource.com/developer/sts)。我将 Springsource 首选项中的编码(与 Eclipse 中的相同)General > Workspace 和 General > Content Types 更改为 UTF-8 好吧,McDowell 在我删除的答案(基本上回答了您已经完成的内容)中提到,这可能是由于 Java 编译器使用错误的编码读取源文件造成的。这是一个非常合理的原因。但由于我不使用/拥有 Mac,我不知道如何修复它。 @OemerA - 您可以通过将"ölm" 替换为"\u00f6lm" 来缩小问题范围。如果这可行,您就知道问题出在 Java 源文件及其编译为字节码。 @OemerA - 我从来没有安装过 STS,所以我不能说太多。鉴于ö 是UTF-8 中的字节序列C3 B6,我会说编辑器正在做正确的事情(您可以使用外部十六进制编辑器进行确认)。因此,读取文件并将其传递给编译器的任何内容都是使用错误的编码读取它 - 查看项目构建器(通过右键单击项目)并可能访问他们各自的错误数据库。 【参考方案1】:

确保在 web.xml 中注册 Spring 的 CharacterEncodingFilter(必须是该文件中的第一个过滤器)。

<filter>  
    <filter-name>encodingFilter</filter-name>  
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    <init-param>  
       <param-name>encoding</param-name>  
       <param-value>UTF-8</param-value>  
    </init-param>  
    <init-param>  
       <param-name>forceEncoding</param-name>  
       <param-value>true</param-value>  
    </init-param>  
</filter>  
<filter-mapping>  
    <filter-name>encodingFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping> 

如果您使用的是 Tomcat,您可能没有在您的 server.xml 中设置 URIEncoding。如果您不将其设置为 UTF-8,它将无法正常工作。绝对保留CharacterEncodingFilter。不过,这里有一个简明的checklist。它肯定会指导您完成这项工作。

【讨论】:

过滤器只设置POST请求的请求参数的编码。 URIEncoding 对 GET 请求执行此操作。当只是通过 HTTP 响应显示页面时,他已经遇到了问题,而不是在处理提交的数据时。 对不起,这对我不起作用。我仍然得到和以前一样的错误字符。 作为 Tomcat 用户,这个答案中最重要的部分是关于在 server.xml 文件中设置 URIEncoding 的语句,即在连接器的定义中到您使用的任何端口(例如 8080 ),您必须具有以下分配:URIEncoding="UTF-8" URIEncoding 自 Tomcat 8 (tomcat.apache.org/migration-8.html#URIEncoding) 以来默认设置为 UTF-8,因此对于新部署来说,这是一个少一个问题。过滤器仍然是正确处理 POST 请求所必需的。 稍微解释一下:我们需要CharacterEncodingFilter,因为浏览器在提交post数据时通常不提供编码信息,因此服务器可能使用与传入数据不同的编码。所以我们告诉服务器CharacterEncodingFilter中的预期编码。【参考方案2】:

好的,伙计们,我找到了编码问题的原因。

问题出在我的构建过程中。我没有在我的pom.xml 文件中告诉 Maven 使用 UTF-8 编码构建项目。因此,Maven 只是从我的系统中获取了默认编码,即 MacRoman,并使用 MacRoman 编码构建它。

幸运的是,Maven 在构建项目时会就此向您发出警告(但由于所有其他消息,该警告很有可能很快从您的屏幕上消失)。

这是您需要在pom.xml 文件中设置的属性:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    ...
</properties>

感谢大家的帮助。如果没有你们,我将无法解决这个问题!

【讨论】:

谢谢!! +1。我没有使用 maven,我刚开始使用 gradle(但我是新手),这个问题开始发生。在gradle中指定java任务的编译编码:compileJava.options.encoding = 'UTF-8'解决问题。 这个问题也可能发生在其他情况下,与您的构建问题无关。【参考方案3】:

除了 Benjamin 的回答(我只是略过)之外,您还需要确保您的文件实际上是使用正确的编码存储的(对于源代码、JSP 等,将是 UTF-8,但请注意Java 属性文件必须按照定义编码为 ISO 8859-1)。

这样做的问题是无法判断使用什么编码来存储文件。您唯一的选择是使用特定编码打开文件,并检查内容是否有意义。您还可以尝试使用 iconv 将文件从假定的编码转换为所需的编码 - 如果产生错误,则说明您的假设不正确。因此,如果您假设 hello.jsp 编码为 UTF-8,请运行“iconv -f UTF-16 -t UTF-8 hello.jsp”并检查错误。

如果您发现您的文件没有正确编码,您需要找出原因。它可能是您用来创建文件的编辑器或 IDE。如果是 Eclipse(和 STS),请确保将文本文件编码(首选项/常规/工作区)设置为 UTF-8(不幸的是,它默认为您系统的平台编码)。

编码问题难以调试的原因在于涉及的组件太多(文本编辑器、浏览器,以及介于两者之间的每个软件组件,在某些情况下还包括数据库),而且每个组件都有可能引入一个错误。

【讨论】:

根据问题的评论,OP已经将编辑器配置为将文件保存为UTF-8。 是的,尽管 OP 的评论是在我回答之前发布的,但当我第一次加载页面并阅读问题时,它并不存在。【参考方案4】:

除了 Benjamin 的回答 - 如果您使用 Spring Security,将 CharacterEncodingFilter 放在 web.xml 中可能并不总是有效。在这种情况下,您需要创建一个自定义过滤器并将其作为第一个过滤器添加到过滤器链中。为确保它是链中的第一个过滤器,您需要在您的 WebSecurityConfigurerAdapter 中使用 addFilterBefore 在 ChannelProcessingFilter 之前添加它:

@Configuration
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter 


    @Override
    protected void configure(HttpSecurity http) throws Exception 

        //add your custom encoding filter as the first filter in the chain
        http.addFilterBefore(new EncodingFilter(), ChannelProcessingFilter.class);

        http.authorizeRequests()
            .and()
            // your code here ...
    

Spring Security 中所有过滤器的排序可在此处获得:HttpSecurityBuilder - addFilter()

您的自定义 UTF-8 编码过滤器可能如下所示:

public class EncodingFilter extends GenericFilterBean 

    @Override
    public void doFilter(
            ServletRequest request, 
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException 

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        chain.doFilter(request, response);
    

不要忘记添加你的jsp文件:

<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>

如果存在,则从 web.xml 中删除 CharacterEncodingFilter。

【讨论】:

你救了我的命。 我必须在我的 jsp 文件中添加 &lt;%@ page contentType="text/html;charset=UTF-8" %&gt;【参考方案5】:

在 Spring MVC 返回字符串中强制 UTF-8 编码的最简单解决方案:

@RequestMapping 中,使用:

produces = MediaType.APPLICATION_JSON_VALUE + "; charset=utf-8"

【讨论】:

有效!!!谢谢我已经尝试了这里列出的所有解决方案,但只有这样有效:) 我觉得这个更好看MediaType.APPLICATION_JSON_UTF8_VALUE 这也是唯一对我有用的解决方案。 “≤”返回为“?”。添加这个为我解决了这个问题。非常感谢!!【参考方案6】:

右键点击你的controller.java然后属性并检查你的文本文件是否用utf-8编码,如果不是这是你的错误。

【讨论】:

【参考方案7】:

要解决此问题,您需要以下三个步骤:

    将页面编码设置为 UTF-8,如下所示:

    <%@ page language="java" pageEncoding="UTF-8"%>
    <%@ page contentType="text/html;charset=UTF-8" %>
    

    在 web.xml 文件中设置过滤器如下:

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    将资源编码设置为 UTF-8,以防您直接在 Java 代码或 JSP 中编写任何 UTF-8 字符。

【讨论】:

【参考方案8】:

根据您呈现视图的方式,您可能还需要:

@Bean
public StringHttpMessageConverter stringHttpMessageConverter() 
    return new StringHttpMessageConverter(Charset.forName("UTF-8"));

【讨论】:

谢谢。我有一个控制器方法,它返回一个编码错误的@ResponseBody String(因为StringHttpMessageConverter 默认在内部使用ISO-8859-1)。顺便说一句,您可以使用 Java 7 的 StandardCharsets.UTF_8,例如new StringHttpMessageConverter(StandardCharsets.UTF_8).【参考方案9】:

像这里一样为我工作Spring MVC Java config

通过添加到网络初始化程序

 @Override
      protected Filter[] getServletFilters() 

        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        return new Filter[]  characterEncodingFilter;
      

【讨论】:

【参考方案10】:

从 servlet spec 4.0 开始,您可以在 servlet 上下文中设置请求字符编码,而无需指定过滤器。

在 web.xml 中:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0">
  <request-character-encoding>UTF-8</request-character-encoding>
  [...]

或者在 Java 配置中:

servletContext.setRequestCharacterEncoding("UTF-8");

【讨论】:

以上是关于Spring MVC UTF-8 编码的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring MVC 时如何在 Freemarker 视图中设置内容类型?

Spring Mvc Hibernate Encoding/多行导入sql

谁在 Spring MVC (@ResponseBody) 中设置响应内容类型

springMvc 返回的Html 中文变成问号??

如何使用 Spring MVC & Security、Jasig CAS 和 JSP 视图在 Spring Boot 2 中配置 UTF-8?

Spring MVC字符编码过滤器