Java 具有泛型的命令对象
我有一个控制器,它有一个Java 具有泛型的命令对象,java,spring,spring-mvc,Java,Spring,Spring Mvc,我有一个控制器,它有一个命令对象,它使用以下泛型: @Controller @RequestMapping(value = "/first") public class MyFirstController { @RequestMapping(value = "/something", method = RequestMethod.POST) @ResponseBody public ADifferentDTO doSomething(RequestDTO<MySt
命令对象
,它使用以下泛型:
@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
}
}
有什么方法可以做到这一点吗?你是对的,这是因为类型擦除 可能最简单的解决方案是创建一个RequestDTO子类,用每个My*对象参数化,并将其用作命令对象类 举个例子:
@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
}
}
您的控制器如何知道如何根据从客户端传递的内容构造RequestDTO?如果您看到的是编译器错误,则不涉及类型擦除。@LewBloch这是一个运行时error@MinhKieu它不知道如何构造它,因为传入的不是
MyStringObject
。哇,我有点惊讶,竟然这么容易!非常感谢。快速提问,我不明白的是扩展参数化类的类如何修复类型擦除问题。因此,MyStringRequestDTO
被认为是一个MyStringObject,即使“extends RequestDTO”在运行时不会被解析为MyStringObject?很快,这是编译器在.class
文件中存储类型信息的一种方式,因为我们声明T=MyStringObject,所以它在运行时可用。尝试运行以下代码段System.out.println(MyStringRequestDTO.class.getGenericSuperclass().getTypeName());System.out.println(新RequestDTO().getClass().getGenericSuperclass().getTypeName())您将看到输出中存在实际类型。查看类文件中存储的内容的另一种方法是使用javap命令将类文件传递给它。例如,上面的示例类似于公共类com.stackoverflow.so44423504.MyStringRequestDTO扩展com.stackoverflow.so44423504.RequestDTO
保留所有类型信息。
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;
}
}
@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"}}%