1

我正在研究 Spring REST API。在需求中,有 2 个具有相同 URL 但请求正文不同的 POST 请求。由于 Spring MVC 必须具有跨控制器的唯一映射,因此我必须预处理请求主体以映射到特定的 POJO。

根据请求正文中的 session_type,我必须将请求映射到特定的 POJO(JSON -> JAVA POJO)。

例如,如果请求正文中的“session_type”是“typeX”,那么请求应该映射到 ClassX POJO。如果请求正文中的“session_type”是“typeY”,则请求应映射到 ClassY POJO。

如果有办法使用某种 requestbody 注释来做到这一点?

4

4 回答 4

5

如果你想绑定typeXand typeY,那么你肯定需要 2 个处理程序。但是,我们为什么不使用以下param选项@RequestMapping

@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
}

如果您需要一些准备工作(fe 规范化参数或手动执行模型绑定),那么您可以将上述方法与 结合使用@InitBinder,但请注意,这@InitBinder需要精确的 ULR 规则以及@ModelAttribute处理程序中的参数。

编辑:在 Spring MVC 中,不可能对确切的 URL使用 2 个处理程序,即当 method/URL/params/consumes 类型相同时。

因此我建议使用统一处理程序,您可以在其中检查必要的参数,然后手动转换为相应的类。为了找到必要的课程,我认为使用策略模式会更好:

//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

这种方法不处理验证,有些东西被省略了,但我相信这可能会有所帮助。

于 2013-03-13T21:07:39.690 回答
0

我认为您应该为两种类型创建一种方法,并根据typeXor调用所需的组件\方法typeY

于 2013-03-13T20:58:47.013 回答
0

有 2 个具有相同 URL 但请求正文不同的 POST 请求

对于 RESTful 接口,相同的 URL 应始终指示相同的资源。请求的主体可能包含该资源的不同表示HttpMessageContverter您可以为两种不同的表示创建不同的类。

于 2013-05-23T15:51:52.080 回答
0

GET 不应该有请求主体,或者至少如果有,服务器端不需要对它们做任何事情。正如您所描述的,此 API 不是 RESTful。

假设您不关心这一点,请尝试创建一个控制器方法,该方法采用 TypeX 和 TypeY 的父类,或者 TypeX 和 TypeY 都实现的接口,使用 @SomethingMeaningfulToYou 对其进行注释,然后使用Web 参数方法解析器来实例化子类你想要的课。

不过,这是对损坏的 API 的一种破解。

于 2013-03-13T21:37:28.713 回答