Сегодня я потратил много часов, чтобы понять, как заставить правильно декодировать закодированные символы в приложениях JSF, работающих на JBoss (используя JBoss 7 Final). Проблема возникает, когда у вас есть, например, китайские символы, переданные через URL. Предположим, у вас есть 指 事, закодированный как% E6% 8C% 87% E4% BA% 8B. Удивительно, но эти персонажи попадают на серверную сторону как æŒ ‡ äº ‹. Они декодируются сервером автоматически с ISO-8859-1. Таким образом, не имеет значения, если вы попытаетесь расшифровать его самостоятельно, например:
|
1
2
3
|
FacesContext fc = FacesContext.getCurrentInstance();String param = fc.getExternalContext().getRequestParameterMap().get(name);String decodedParam = java.net.URLDecoder.decode(param, "UTF-8"); |
Это не помогает, потому что символы уже были неправильно декодированы, а вы уже неправильно их декодировали из карты параметров запроса. Это тоже не поможет, если у вас есть на странице
|
1
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> |
Чтобы преодолеть эту ошибку, вам нужны две вещи: специальный фильтр кодировки символов и конфигурация в standalone.xml JBoss. Фильтр должен установить настроенную кодировку для запроса и ответа.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public class CharacterEncodingFilter implements Filter { /** The default character encoding to set for request / response. */ private String encoding = null; /** The filter configuration object. */ private FilterConfig filterConfig; /** Should a character encoding specified by the client be ignored? */ private boolean ignore = true; public void destroy() { encoding = null; filterConfig = null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // conditionally select and set the character encoding to be used if ((ignore || (request.getCharacterEncoding() == null)) && (encoding != null)) { request.setCharacterEncoding(encoding); response.setCharacterEncoding(encoding); } // pass control on to the next filter chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; this.encoding = filterConfig.getInitParameter("encoding"); String value = filterConfig.getInitParameter("ignore"); this.ignore = ((value == null) || value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")); }} |
Примечание: это не поможет, если вы только установите кодировку для запроса. Вы также должны установить его для ответа response.setCharacterEncoding (кодировка). Конфигурация в web.xml выглядит так
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>xyz.mypackage.CharacterEncodingFilter</filter-class> <init-param> <description>override any encodings from client</description> <param-name>ignore</param-name> <param-value>true</param-value> </init-param> <init-param> <description>the encoding to use</description> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param></filter><filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>*.jsf</url-pattern></filter-mapping> |
Теперь вам нужно добавить следующие системные свойства в standalone.xml сразу после закрывающего тега <extensions>:
|
1
2
3
4
|
<system-properties> <property name="org.apache.catalina.connector.URI_ENCODING" value="UTF-8"/> <property name="org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING" value="true"/></system-properties> |
Из документа:
- org.apache.catalina.connector.URI_ENCODING указывает кодировку символов, используемую для декодирования байтов URI, после% xx декодирования URL-адреса. Если не указано, будет использоваться ISO-8859-1.
- org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING указывает, следует ли использовать кодировку, указанную в contentType, для параметров запроса URI вместо использования org.apache.catalina.connector.URI_ENCODING. Этот параметр присутствует для совместимости с Tomcat 4.1.x, где для параметров из URL-адреса также использовалась кодировка, указанная в contentType или явно заданная с использованием метода Request.setCharacterEncoding. Значение по умолчанию неверно.
JBoss теперь устанавливает кодировку символов для ответа и декодирует параметры URL с его помощью. Я надеюсь, что эта информация поможет вам сэкономить ваше время.