我有一个控制器,它有一个使用泛型的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; } }有没有办法可以做到这一点?
I have a controller that has a Command Object that uses generics like so:
@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 } }However, this does not work. I'm assuming it does not working because of Type Erasure in Java. Is there a way I can have the Command Object use a generic? Here is what some of the other classes might look like.
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 }The error I get:
java.lang.Object cannot be cast to com.test.MyStringObject
Of course if I change my RequestDTO to only use a MyStringObject it works fine.
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; } }Is there a way this can be done?
最满意答案
你是对的,这是因为类型擦除。
可能最简单的解决方案是创建一个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"}}%You are correct, it is because of type erasure.
Probably the simplest solution is to create a RequestDTO subclasses parameterized with each of your My*Object and use it as a Command Object class.
Given your example:
@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 } }Then it works fine:
$ 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"}}%更多推荐
发布评论