web-dev-qa-db-ja.com

Spring / Rest @PathVariable文字エンコーディング

私が使用している環境(Tomcat 6)では、パスセグメント内のパーセントシーケンスは、@ PathVariableにマップされるときにISO-8859-1を使用して明らかにデコードされます。

それをUTF-8にしたいのですが。

TomcatでUTF-8を使用するように構成しました(server.xmlのURIEncoding属性を使用)。

Spring/Restは独自にデコードを行っていますか?はいの場合、デフォルトのエンコーディングをどこでオーバーライドできますか?

追加情報;これが私のテストコードです:

@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 );
}

次のURIパスを使用してHTTP GETリクエストを実行すると、

/TEST/enc/%c2%a3%20and%20%e2%82%ac%20rates

これは、UTF-8でエンコードされ、次にパーセントでエンコードされた形式です。

/TEST/enc/£ and € rates

私が得る出力は:

      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

これは、Tomcat(URIEncoding属性を設定した後)が正しいこと(getPathInfo()を参照)を実行することを示していますが、パス変数はISO-8859-1でデコードされます。

そして答えは

Spring/Restは明らかにリクエストエンコーディングを使用しますが、これはURIではなくbodyに関するものであるため、実行するのは非常に奇妙です。はぁ。

これを追加:

<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>

問題を修正しました。本当にもっとシンプルなはずです。

そして実際には、それはさらに悪い:

メソッドが実際にhasリクエスト本文であり、その本文がUTF-8でエンコードされていない場合は、追加のforceEncodingパラメータが必要です。これは機能するようですが、後でさらに問題が発生するのではないかと心配しています。

別のアプローチ

それまでの間、デコードを無効にすることが可能であることがわかりました。

<property name="urlDecode" value="false"/>

...その場合、受信者は正しいことにアクセスできます。もちろん、これは他の多くのことを難しくします。

26
Julian Reschke

フィルターをweb.xmlに追加する必要があること

<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>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
27
Hurda

パス変数は、文字エンコーディングフィルターを使用しても、ISO-8859-1でデコードされます。これを回避するために私がしなければならなかったことはここにあります。他にアイデアがあれば教えてください!

サーバー上で実際にUTF-8でデコードされた文字を確認するには、これを実行して値を確認します(「HttpServletRequest httpServletRequest」をコントローラーパラメーターに追加する必要があります)。

String requestURI = httpServletRequest.getRequestURI();
String decodedURI = URLDecoder.decode(requestURI, "UTF-8");

その後、サーバーに適切なデコード済みデータを取得したので、(デコードされたURIから手動でパラメーターを取得するなど)何でも好きなことができます。

4
11101101b

Server.xmlでTomcatのコネクタを設定してみてください。追加 useBodyEncodingForURI="true"またはURIEncoding="UTF-8"をConnectorタグに追加します。例えば:

    <Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           useBodyEncodingForURI="true"
           redirectPort="8443" />
3