SpringBoot 2.7.1:RestController缺请求参数仍返回200状态码
问题解析:SpringBoot接口返回200但响应体含500错误信息
问题场景
有如下正常运行的SpringBoot控制器及测试用例,测试断言200响应可正常通过:
控制器代码
@GetMapping("/payment/list") public ResponseEntity<?> getPaymentList(@RequestParam(value = "pageNum") Integer pageNum, @RequestParam(value = "pageSize") Integer pageSize, @RequestParam(value = "accountId") String accountId, @RequestParam(value = "sortParam") Integer sortParam) { PageableResult<PaymentDTO> paymentList = paymentService.getPaymentList(pageNum, pageSize, accountId, sortParam); return ResponseEntity.ok().body(paymentList); }
测试用例
@Test public void testfindAll() throws Exception { //Given Integer pageNum = 1; Integer pageSize = 5; String accountId = "testaccountId"; Integer sortParam = 2; PageableResult<PaymentDTO> result = gettestResult(); //when Mockito.when(paymentService.getPaymentList(pageNum, pageSize, accountId, sortParam)).thenReturn(result); //Then mockMvc.perform(MockMvcRequestBuilders .get("/payment/list") .param("pageNum", pageNum.toString()) .param("pageSize", pageSize.toString()) .param("accountId", accountId) .param("sortParam", sortParam.toString()) ).andDo(print()) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); }
但在测试中注释掉pageSize参数后,控制台日志显示MissingServletRequestParameterException错误,但测试仍通过,且接口返回状态码为200,响应体中包含500错误信息。
控制台错误日志:
2022-12-05 14:51:45.285[HW0015904][Test worker][ERROR][GlobalControllerExceptionHandler] - unexpected-error: request uri: [{E}/payment/list{/E}] exception: org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'pageSize' for method parameter type Integer is not present at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValueInternal(RequestParamMethodArgumentResolver.java:218) at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:193) at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:114) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) MockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:"application/json"] Content type = application/json Body = {"status":false,"errorCode":500,"errorMessage":"Internal Error!","result":null} Forwarded URL = null Redirected URL = null Cookies = []
原因分析
MissingServletRequestParameterException是Spring发现必填请求参数缺失时抛出的标准异常,默认应该返回400 Bad Request状态码。- 项目中存在全局异常处理器
GlobalControllerExceptionHandler,它捕获了该异常,但处理逻辑存在问题:没有为这类客户端参数错误设置正确的HTTP状态码,而是默认返回200,同时在自定义响应体中填入了500的错误码和通用提示。 - 测试用例仅断言了
status().isOk(),并未校验响应体的错误内容,所以即使返回错误响应,测试依然会通过。
解决方案
1. 修正全局异常处理器
针对MissingServletRequestParameterException这类客户端参数错误,返回对应的400状态码,同时优化错误提示的准确性:
@RestControllerAdvice public class GlobalControllerExceptionHandler { @ExceptionHandler(MissingServletRequestParameterException.class) public ResponseEntity<ErrorResponse> handleMissingParam(MissingServletRequestParameterException e) { ErrorResponse error = new ErrorResponse(false, 400, "缺少必填参数:" + e.getParameterName(), null); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } // 其他异常处理方法... }
注:ErrorResponse为项目中自定义的响应体类,结构与现有返回的{"status":false,"errorCode":...}一致。
2. 修正测试用例
针对参数缺失的场景,调整断言逻辑,校验正确的状态码和响应体内容:
@Test public void testFindAllWithoutPageSize() throws Exception { //Given Integer pageNum = 1; String accountId = "testaccountId"; Integer sortParam = 2; //Then mockMvc.perform(MockMvcRequestBuilders .get("/payment/list") .param("pageNum", pageNum.toString()) // 注释pageSize参数 .param("accountId", accountId) .param("sortParam", sortParam.toString()) ).andDo(print()) .andExpect(status().isBadRequest()) // 断言400状态码 .andExpect(jsonPath("$.errorCode").value(400)) // 断言响应体错误码 .andReturn().getResponse().getContentAsString(); }
内容的提问来源于stack exchange,提问作者OTUser
相关产品推荐
相关产品推荐

