Springの@RequestBodyを使用して、httpservletrequest.getInputStream()を読んでいます

StackOverflow https://stackoverflow.com/questions/4097012

質問

私は私のリクエストのJSONの投稿データをSpringを使用してオブジェクトにマッピングします @RequestBody 注釈と MappingJacksonHttpMessageConverter. 。しかしその後、私はでデータを読みたいです String 追加の認証を行うためのフォーム。しかし、マーシャリングが起こったとき、 InputStreamHttpServletRequest 空です。削除したら @RequestBody メソッドからのパラメーターポストデータの読み取り値への読み取り String 期待どおりに機能します。

あきらめることで妥協する必要がありますか @RequestBody そして、何らかの方法でバインディングをしているのですか、それともよりエレガントな解決策はありますか?

役に立ちましたか?

解決

したがって、基本的には、リクエスト本体のハッシュを計算する必要があります。それを行うためのエレガントな方法は、デコレーターをに適用することです InputStream.

たとえば、ハンドラー方法内(この場合は使用できません @RequestBody そして、作成する必要があります HttpMessageConverter 手動で):

@RequestMapping(...)
public void handle(HttpServletRequest request) throws IOException {
    final HashingInputStreamDecorator d = 
        new HashingInputStreamDecorator(request.getInputStream(), secretKey);
    HttpServletRequest wrapper = new HttpServletRequestWrapper(request) {
        @Override
        public ServletInputStream getInputStream() throws IOException {
            return d;
        }
    };

    HttpMessageConverter conv = ...;
    Foo requestBody = (Foo) conv.read(Foo.class, new ServletServerHttpRequest(wrapper));
    String hash = d.getHash();

    ...
}

ここで、ハッシュはオーバーライデンで徐々に計算されます read の方法 HashingInputStreamDecorator.

使用することもできます @RequestBody あなたが作成する場合 Filter デコレーターを適用します。この場合、デコレーターは、計算されたハッシュをリクエスト属性としてハンドラーメソッドに渡すことができます。ただし、このフィルターを慎重にマッピングして、特定のハンドラーメソッドにリクエストにのみ適用する必要があります。

他のヒント

URLマッピングBeanでは、追加のインターセプターのリストを宣言できます。

  <bean id="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
      <list>
        <bean class="org.foo.MyAuthInterceptor"/>
      </list>
    </property>
  </bean>

これらのインターセプターはhttpservletrequestにアクセスできますが、ストリームから読んだ場合、パラメーターマッパーが読み取れない可能性があります。

public class AuthInterceptor extends HandlerInterceptorAdapter {

  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    ...
  }

  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) {
    ...
  }
}

これを正しく理解している場合、JAX-RSで使用される1つの一般的な方法(これは、バインディングリクエストに関してスプリングMVCに多少似ています)は、最初に中間生タイプに「バインド」することです(通常はバイト[]が、文字列も機能します) 、そしてそれから手動でバインドし、基礎となるデータバインダー(Jackson)を使用します。データバインディングのエラー処理を完全にカスタマイズできるように、これを行うことがよくあります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top