En el entorno que estoy usando (Tomcat 6), las secuencias porcentuales en segmentos de ruta aparentemente se decodifican utilizando ISO-8859-1 cuando se asignan a @PathVariable.Spring/Rest @PathVariable codificación de caracteres
Me gustaría que fuera UTF-8.
Ya configuré Tomcat para usar UTF-8 (usando el atributo URIEncoding en server.xml).
¿Spring/Rest hace la decodificación por sí mismo? En caso afirmativo, ¿dónde puedo anular la codificación predeterminada?
Información adicional; aquí está mi código de prueba:
@RequestMapping(value = "/enc/{foo}", method = RequestMethod.GET)
public HttpEntity<String> enc(@PathVariable("foo") String foo, HttpServletRequest req)
{
String resp;
resp = " path variable foo: " + foo + "\n" +
" req.getPathInfo(): " + req.getPathInfo() + "\n" +
"req.getPathTranslated(): " + req.getPathTranslated() + "\n" +
" req.getRequestURI(): " + req.getRequestURI() + "\n" +
" req.getContextPath(): " + req.getContextPath() + "\n";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("text", "plain", Charset.forName("UTF-8")));
return new HttpEntity<String>(resp, headers);
}
Si hago una solicitud GET HTTP con la siguiente ruta URI:
/TEST/enc/%c2%a3%20and%20%e2%82%ac%20rates
que es la codificación UTF-8 a continuación, forma de
/TEST/enc/£ and € rates
ciento codificados
la salida que consigo es:
path variable foo: £ and ⬠rates
req.getPathInfo(): /enc/£ and € rates
req.getPathTranslated(): C:\Users\jre\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\TEST\enc\£ and € rates
req.getRequestURI(): /TEST/enc/%C2%A3%20and%20%E2%82%AC%20rates
req.getContextPath(): /TEST
que para mí muestra que Tomcat (después de configurar el atributo URIEncoding) hace lo correcto (ver getPathInfo()), pero la variable de ruta se decodifica aún en ISO-8859-1.
Y la respuesta es:
Primavera/Resto aparentemente utiliza la codificación solicitud, que es una cosa muy extraña que hacer, ya que esto es sobre el cuerpo , no el URI. Suspiro.
La adición de este:
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
solucionado el problema. Realmente debería ser más simple.
Y, de hecho, es peor:
Si el método de hecho tiene un cuerpo de la petición, y que uno no está codificado en UTF-8, se necesita el parámetro forceEncoding adicional. Esto parece funcionar, pero me preocupa que cause más problemas más adelante.
Otro enfoque
Mientras tanto, he descubierto que es posible desactivar la decodificación, mi especificando
<property name="urlDecode" value="false"/>
... en cuyo caso el destinatario pueda para lo correcto ; pero, por supuesto, esto hará que muchas otras cosas sean más difíciles.
Esto suena bien en teoría, pero no parece ayudar. Mirando los documentos, si aplica la codificación para el * cuerpo *, no el URI. –
@Julian: Esta es una solución correcta (aunque 'forceEncoding' no es necesario), Spring utiliza la codificación de solicitud para resolver las variables de ruta, vea http://static.springsource.org/spring/docs/3.0.x/javadoc-api /org/springframework/web/util/UrlPathHelper.html (y también necesita este filtro para los parámetros POST de todos modos). – axtavt
@axtavt: oh mi, ¿a quién se le ocurren diseños como este? De todos modos, he podido confirmar que recibo UTF-8 cuando envío una solicitud HTTP con un cuerpo codificado UTF-8, como POST. No * he * podido hacer que el filtro funcione según lo anunciado (sé que algo está sucediendo porque cuando rompo el nombre de clase, obtengo una excepción ClassNotFoundException). –