Java HTML:表单不发送UTF-8格式的输入

Java HTML:表单不发送UTF-8格式的输入,java,html,forms,jsp,utf-8,Java,Html,Forms,Jsp,Utf 8,我已经访问了关于HTML中UTF-8编码的每一个问题,但似乎没有什么能让它像预期的那样工作 我添加了meta标记:没有任何更改。 我在表单中添加了接受字符集属性:没有任何更改。 JSP文件 您可以在字符集中使用与ISO相关的字符串,在JSP代码中使用页面编码定义 类似于charset=“ISO-8859-1”和pageEncoding=“ISO-8859-1”。根据您发布的输出,参数似乎以UTF8的形式发送,随后字符串的unicode字节被解释为ISO-8859-1 下面的代码片段演示了您观察

我已经访问了关于HTML中UTF-8编码的每一个问题,但似乎没有什么能让它像预期的那样工作

我添加了
meta
标记:没有任何更改。
我在
表单
中添加了
接受字符集
属性:没有任何更改。


JSP文件
您可以在字符集中使用与ISO相关的字符串,在JSP代码中使用页面编码定义


类似于charset=“ISO-8859-1”和pageEncoding=“ISO-8859-1”。

根据您发布的输出,参数似乎以UTF8的形式发送,随后字符串的unicode字节被解释为ISO-8859-1

下面的代码片段演示了您观察到的行为

String eGrave = "\u00E8"; // the letter è
System.out.printf("letter UTF8      : %s%n", eGrave);
byte[] bytes = eGrave.getBytes(StandardCharsets.UTF_8);
System.out.printf("UTF-8 hex        : %X %X%n",
        bytes[0], bytes[1], bytes[0], bytes[1]
);
System.out.printf("letter ISO-8859-1: %s%n",
        new String(bytes, StandardCharsets.ISO_8859_1)
);
输出

letter UTF8      : è
UTF-8 hex        : C3 A8
letter ISO-8859-1: è
对我来说,表单发送正确的UTF8编码数据,但稍后该数据不会被视为UTF8

编辑要尝试的其他要点:

输出您请求的字符编码

System.out.println(request.getCharacterEncoding())
强制使用UTF-8检索参数(未经测试,仅为一个想法)

我添加了
meta
标记:没有任何更改

当页面通过HTTP而不是通过本地磁盘文件系统(即页面的URL为
http://...
而不是例如
file://...
)。在HTTP中,将使用HTTP响应头中的字符集。您已将其设置为如下所示:

<%@page pageEncoding="UTF-8"%>
如上所述,这将告诉JSP引擎使用UTF-8编写HTTP响应输出,并将其设置在HTTP响应头中。在发送回服务器之前,webbrowser将使用相同的字符集对HTTP请求参数进行编码

您唯一缺少的步骤是告诉服务器在返回
getParameterXxx()
调用之前必须使用UTF-8解码HTTP请求参数。如何全局实现这一点取决于HTTP请求方法。考虑到您使用的是POST方法,使用下面的servlet筛选器类可以相对容易地实现这一点,该类可以自动钩住所有请求:

@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {
        // NOOP.
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // NOOP.
    }
}
就这些。在Servlet3.0+(Tomcat7和更新版本)中,您不需要额外的
web.xml
配置

您只需要记住,在第一次使用任何
getParameterXxx()
方法获取POST请求参数之前调用
setCharacterEncoding()
方法非常重要。这是因为它们在第一次访问时只解析一次,然后缓存在服务器内存中

例如,下面的顺序是错误的:

String foo = request.getParameter("foo"); // Wrong encoding.
// ...
request.setCharacterEncoding("UTF-8"); // Attempt to set it.
String bar = request.getParameter("bar"); // STILL wrong encoding!
在servlet过滤器中执行
setCharacterEncoding()
作业将确保它及时运行(至少在任何servlet之前)


如果您希望指示服务器也使用UTF-8解码GET(而不是POST)请求参数(您知道,URL中
字符后看到的参数),那么您基本上需要在服务器端对其进行配置。不可能通过ServletAPI对其进行配置。例如,如果您使用Tomcat作为服务器,那么需要在Tomcat自己的
/conf/server.xml
元素的
中添加
URIEncoding=“UTF-8”
属性

如果您仍然在
System.out.println()调用的控制台输出中看到,那么stdout本身没有配置为使用UTF-8的可能性很大。如何做到这一点取决于谁负责解释和呈现标准。例如,如果您使用Eclipse作为IDE,则需要将窗口>首选项>常规>工作区>文本文件编码设置为UTF-8

另见:
预热 让我先说一个普遍的事实,我们都知道计算机除了0和1之外什么都不懂

现在,当您通过HTTP提交HTML表单,并且值通过网络传输到目标服务器时,实际上会传递大量位-0和1

  • 在将数据发送到服务器之前,HTTP客户端(浏览器或curl等)将使用某种编码方案对其进行编码,并期望服务器使用相同的方案对其进行解码,以便服务器准确地知道客户端发送了什么
  • 在将响应发送回客户机之前,服务器将使用某种编码方案对其进行编码,并期望客户机使用相同的方案对其进行解码,以便客户机确切地知道服务器发送了什么
一个类似的例子是,我给你发了一封信,告诉你信是用英语、法语还是荷兰语写的,这样你就能得到我想要给你的确切信息。在回答我的时候,你也会提到我应该读哪种语言

重要的一点是,当数据离开客户端时,它将被编码,并在服务器端解码,反之亦然。如果您没有指定任何内容,那么在从客户端转到服务器端之前,内容将按照进行编码

核心概念 阅读热身很重要。你需要做几件事来确保达到预期的结果

  • 在将数据从客户端发送到服务器之前设置正确的编码
  • 在服务器端设置了正确的解码和编码,以读取请求并将响应写回客户端(这就是您无法获得预期结果的原因
  • 确保所有使用相同编码方案的地方都不会出现这样的情况:在客户端,您使用ISO-8859-1编码,在服务器上,您使用UTF-8解码,否则会出现错误(根据我的类比,我用英语给您写信,您用法语阅读)
  • 如果尝试使用Windows命令行或Eclipse日志查看器等使用日志进行验证,请为日志查看器设置正确的编码。(这是导致问题的原因,但不是主要原因,因为从请求对象读取的数据首先没有正确解码。Windows
    request.setCharacterEncoding("UTF-8");
    ... request.getParameter(...);
    
    <%@page pageEncoding="UTF-8"%>
    
    @WebFilter("/*")
    public class CharacterEncodingFilter implements Filter {
    
        @Override
        public void init(FilterConfig config) throws ServletException {
            // NOOP.
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding("UTF-8");
            chain.doFilter(request, response);
        }
    
        @Override
        public void destroy() {
            // NOOP.
        }
    }
    
    String foo = request.getParameter("foo"); // Wrong encoding.
    // ...
    request.setCharacterEncoding("UTF-8"); // Attempt to set it.
    String bar = request.getParameter("bar"); // STILL wrong encoding!
    
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>
            com.sks.hagrawal.EncodingFilter
        </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>
    
    public class EncodingFilter implements Filter {
        private String encoding = "UTF-8";
        private boolean forceEncoding = false;
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
            request.setCharacterEncoding(encoding);
            if(forceEncoding){ //If force encoding is set then it means that set response stream encoding as well ...
                response.setCharacterEncoding(encoding);
            }
            filterChain.doFilter(request, response);
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
            String encodingParam = filterConfig.getInitParameter("encoding");
            String forceEncoding = filterConfig.getInitParameter("forceEncoding");
            if (encodingParam != null) {
                encoding = encodingParam;
            }
            if (forceEncoding != null) {
                this.forceEncoding = Boolean.valueOf(forceEncoding);
            }
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
    
        }
    }
    
    System.out.println("CharacterEncoding = " + request.getCharacterEncoding());
    request.setCharacterEncoding("UTF-8");
    System.out.println("CharacterEncoding = " + request.getCharacterEncoding());
    
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
             pageEncoding="UTF-8"%>
    
    resp.setContentType("text/html;charset=UT-8");