The difficult way to achieve my goal was to write your own javax.servlet.Filter and insert it into the filter chain. This solution is in line with the Apache Tomcat proposal introduced in the Tomcat Wiki, a character encoding problem .
Update (2010-07-31): The first version of this filter interpreted the query string itself, which was a bad idea. It did not handle POST requests correctly and had problems in combination with other servlet filters, for example, to rewrite URLs. This version instead wraps the parameters originally provided and transcodes them. For it to work correctly, URIEncoding (e.g. in Tomcat) must be configured as ISO-8859-1 .
package de.roland_illig.webapps.webapp1; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; public class EncodingFilter implements Filter { private static final Pattern PAT_COMMA = Pattern.compile(",\\s*"); private String inputEncodingParameterName = null; private final List<Charset> encodings = new ArrayList<Charset>(); @Override @SuppressWarnings("unchecked") public void init(FilterConfig config) throws ServletException { String encodingsStr = "UTF-8"; Enumeration<String> en = config.getInitParameterNames(); while (en.hasMoreElements()) { final String name = en.nextElement(); final String value = config.getInitParameter(name); if (name.equals("encodings")) { encodingsStr = value; } else if (name.equals("inputEncodingParameterName")) { inputEncodingParameterName = value; } else { throw new IllegalArgumentException("Unknown parameter: " + name); } } for (String encoding : PAT_COMMA.split(encodingsStr)) { Charset charset = Charset.forName(encoding); encodings.add(charset); } } @SuppressWarnings("unchecked") @Override public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain fc) throws IOException, ServletException { final HttpServletRequest req = (HttpServletRequest) sreq; final HttpServletResponse res = (HttpServletResponse) sres; final Map<String, String[]> params; try { params = Util.decodeParameters(req.getParameterMap(), encodings, inputEncodingParameterName); } catch (IOException e) { res.sendError(400, e.getMessage()); return; } HttpServletRequest wrapper = new ParametersWrapper(req, params); fc.doFilter(wrapper, res); } @Override public void destroy() {
While the code size is small enough, some implementation details may be wrong, so I expected Tomcat to provide a similar filter already.
To activate this filter, I added the following to web.xml :
<filter> <filter-name>EncodingFilter</filter-name> <filter-class>de.roland_illig.webapps.webapp1.EncodingFilter</filter-class> <init-param> <param-name>encodings</param-name> <param-value>US-ASCII, UTF-8, EUC-KR, ISO-8859-15, ISO-8859-1</param-value> </init-param> <init-param> <param-name>inputEncodingParameterName</param-name> <param-value>ie</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Roland Illig Apr 17 '10 at 9:23 2010-04-17 09:23
source share