Сегодня я потратил много часов, чтобы понять, как заставить правильно декодировать закодированные символы в приложениях 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 с его помощью. Я надеюсь, что эта информация поможет вам сэкономить ваше время.