[英]Spring MVC Controller pre process request body
I am working on spring REST APIs. 我正在研究Spring REST API。 In requirements, there are 2 POST requests with same URL but different request body. 在需求中,有2个POST请求具有相同的URL,但请求主体不同。 Since Spring MVC must have unique mappings across controller, I have to pre-process the request body to map to a specific POJO. 由于Spring MVC必须跨控制器具有唯一的映射,因此我必须预处理请求主体以映射到特定的POJO。
On the basis of session_type in request body, I have to map the request to specific POJO (JSON -> JAVA POJO). 根据请求正文中的session_type,我必须将请求映射到特定的POJO(JSON-> JAVA POJO)。
For example, if 'session_type' in request body is 'typeX' then the request should map to ClassX POJO. 例如,如果请求正文中的“ session_type”为“ typeX”,则请求应映射到ClassX POJO。 If 'session_type' in request body is 'typeY' then the request should map to ClassY POJO. 如果请求正文中的“ session_type”为“ typeY”,则请求应映射到ClassY POJO。
If there a way to do it using some kind of requestbody annotation? 是否可以使用某种requestbody注释来做到这一点?
If you want to bind typeX
and typeY
, then you definitely need 2 handlers. 如果要绑定typeX
和typeY
,则肯定需要2个处理程序。 But, why wouldn't we use param
option of @RequestMapping
: 但是,为什么我们不使用@RequestMapping
param
选项:
@RequestMapping(method = RequestMethod.POST,
value = "/url", params = "session_type=typeX")
public String handleTypeX(@RequestBody @ModelAttribute TypeX typeX){
//TODO implement
}
@RequestMapping(method = RequestMethod.POST,
value = "/url", params = "session_type=typeY")
public String handleTypeY(@RequestBody @ModelAttribute TypeY typeY){
//TODO implement
}
If you need some preparations (fe normalize params or perform model binding manually), then the approach above you may combine along with @InitBinder
, but please note, that @InitBinder
needs exact ULR's rules along with @ModelAttribute
parameters in handlers. 如果您需要一些准备工作(例如,规范化参数或手动执行模型绑定),则可以将上述方法与@InitBinder
结合使用,但请注意, @InitBinder
需要确切的@InitBinder
规则以及处理程序中的@ModelAttribute
参数。
EDIT : In Spring MVC there is no possibility to use 2 handlers for exact URL , ie when method/URL/params/consumes type are the same. 编辑 :在Spring MVC中,不可能使用2个用于确切URL的处理程序,即,当method / URL / params / consumes类型相同时。
Thus I suggest use unified handler, where you would check necessary parameter and then manually convert into corresponding class. 因此,我建议使用统一处理程序,在该程序中您将检查必要的参数,然后手动将其转换为相应的类。 For finding necessary class I suppose it would be better to use Strategy pattern : 为了找到必要的课程,我想最好使用Strategy模式 :
//class resolver according "session_type" parameter
//note, that you can use Spring autowiring capabilities
private final Map<String, Class> TYPES_CONTEXT = new HashMap<String, Class>(){
{
this.put("x", TypeX.class);
this.put("y", TypeY.class);
//TODO probably other classes
}
}
@RequestMapping(method = RequestMethod.POST,
value = "/url")
public @ResponseBody String handleAnyType(@RequestBody Map<String, String> body){
String sessionType = body.get("session_type");
//TODO handle case if sessionType is NULL
Class convertedClass = TYPES_CONTEXT.get(sessionType);
//TODO handle case if class is not found
Object actualObject = objectMapper.convertValue(body, convertedClass);
//now we use reflection for actual handlers, but you may refactor this in the way you want, f.e. again with Strategy pattern
//note that current approach there should be contract for methods names
Method actualHandler = this.getClass().getMethod("handle" + actualObject.getClass().getSimpleName());
return (String)actualHandler.invoke(this, actualObject);
}
public String handleTypeX(TypeX typeX){
//TODO implement
}
public String handleTypeY(TypeY typeY){
//TODO implement
}
//TODO probably other methods
This approach doesn't handle validation and some things were omitted, but I believe this might be helpful. 这种方法无法处理验证,因此省略了一些内容,但我认为这可能会有所帮助。
我认为您应该使用两种类型的一种方法创建控制器,并根据typeX
或typeY
在其中调用所需的component \\ method。
GETs shouldn't have request bodies, or at least if they do, the server side isn't required to do anything with them . GET不应具有请求主体,或者至少具有请求主体, 服务器端无需对其进行任何处理 。 As you describe it, this API isn't RESTful. 正如您描述的那样,该API不是RESTful的。
Assuming you don't care about that, try creating a controller method that takes a parent class of TypeX and TypeY, or interface that both TypeX and TypeY implement, annotate it with @SomethingMeaningfulToYou, then use a web argument method resolver to instantiate the child class you want. 假设您对此不关心,请尝试创建一个采用TypeX和TypeY父类的控制器方法,或者使用TypeX和TypeY都实现的接口,然后使用@SomethingMeaningfulToYou对其进行注释,然后使用网络参数方法解析器实例化该子级。你想要的课。
It's a hack around a broken API though. 不过,这是围绕损坏的API的黑客。
there are 2 POST requests with same URL but different request body 有2个POST请求具有相同的URL,但请求正文不同
For a RESTful interface, the same URL should always indicate the same resource . 对于RESTful接口,相同的URL应始终指示相同的资源 。 The body of a request may contain different representations of that resource. 请求的正文可能包含该资源的不同表示形式 。 You could create different HttpMessageContverter
classes for the two different kinds of representation. 您可以为两种不同的表示形式创建不同的HttpMessageContverter
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.