Tomcat considers the entire request to be ISO-8859-1
by default "factory".
The direct and specific solution for Tomcat is to change the server configuration (server.xml
):
<Server port="8105" shutdown="SHUTDOWN">
...
<Service name="Catalina">
<Connector port="8180" URIEncoding="UTF-8" />
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" />
</Engine>
</Service>
....
</Server>
However, I don’t consider this ideal solution because when you need to do the deploy of its application in an environment controlled by third parties will probably not have access to this change.
A solution that can be implemented in the application itself is divided (at least) into: adjust the encoding in the body of requests, parameters and headers.
To solve the problem for data in the request body, I usually add a filter to the web.xml
that forces the encoding to be of a certain type. In a project where I use Spring, the following excerpt solves the problem:
<filter>
<filter-name>encoding-filter</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>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
If you don’t use Spring, you can use apache library code and put the class in its own design.
For data in headers or parameters, we can encapsulate the HttpServletRequest
through a filter. I did the implementation below, but I don’t have an application in hand to test, so any problem give me a feedback:
public class ParametersEncodingFilter implements Filter {
private String charset = "UTF-8";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String charsetParam = filterConfig.getInitParameter("charset");
if (charsetParam != null && !charsetParam.isEmpty()) {
this.charset = charsetParam;
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new FilteredRequest(charset, request), response);
}
@Override
public void destroy() {
//nothing to clean up
}
final private static class FilteredRequest extends HttpServletRequestWrapper {
public FilteredRequest(String charset, ServletRequest request) {
super((HttpServletRequest)request);
//convert encoding params
Map<String, String[]> originalParams = super.getParameterMap();
for(Object key : originalParams.keySet()) {
String[] entry = originalParams.get(key);
for (int i = 0; i < entry.length; i++) {
try {
entry[i] = new String(entry[i].getBytes("ISO-8859-1"), charset);
} catch (UnsupportedEncodingException e) {
return; //if can't convert one, it cannot convert any of them
}
}
}
}
}
}
Note: This implementation considers that the filter has a parameter with the desired encoding, as in the Spring filter settings above.
And one last comment: if it is possible to encode the URL parameters, for example N%C3%A3o%2Bpermitido
instead of Não+Permitido
, perhaps solve the parameter specific problem without further implementations.
Please try the message encounter before redirecting to the screen: http://stackoverflow.com/questions/5330104/encoding-url-query-parameters-in-java
– Victor Salvalagio Pereira
The problem is that it is the framework that redirects when an exception is thrown. When I do the message encounter, some characters are doubly encoded. For example, the message "a b" turns "a+b" and when it redirects, it turns "a%2Bb".
– rodrigorgs
I understand... do the Code by javascript then: http://stackoverflow.com/questions/12042592/decoding-ur-parameters-with-javascript
– Victor Salvalagio Pereira
It may be, but I’m still looking for a better solution.
– rodrigorgs