In der Umgebung, die ich verwende (Tomcat 6), werden prozentuale Sequenzen in Pfadsegmenten offenbar mit ISO-8859-1 decodiert, wenn sie einer @PathVariable zugeordnet werden.Spring/Rest @PathVariable Zeichencodierung
Ich möchte das UTF-8 sein.
Ich habe Tomcat bereits für die Verwendung von UTF-8 konfiguriert (mit dem URIncoding-Attribut in server.xml).
Macht Spring/Rest die Decodierung für sich alleine? Wenn ja, wo kann ich die Standardcodierung überschreiben?
Zusätzliche Informationen; hier ist mein Testcode:
@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);
}
Wenn ich eine HTTP-GET-Anforderung mit dem folgenden URI-Pfad:
/TEST/enc/%c2%a3%20and%20%e2%82%ac%20rates
, die die UTF-8 codierten dann Prozent-kodierte Form von
/TEST/enc/£ and € rates
die Ausgabe, die ich erhalte, ist:
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
Das zeigt mir, dass Tomcat (nach dem Setzen des URIncoding-Attributs) das Richtige tut (siehe getPathInfo()), aber die Pfadvariable wird noch in ISO-8859-1 dekodiert.
Und die Antwort ist:
Frühling/Rest nutzt offenbar die Anfrage Codierung, die eine sehr seltsame Sache zu tun, da dies über den Körper ist, nicht der URI. Seufzer.
das Hinzufügen von:
<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>
das Problem behoben. Es sollte wirklich einfacher sein.
Und tatsächlich, es ist schlimmer:
Wenn die Methode in die Tat hat eine Anfrage Körper, und dass man nicht in UTF-8, die zusätzlichen forceEncoding Parameter codiert wird benötigt. Dies scheint zu funktionieren, aber ich bin besorgt, es wird später mehr Probleme verursachen.
Ein anderer Ansatz
In der Zwischenzeit fand ich heraus, dass es möglich ist, die Decodierung zu deaktivieren, meine Angabe
<property name="urlDecode" value="false"/>
... in diesem Fall kann der Empfänger auf die Richtige; aber das wird natürlich viele andere Dinge schwieriger machen.
Das klingt in der Theorie gut, aber scheint nicht zu helfen. Wenn Sie die Dokumente überprüfen, wird die Codierung für den * body * und nicht für den URI erzwungen. –
@Julian: Dies ist eine richtige Lösung (obwohl 'forceEncoding' nicht erforderlich ist), verwendet Spring die Anforderungscodierung zum Auflösen von Pfadvariablen, siehe http://static.springsource.org/spring/docs/3.0.x/javadoc-api /org/springframework/web/util/UrlPathHelper.html (und Sie benötigen diesen Filter auch für POST-Parameter). – axtavt
@axtavt: Oh mein Gott, wer kommt mit solchen Designs? Wie auch immer, ich konnte bestätigen, dass ich tatsächlich UTF-8 bekomme, wenn ich eine HTTP-Anfrage mit einer UTF-8-kodierten Nachricht, wie zB POST, sende. Ich bin * nicht * in der Lage gewesen, den Filter funktionierend wie angekündigt zu bekommen (ich weiß, dass etwas passiert, weil, wenn ich den Klassennamen breche, ich eine ClassNotFoundException erhalte). –