You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 = []          

原因分析

  1. MissingServletRequestParameterException是Spring发现必填请求参数缺失时抛出的标准异常,默认应该返回400 Bad Request状态码。
  2. 项目中存在全局异常处理器GlobalControllerExceptionHandler,它捕获了该异常,但处理逻辑存在问题:没有为这类客户端参数错误设置正确的HTTP状态码,而是默认返回200,同时在自定义响应体中填入了500的错误码和通用提示。
  3. 测试用例仅断言了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:40:57