Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有泛型的命令对象_Java_Spring_Spring Mvc - Fatal编程技术网

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())公共类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"}}%