首页 文章

Spring MVC Controller预处理请求体

提问于
浏览
1

我正在研究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 .

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

4 回答

  • 0

    如果你想绑定 typeXtypeY ,那么你肯定需要2个处理程序 . 但是,为什么我们不使用 @RequestMappingparam 选项:

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

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

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

    因此我建议使用统一处理程序,您可以在其中检查必要的参数,然后手动转换为相应的类 . 为了找到必要的类,我想最好使用Strategy pattern

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

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

  • 0

    我认为您应该为两种类型创建一个控制器,并根据 typeXtypeY 调用所需的组件\方法 .

  • 0

    GET不应该有请求机构,或者至少应该有请求机构,the server side isn't required to do anything with them . 正如您所描述的那样,此API不是RESTful .

    假设您不关心这一点,请尝试创建一个控制器方法,该方法接受TypeX和TypeY的父类,或者TypeX和TypeY都实现的接口,使用@SomethingMeaningfulToYou注释它,然后使用web argument method resolver来实例化您想要的子类 .

    虽然这是一个破坏API的黑客攻击 .

  • 5

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

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

相关问题