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

Spring rest控制器@RequestParam验证

何修能
2023-03-14

我想验证请求参数。我已经浏览了很多博客并回答了问题,我也做了同样的事情。在控制器类上添加了@Validated。

控制器中的方法:

public ResponseEntity<Employee> getHistory(
@Valid @Pattern(regexp = "^[A-Z]{2}[0-9]{6}[A-Z]{0,1}$", message = "Invalid 
emp") @NotNull(message = "input cannot be null") @RequestParam(name = "emp") 
String emp) { method body..........}

控制器建议

@ExceptionHandler(value = {ConstraintViolationException.class})
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleValidationFailure(ConstraintViolationException ex) {

  StringBuilder messages = new StringBuilder();

  for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
      messages.append(violation.getMessage() + "\n");
  }

  return messages.toString();
}

配置

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
  return new MethodValidationPostProcessor();
}

完成所有这些之后,现在我得到一个404错误。"状态":404,"错误":"未找到","消息":"没有可用的消息"

共有1个答案

华宇
2023-03-14

在控制器建议中,您缺少对方法的@响应体注释。它会导致一个错误,因为Spring试图找到这个方法中返回名称为String的模板,所以在REST调用期间,您会得到这样的结果:

{
    "error": "Not Found", 
    "exception": "javax.validation.ConstraintViolationException", 
    "message": "No message available", 
    "path": "/history", 
    "status": 404, 
    "timestamp": 1502293311543
}

将注释添加到handleValidationFailure(ConstraintViolationExc0019 ex)方法意味着当返回String时,返回的不是模板名称,而是响应对象本身。

或者,您可以使用ResponseEntity

@ExceptionHandler(value = {ConstraintViolationException.class})
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public ResponseEntity<String> handleValidationFailure(ConstraintViolationException ex) {
    StringBuilder messages = new StringBuilder();

    for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
        messages.append(violation.getMessage());
    }

    return ResponseEntity.badRequest().body(messages.toString());
}

因此,您不必用@响应体注释方法,Spring现在将不再是视图名称,而是响应体本身。我希望它能有所帮助。

我认为您呼叫的endpoint不正确。我创建了一个小型Spring Boot应用程序,它使用提供的信息复制您的问题:

https://github.com/wololock/rest-validation-demo

随意克隆它并运行它。运行后,您可以尝试调用/历史终结点:

curl "localhost:8080/history?emp=AZ000001A"

作为回报,它将显示:

{"id":"AZ000001A","name":"Joe Doe"}%

如果使用违反验证规则的emp调用此终结点:

curl "localhost:8080/history?emp=sd"

您将得到以下响应:

{"message":"Your request contains errors","errors":[{"getHistory.arg0":"Invalid emp"}]}

我的假设是,在您的情况下,您错误地调用了终结点。在使用@RestController注释时存在普遍的误解。我看到人们使用它像@RestController("/某些RootPath"),然后他们希望有像这样的endpoint

localhost:8080/someRootPath/...

这是不正确的。传递给@RestController注释的值无非是:

该值可能表示对逻辑组件名称的建议,在自动检测组件的情况下,该名称将转换为Springbean。

您可以随时查看控制台日志以查看控制器的最终映射,例如。

2017-08-09 20:40:45.663  INFO 1340 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6385cb26: startup date [Wed Aug 09 20:40:44 CEST 2017]; root of context hierarchy
2017-08-09 20:40:45.696  INFO 1340 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/history],methods=[GET]}" onto public org.springframework.http.ResponseEntity<com.github.wololock.restvalidationdemo.Employee> com.github.wololock.restvalidationdemo.EmployeeController.getHistory(java.lang.String)
2017-08-09 20:40:45.698  INFO 1340 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-08-09 20:40:45.698  INFO 1340 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-08-09 20:40:45.708  INFO 1340 --- [           main] o.s.w.s.h.BeanNameUrlHandlerMapping      : Mapped URL path [/employee] onto handler '/employee'
2017-08-09 20:40:45.714  INFO 1340 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-08-09 20:40:45.714  INFO 1340 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

我希望有帮助。

 类似资料:
  • 是否有一种方法可以在@RequestParams上进行spring控制器单元测试以进行javax验证。 我在控制器中有一个get方法,它用@size验证请求参数的大小。 有没有办法模拟jUnit测试大小验证器?我想验证大小为 样本测试: @RunWith(MockitoJUnitRunner.class)公共类MyControllerTest{ } 我也试过SpringRunner,但似乎还是失败

  • 我的Spring MVC+Apache Tile2项目有以下配置。 我的问题是当我调用test2(没有参数)时,可以读取header.css。但是当调用test1时,我将得到header.css的404Not found。我注意到视图试图访问路径为 谢谢。

  • 下面的API接受来自客户端的json字符串,并将其映射到电子邮件对象中。如何将请求正文()作为原始字符串获取?(我需要原始字符串和键入版本的参数) PS:这个问题不是重复的:如何在SpringREST控制器中访问普通json主体?

  • 我需要将bean列表传递到我的控制器中。 和MyBean: 我需要从AngularJS做到这一点,但现在我正在用curl在bash中测试它。我需要什么命令? 会产生如下错误:

  • 我们正在尝试做一些具有登录屏幕的网站。但是我们有一个问题。我们的域是本地主机/登录/用户。但是,如果用户进入localhost/Home/Index,他/她无需登录即可访问我们的主站点。因此,我们将 [授权] 写入索引控制器。但我不知道我必须使用什么。我是否必须在我们的项目中使用AuthorizeAttribute? 如何访问LoginController/Authentication函数中的索引