【问题标题】:neither @RequestBody nor @RequestParam work@RequestBody 和 @RequestParam 都不起作用
【发布时间】:2017-02-09 12:50:51
【问题描述】:

我想在春天进行 PUT 调用。

这是我的控制器代码:

@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"
}

我打了同样的电话,链接http://localhost:8080/api/todo/magic上的一个PUT 与身体

{
    "id":"589c5e322abb5f28631ef2cc"
}

这是我的数据库中一个对象的 id。

我的问题是,我怎样才能实现我的目标?如果我通过链接中的参数,例如 api/todo/magic/589c5e322abb5f28631ef2cc,使用@PathVariable,它可以工作

【问题讨论】:

  • “用@PathVariable,它可以工作” 然后使用它。如果不发送数据,请不要使用PUT
  • @zeroflagL 在 URL 中发送数据不是反模式吗?这只是一个测试,这就是什么都不做的方法的原因:)
  • 如果您的方法的目的是返回带有或基于某个 id 的项目,那么 id 不是真正的数据。如果 id 实际上是数据,那么你是对的,它应该作为正文发送。但根据错误消息,您没有这样做。
  • @zeroflagL 那么你对数据的理解是什么?图片?

标签: java spring spring-mvc spring-restcontroller


【解决方案1】:

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

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());
        }

【讨论】:

  • 在任何情况下应该首选它而不是简单的地图?
  • not 使用映射的原因:1) 建议的解决方案为您提供对预期输入的类型安全访问,映射强制您使用键并在可用之前检查类型是否符合您的期望。 2)对于阅读代码的其他开发人员也很清楚。 3) 它允许自动生成 API 文档(使用 spring fox)。 4) 如果配置正确,Jackson 映射器可以在用户使用不正确的请求值时警告用户,而地图接受来自正文的任何​​属性。 5) 如果你有嵌套的 JSON 结构,你最终会得到地图中的地图(甚至是转换错误)。
【解决方案2】:

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

"589c5e322abb5f28631ef2cc"

如果您想发送带有id 字段的对象

{
    "id":"589c5e322abb5f28631ef2cc"
}

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

【讨论】:

  • 如果我有 2 个参数,只需用逗号分隔它们?
  • 不,因为@RequestBody代表整个请求体,如果有2个参数,你必须为它们创建一个类(或者你Map)。
  • 所以这个选项只适用于 1 个参数。谢谢你的快捷方式!
【解决方案3】:

虽然按照其他答案中的建议创建包装类会起作用,但我认为可以避免这种开销并简单地使用 Map。

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

【讨论】:

  • 这似乎是最好的选择,因为它不需要额外的类。如果我想要 2 个参数,只需调用 data.get("foo")?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多