Spring MVC Controller预处理请求体

R P*_*R P 1 java spring spring-mvc request

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

在请求体中的session_type的基础上,我必须将请求映射到特定的POJO(JSON - > JAVA POJO).

例如,如果请求正文中的"session_type"为"typeX",则请求应映射到ClassX POJO.如果请求正文中的"session_type"为"typeY",则请求应映射到ClassY POJO.

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

n1c*_*las 5

如果你要绑定typeX和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
}
Run Code Online (Sandbox Code Playgroud)

如果你需要一些准备工作(fe规范化params或手动执行模型绑定),那么你上面的方法可能会合并@InitBinder,但请注意,这@InitBinder需要精确的ULR规则以及@ModelAttribute处理程序中的参数.

编辑:在Spring MVC中,没有可能使用2个处理程序来确定URL,即当method/URL/params/consume类型相同时.

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

//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
Run Code Online (Sandbox Code Playgroud)

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