باستخدام Spring's REquestBody وقراءة httpservletrequest.getInputStream () بعد ذلك)

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

سؤال

أقوم بتخطيط بيانات نشر JSON الخاصة بطلبي في كائن باستخدام الربيع @RequestBody التعليقات التوضيحية و MappingJacksonHttpMessageConverter. ولكن بعد ذلك أود قراءة البيانات في String شكل للقيام ببعض المصادقة الإضافية. ولكن عندما حدث الحشد ، InputStream في HttpServletRequest فارغ. بمجرد إزالة @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 لتطبيق الديكور. في هذه الحالة ، يمكن للديكور تمرير التجزئة المحسوبة إلى طريقة المعالج كسمات طلب. ومع ذلك ، تحتاج إلى تعيين هذا المرشح بعناية لتطبيقه فقط على الطلبات على طريقة معالج محددة.

نصائح أخرى

في حبة urlmapping الخاصة بك ، يمكنك إعلان قائمة المعترضات الإضافية:

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

يمكن لهذه التقاطعات الوصول إلى httpservletrequest ، على الرغم من أنك إذا قرأت من الدفق ، فإن الفرص هي أن Mapper المعلمة لن تتمكن من قراءتها.

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 (والتي تشبه إلى حد ما MVC Spring فيما يتعلق بطلبات الربط) هي "الربط" أولاً في نوع RAW الوسيط (عادةً ما يكون البايت [] ، لكن السلسلة تعمل أيضًا) وربط يدويًا من ذلك إلى كائن ، باستخدام موثق البيانات الأساسي (جاكسون). غالبًا ما أقوم بذلك لأتمكن من تخصيص معالجة الأخطاء بالكامل لربط البيانات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top