当前位置: 首页 > 知识库问答 >
问题:

在Spring Boot控制器中验证HTTP POST请求中的请求体是否为空

梁丘逸仙
2023-03-14

我正在替换Spring Boot REST控制器中对POST请求输入的手动验证。JSR-303 Spring Bean验证用于验证请求主体中的实例变量,这是预期的工作。什么是建议的方法来验证请求主体中的对象不是null?

我试过:

>

用@NotNull注释整个类

我正在替换:

@PostMapping...
public ResponseEntity<Map<String, Object>> editFoo(
@RequestBody Foo foo, ...) {
   if(foo == null) {
      return (new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST));
   }
}

与Bean验证等效:

@PostMapping...
public ResponseEntity<Map<String, Object>> editFoo(
@Valid @RequestBody Foo foo, ...) {
   ...
}

我尝试通过以下方式对控制器方法进行单元测试:

// Arrange
    Foo foo = null;
    String requestBody = objectMapper.writeValueAsString(foo);

    // Act + assert
    mockMvc
    .perform(
    post("/end_point")
    .contentType("application/json")
    .content(requestBody))
    .andExpect(status().isBadRequest());

我希望MethodArgumentNotValidException由@ControllerAdvice处理此异常,但在执行单元测试时,我得到了HttpMessageEndableException。我的问题是:

  1. 是否需要测试请求主体是否为空
  2. 如果1。如果是真的,那么应该如何通过Bean验证来实现呢

共有1个答案

胡弘毅
2023-03-14

查看代码时,您已经检查了主体是否为空。实际上,@RequestBody有一个默认参数required,默认为true。所以不需要进行Bean验证!

你的主要问题似乎在你的测试中。首先,编写一个测试来验证null上的endpoint行为是很好的。

然而,在你的测试中,你不能通过null。您尝试使用objectMappernull值创建Json对象。您正在编写的对象似乎不是有效的json。因此,当您发送此正文时,Spring表示它无法读取消息,也就是您请求的正文,正如您所说,它是一个应用程序/json内容,但其中没有json。

要测试空正文,只需在测试中发送请求,只需删除。内容(requestBody)行,它应该可以工作!

---编辑1我以为它是因为身体而拒绝了信息,但事实上它似乎马上就对我起作用了。这是我的控制器和测试,您可以将其与完整代码进行比较:

@RestController()
@RequestMapping("end_point")
public class TestController {

    @PostMapping
    public ResponseEntity<Map<String, Object>> editFoo(@RequestBody Foo foo) {
       // if(foo == null) {
       //     return (new ResponseEntity<>(new HashMap<>(), HttpStatus.BAD_REQUEST));
       // }

        return (new ResponseEntity<>(new HashMap<>(), HttpStatus.OK));
    }
}


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class TestControllerTest {
    @Autowired
    private MockMvc mvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void test_body_is_null() throws Exception {

        Foo foo = null;
        String requestBody = objectMapper.writeValueAsString(foo);

        // Act + assert
        mvc
            .perform(
                post("/end_point")
                    .contentType("application/json")
                    .content(requestBody))
            .andExpect(status().isBadRequest());
    }
}

这是使用Spring Boot 2.1.6制作的。发布

---为记录编辑2如果您想在此处使用null验证,请参阅控制器的一个片段:

@RestController()
@RequestMapping("end_point")
@Validated
public class TestController {

    @PostMapping
    public ResponseEntity<Map<String, Object>> editFoo(@NotNull @RequestBody(required = false) Foo foo) {

        return (new ResponseEntity<>(new HashMap<>(), HttpStatus.OK));
    }
}

首先,必须将主体的required设置为false,因为默认值为true。然后,您必须在请求主体上添加@NotNull注释,并在控制器上添加@Validated。在这里,如果启动测试,您将看到请求失败,原因是:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ConstraintViolationException: editFoo.foo: must not be null

正如你所说的,你有一个@ControlllerAdtions,然后你可以按照你的意愿映射异常!

 类似资料:
  • 我正在使用Java和Spring构建一个RESTAPI,我需要在我的控制器中处理一个POST请求,但我需要从该请求中提取主体,它是一个JSON,也是该请求的“来源”, 我有几个问题:首先是如何获取该请求的来源(我猜是在标题中移动的url?),是否有与@RequestBody类似的注释?。 我的第二个问题是,在这种post方法中,通常应该返回什么对象作为响应。

  • 在我的控制器中,我有一个用以下映射映射的方法:@PostMapping(“/”)。 此方法需要一个我试图捕获的请求主体,如下所述: 使用这两种方法对我来说都很好,我只是进退两难,如果直接在实体类中接受请求体是一个好主意和最佳实践的话。 我不想在controller类中公开我的实体类,因为我不确定这是否是一个好主意。 java 这两种方法都给出了相同的结果,更多的是关注要遵循的最佳实践。

  • 对传递的 URL 发出一个 POST 请求。 使用 XMLHttpRequest web api 对给定的url 发出一个 post 请求。 用 setRequestHeader 方法设置 HTTP 请求头的值。 通过调用给定的 callback 和 responseText 来处理 onload 事件。 通过运行提供的 err 函数,处理onerror事件。 省略第三个参数 data ,不发送数

  • 问题内容: 我正在开发一个使用大量ajax的grails应用程序。如果请求是ajax调用,那么它应该给出响应(这部分正在工作),但是如果我在浏览器中输入URL,它应该带我到主页/索引页面而不是请求的页面。下面是Ajax调用的示例gsp代码。 如果我们在浏览器URL栏中键入http:// localhost:8080 / Dash / todo / list ,则控制器应重定向到http:// lo

  • 我需要实现一个接受对象(json)的postendpoint。但对象中的某些参数是可选的。所以,当我尝试进行api调用时,它并没有映射到相应的方法。 显示页面未找到Err: 404 我发送的请求正文只包含两个字段,其余的都是可选的。 对象的Pojo Spring控制器: 卷曲命令: 有效载荷 } Rest控制器:

  • 我试图在提供者端运行一个PACT测试,但我不知道如何操作从PACT文件中获得的请求体。我需要这样做,因为我必须使用来自State Step的id。 此外,更复杂的是,我的主体是一个XML。下面是我的协议请求的样子: 正如我所说的,在Provider状态下,我将有一个请求,并且这个请求的响应将是让我们说'Mary'。所以我的问题是,在执行验证测试时,如何将协议请求体中的“Jane”替换为“Mary”