具有泛型的命令对象

时间:2017-06-07 22:01:58

标签: java spring spring-mvc

我有一个Command Object的控制器,它使用泛型,如下所示:

@Controller
@RequestMapping(value = "/first")
public class MyFirstController {

    @RequestMapping(value = "/something", method = RequestMethod.POST)
    @ResponseBody
    public ADifferentDTO doSomething(RequestDTO<MyStringObject> requestDTO, HttpServletRequest request,
            HttpServletResponse response) {

            requestDTO.getSomeObject(); // ERROR HERE


            //.. do something
    }
}

然而,这不起作用。我认为它因Java中的Type Erasure而无法正常工作。有没有办法让Command对象使用泛型? 以下是其他一些类的内容。

public class RequestDTO<T> {

    private T someObject;
    // some other objects here as well that are from a submitted form (not listed)


    public void setSomeObject(T someObject){
        this.someObject = someObject;
    }

    public T getSomeObject(){
        return someObject;
    }
}

public class MyStringObject {
    private String someString;

    public MyStringObject(String someString){
        this.someString = someString;
    }
    // getter and setter
}


public class MyIntegerObject {
    private Integer someInteger;
    private Integer anotherInteger;

    public MyIntegerObject(Integer someInteger, Integer anotherInteger){
        this.someInteger = someInteger;
        this.anotherInteger = anotherInteger;
    }
    // getter and setter
}

我得到的错误:

java.lang.Object cannot be cast to com.test.MyStringObject

当然,如果我将RequestDTO更改为仅使用MyStringObject,则可以正常使用。

public class RequestDTO {

    private MyStringObject someObject;
    // some other objects here as well that are from a submitted form (not listed)


    public void setSomeObject(MyStringObject someObject){
        this.someObject = someObject;
    }

    public MyStringObject getSomeObject(){
        return someObject;
    }
}

有没有办法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

你是对的,这是因为类型擦除。

可能最简单的解决方案是创建一个RequestDTO子类,使用每个My * Object参数化,并将其用作命令对象类。

鉴于你的例子:

@SpringBootApplication
public class So44423504Application {

    public static void main(String[] args) {
        SpringApplication.run(So44423504Application.class, args);
    }

    @RestController
    @RequestMapping(value = "/first")
    public static class MyFirstController {

        public static class MyStringRequestDTO extends RequestDTO<MyStringObject> {}

        public static class MyIntegerRequestDTO extends RequestDTO<MyIntegerObject> {}

        @PostMapping(value = "/something")
        public String doSomething(@ModelAttribute MyStringRequestDTO/*MyIntegerRequestDTO*/ requestDTO) throws JsonProcessingException {
            return new ObjectMapper().writeValueAsString(requestDTO);
        }
    }

    public static class RequestDTO<T> {
        private T someObject;
        // getter and setter
    }

    public static class MyStringObject {
        private String someString;

        public MyStringObject() { } // required since another non-default ctor is present.

        public MyStringObject(String someString){
            this.someString = someString;
        }

        // getter and setter
    }

    public static class MyIntegerObject {
        private Integer someInteger;
        private Integer anotherInteger;

        public MyIntegerObject() { } // required since another non-default ctor is present.

        public MyIntegerObject(Integer someInteger, Integer anotherInteger){
            this.someInteger = someInteger;
            this.anotherInteger = anotherInteger;
        }
        // getters and setters
    }
}

然后它工作正常:

$ curl -XPOST 'localhost:8080/first/something?someObject.someInteger=23&someObject.anotherInteger=42'
{"someObject":{"someInteger":23,"anotherInteger":42}}%

$ curl -XPOST 'localhost:8080/first/something?someObject.someString=test'                            
{"someObject":{"someString":"test"}}%