POSTおよびGETリクエストにおける中国語の乱码問題の解決方法

HTTPリクエストで中国語を扱う際、POSTおよびGETメソッドで文字化けが発生するケースがあります。Spring MVCでは専用のフィルタを用いて解決できますが、特定の状況では追加設定が必要です。

web.xmlでの基本設定例

<filter>
    <filter-name>encoding</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>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

GETリクエスト専用の対処法

  1. Tomcat設定ファイルの変更
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />
  1. 特殊なケース向けのカスタムフィルタ(Spring MVC標準フィルタが対応できない場合)
package com.example.encoding;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

public class CustomEncodingFilter implements Filter {
    @Override
    public void destroy() {}
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.setContentType("text/html;charset=UTF-8");
        
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletRequest wrappedReq = new CustomRequestWrapper(req);
        chain.doFilter(wrappedReq, response);
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
}

class CustomRequestWrapper extends HttpServletRequestWrapper {
    private final HttpServletRequest request;
    private boolean isEncoded = false;
    
    public CustomRequestWrapper(HttpServletRequest req) {
        super(req);
        this.request = req;
    }
    
    @Override
    public Map<String, String[]> getParameterMap() {
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
            try {
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
            Map<String, String[]> paramMap = request.getParameterMap();
            if (!isEncoded) {
                for (String name : paramMap.keySet()) {
                    String[] values = paramMap.get(name);
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                values[i] = new String(values[i].getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                isEncoded = true;
            }
            return paramMap;
        }
        return super.getParameterMap();
    }
    
    @Override
    public String getParameter(String name) {
        Map<String, String[]> map = getParameterMap();
        String[] values = map.get(name);
        return values != null ? values[0] : null;
    }
    
    @Override
    public String[] getParameterValues(String name) {
        return getParameterMap().get(name);
    }
}

web.xmlへの登録方法

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>com.example.encoding.CustomEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

タグ: SpringMVC CharacterEncodingFilter HTTPリクエスト Tomcat設定 カスタムフィルタ

8月4日 01:02 投稿