Java @RequestBody和@RequestParam都不起作用

Java @RequestBody和@RequestParam都不起作用,java,spring,spring-mvc,spring-restcontroller,Java,Spring,Spring Mvc,Spring Restcontroller,我想在春天打个电话 这是我的控制器代码: @RequestMapping(value = "/magic", method = RequestMethod.PUT) TodoDTO magic(@RequestBody String id){ return service.magic(id); } 因为我想在调用中传递一个id字符串 问题是,我收到了这个 { "timestamp": 1486644310464, "status": 500, "er

我想在春天打个电话

这是我的控制器代码:

@RequestMapping(value = "/magic", method = RequestMethod.PUT)
    TodoDTO magic(@RequestBody String id){
        return service.magic(id);
    }
因为我想在调用中传递一个id字符串

问题是,我收到了这个

{
  "timestamp": 1486644310464,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "java.lang.NullPointerException",
  "message": "{\n\t\"id\":\"589c5e322abb5f28631ef2cc\"\n}",
  "path": "/api/todo/magic"
}
如果我这样更改代码:

@RequestMapping(value = "/magic", method = RequestMethod.PUT)
    TodoDTO magic(@RequestParam(value = "id") String id){
        return service.magic(id);
    }
我收到

{
  "timestamp": 1486644539977,
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.web.bind.MissingServletRequestParameterException",
  "message": "Required String parameter 'id' is not present",
  "path": "/api/todo/magic"
}
我也打了同样的电话,一个连接 用身体

{
    "id":"589c5e322abb5f28631ef2cc"
}
这是我数据库中一个对象的id


我的问题是,我怎样才能实现我的目标?如果我在链接中使用@PathVariable传递参数,如api/todo/magic/589c5e322abb5f28631ef2cc,它将起作用

Class Request
{
private String id;
//getter and setter
}
并将方法更改为

@RequestMapping(value = "/magic", method = RequestMethod.PUT)
    TodoDTO magic(@RequestBody Request request){
        return service.magic(request.getId());
    }
您还可以在url中获取id,并在方法签名中使用@Pathvariable

@RequestMapping(value = "/magic/{id}", method = RequestMethod.PUT)
        TodoDTO magic(@PathVariable String id){
            return service.magic(request.getId());
        }

创建自己的自定义类,如下所示

Class Request
{
private String id;
//getter and setter
}
并将方法更改为

@RequestMapping(value = "/magic", method = RequestMethod.PUT)
    TodoDTO magic(@RequestBody Request request){
        return service.magic(request.getId());
    }
您还可以在url中获取id,并在方法签名中使用@Pathvariable

@RequestMapping(value = "/magic/{id}", method = RequestMethod.PUT)
        TodoDTO magic(@PathVariable String id){
            return service.magic(request.getId());
        }

当您使用
@RequestBody String id
时,它只需要一个字符串:

"589c5e322abb5f28631ef2cc"
如果要发送具有
id
字段的对象,如

{
    "id":"589c5e322abb5f28631ef2cc"
}

当您使用
@RequestBody String id
时,您应该创建一个具有
id
字段的类,并修改方法的签名以获取该类,而不是
String

它只需要一个字符串:

"589c5e322abb5f28631ef2cc"
如果要发送具有
id
字段的对象,如

{
    "id":"589c5e322abb5f28631ef2cc"
}

您应该创建一个具有
id
字段的类,并修改方法的签名以获取此类,而不是
String

,同时按照其他答案中的建议创建包装类也可以,我认为可以避免这种开销,只需使用映射即可

@RequestMapping(value = "/magic", method = RequestMethod.PUT)
    TodoDTO magic(@RequestBody Map<String, String> data){
        return service.magic(data.get("id");
}
@RequestMapping(value=“/magic”,method=RequestMethod.PUT)
TodoDTO magic(@RequestBody映射数据){
return service.magic(data.get(“id”);
}

虽然按照其他答案中的建议创建包装器类会起作用,但我认为可以避免这种开销,只需使用映射即可

@RequestMapping(value = "/magic", method = RequestMethod.PUT)
    TodoDTO magic(@RequestBody Map<String, String> data){
        return service.magic(data.get("id");
}
@RequestMapping(value=“/magic”,method=RequestMethod.PUT)
TodoDTO magic(@RequestBody映射数据){
return service.magic(data.get(“id”);
}

“使用@PathVariable,它可以工作”,然后使用它。如果不发送数据,请不要使用
PUT
。@zeroflagL在URL中发送数据不是一种反模式吗?这只是一个测试,这就是不做任何事情方法的原因:)如果您的方法的目的是返回带有或基于某个id的项,那么该id实际上不是数据。如果该id实际上是数据,那么您是对的,它应该作为正文发送。但是根据错误消息,您没有这样做。@zeroflagL那么您对数据的理解是什么?图像?“使用@PathVariable,它可以工作”然后使用它。如果你不发送数据,就不要使用
PUT
。@zeroflagL在URL中发送数据不是一种反模式吗?这只是一个测试,这就是不做任何事情方法的原因:)如果你的方法的目的是返回带有或基于某个id的项目,那么该id实际上不是数据。如果id实际上是数据,那么您是对的,它应该作为正文发送。但是根据错误消息,您没有这样做。@zeroflagL那么您对数据的理解是什么呢?图像?这似乎是最好的选择,因为它不需要额外的类。如果我想要2个参数,只需调用data.get(“foo”)?这似乎是最好的选择,因为它不需要额外的类。如果我想要2个参数,只需调用data.get(“foo”)?如果我有2个参数,只需用逗号分隔它们?不,因为
@RequestBody
代表整个请求体,如果有2个参数,你必须为它们创建一个类(或者你
映射
)。因此此选项仅适用于1个参数。谢谢你的捷径!如果我有两个参数,就用逗号分隔它们?不,因为
@RequestBody
代表整个请求体,如果有两个参数,你必须为它们创建一个类(或者你
映射
)。所以这个选项只适用于一个参数。谢谢你的捷径!在任何情况下,是否应该首选此方法而不是简单的映射?不使用映射的原因:1)建议的解决方案为您提供了对预期输入的类型安全访问,映射强制您使用密钥获取数据,并在可用之前检查类型是否与您预期的相同。2) 对于阅读代码的其他开发人员也很清楚。3) 它允许自动生成API文档(使用spring fox)。4) 如果配置正确,Jackson mapper可以在用户使用不正确的请求值时向用户发出警告,同时映射接受来自主体的任何属性。5) 如果你有嵌套的JSON结构,你最终会得到映射中的映射(甚至转换错误)。有没有任何情况下应该优先使用它而不是简单的映射?不使用映射的原因:1)建议的解决方案为你提供了对预期输入的类型安全访问,映射强制您使用键获取数据,并在可用之前检查类型是否符合预期。2) 对于阅读代码的其他开发人员也很清楚。3) 它允许自动生成API文档(使用spring fox)。4) 如果配置正确,Jackson mapper可以在用户使用不正确的请求值时向用户发出警告,同时映射接受来自主体的任何属性。5) 如果您有嵌套的JSON结构,那么最终会出现映射中的映射(甚至转换错误)。