باستخدام Spring's REquestBody وقراءة httpservletrequest.getInputStream () بعد ذلك)
-
28-09-2019 - |
سؤال
أقوم بتخطيط بيانات نشر 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 الوسيط (عادةً ما يكون البايت [] ، لكن السلسلة تعمل أيضًا) وربط يدويًا من ذلك إلى كائن ، باستخدام موثق البيانات الأساسي (جاكسون). غالبًا ما أقوم بذلك لأتمكن من تخصيص معالجة الأخطاء بالكامل لربط البيانات.