danach unter Verwendung von Spring @RequestBody und Lese HttpServletRequest.getInputStream ()
-
28-09-2019 - |
Frage
Ich bin Abbilden meines Wunsches des JSON POST-Daten in ein Objekt mit Spring @RequestBody
Annotation und MappingJacksonHttpMessageConverter
. Doch nach, dass ich mag die Daten in String
Form lesen einige zusätzliche Authentifizierung zu tun. Aber wenn die Rangierung geschehen ist, ist die InputStream
in HttpServletRequest
leer. Sobald ich das Lesen von POST-Daten in ein @RequestBody
Werke String
Parameter aus dem Verfahren entfernen, wie erwartet.
Muss ich Kompromisse eingehen müssen, indem die @RequestBody
Aufgeben und dabei die Bindung irgendwie manuell oder ist es eine elegantere Lösung?
Lösung
Also, im Grunde benötigen Sie einen Hash-Wert des Anforderungstext zu berechnen. Die elegante Art und Weise, es zu tun ist, einen Dekorateur zum InputStream
anzuwenden.
Zum Beispiel in einer Handler-Methode (in diesem Fall können Sie nicht @RequestBody
und Bedarf verwenden HttpMessageConverter
manuell erstellen):
@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();
...
}
wobei hash inkrementell in überschriebenen read
Methoden der HashingInputStreamDecorator
berechnet wird.
Sie können auch @RequestBody
verwenden, wenn Sie einen Filter
erstellen Sie den Dekorateur anzuwenden. In diesem Fall kann die decorator berechnete Hash zu der Handler-Methode als Anforderungs Attribut übergeben. Allerdings müssen Sie diese Filter zur Karte sorgfältig sie gelten nur für die Anfragen an bestimmten Behandlungsmethode.
Andere Tipps
In Ihrem UrlMapping bean können Sie die Liste zusätzlicher Abfangjäger deklarieren:
<bean id="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="org.foo.MyAuthInterceptor"/>
</list>
</property>
</bean>
Diese Abfangjäger haben Zugriff auf HttpServletRequest, obwohl, wenn Sie aus dem Stream lesen die Chancen, dass Parameter Mapper sind nicht in der Lage sein, es zu lesen.
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) {
...
}
}
Wenn ich das richtig verstehe, eine gemeinsame Art und Weise verwendet, um mit JAX-RS (die Spring MVC in Bezug auf verbindliche Anfragen ein wenig ähnlich ist) ist zum ersten „bind“ in einem Zwischen roh Typ (in der Regel byte [], aber String funktioniert auch) und manuell von dem Objekt zu binden, zu Grunde liegende Daten Bindemittel (Jackson) verwendet wird. Ich oft tue dies der Lage sein, voll Bindungsfehlerbehandlung von Daten anpassen.