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

@Spring REST控制器中有效Hibernate验证

邓昊天
2023-03-14

我试图在带有@valid注释的Spring REST控制器中使用Hibernate验证。

但验证没有发生。

下面是Maven构建必须要说的话:

java.lang.AssertionError:状态应为:<400>,但实际为:<201>

@Test
public void testValidation() throws Exception {
    HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + PASSWORD);

MvcResult resultPost = this.mockMvc.perform(
        post("/admin").headers(httpHeaders)
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON)
        .content("{ \"firstname\" : \"" + admin0.getFirstname() + "\", \"lastname\" : \"" + admin0.getLastname() + "\", \"email\" : \"" + admin0.getEmail() + "\", \"login\" : \"" + admin0.getLogin() + "\", \"password\" : \"" + admin0.getPassword() + "\", \"passwordSalt\" : \"" + admin0.getPasswordSalt() + "\" }")
    ).andDo(print())
    .andExpect(status().isBadRequest())
    .andExpect(jsonPath("$.firstname").value(admin0.getFirstname()))
    .andExpect(jsonPath("$.lastname").value(admin0.getLastname()))
    .andExpect(jsonPath("$.email").value(""))
    .andExpect(jsonPath("$.login").value("short"))
    .andExpect(jsonPath("$.password").value(admin0.getPassword()))
    .andExpect(jsonPath("$.passwordSalt").value(admin0.getPasswordSalt()))
    .andExpect(header().string("Location", Matchers.containsString("/admin/")))
    .andReturn();
@ControllerAdvice
public class AdminExceptionHandler {

    @ExceptionHandler(AdminNotFoundException.class)
    @ResponseBody
    public ResponseEntity<ErrorInfo> adminNotFoundException(HttpServletRequest request, AdminNotFoundException e) {
        String url = request.getRequestURL().toString();
        String errorMessage = localizeErrorMessage("error.admin.not.found", new Object[] { e.getAdminId() });
        return new ResponseEntity<ErrorInfo>(new ErrorInfo(url, errorMessage), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseEntity<ErrorFormInfo> methodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
        String url = request.getRequestURL().toString();
        String errorMessage = localizeErrorMessage("error.admin.invalid.form.argument");
        ErrorFormInfo errorFormInfo = new ErrorFormInfo(url, errorMessage);
        BindingResult result = e.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();
        errorFormInfo.getFieldErrors().addAll(populateFieldErrors(fieldErrors));
        return new ResponseEntity<ErrorFormInfo>(errorFormInfo, HttpStatus.BAD_REQUEST);
    }

    public List<ErrorFormField> populateFieldErrors(List<FieldError> fieldErrorList) {
        List<ErrorFormField> errorFormFields = new ArrayList<ErrorFormField>();
        StringBuilder errorMessage = new StringBuilder("");
        for (FieldError fieldError : fieldErrorList) {
            errorMessage.append(fieldError.getCode()).append(".");
            errorMessage.append(fieldError.getObjectName()).append(".");
            errorMessage.append(fieldError.getField());
            errorFormFields.add(new ErrorFormField(fieldError.getField(), localizeErrorMessage(errorMessage.toString())));
            errorMessage.delete(0, errorMessage.capacity());
        }
        return errorFormFields;
    }

    private String localizeErrorMessage(String errorCode) {
        return localizeErrorMessage(errorCode, null);
    }

    private String localizeErrorMessage(String errorCode, Object args[]) {
        Locale locale = LocaleContextHolder.getLocale();
        String errorMessage = messageSource.getMessage(errorCode, args, locale);
        return errorMessage;
    }

}

注意AdminNotFoundException是由其他测试触发的。

但不触发MethodArgumentNotValidException。

下面是controller类:

@Controller
@ExposesResourceFor(Admin.class)
@RequestMapping("/admin")
public class AdminController {

    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<Admin> add(@RequestBody @Valid Admin admin, UriComponentsBuilder builder) {
        AdminCreatedEvent adminCreatedEvent = adminService.add(new CreateAdminEvent(admin.toEventAdmin()));
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setLocation(builder.path("/admin/{id}").buildAndExpand(adminCreatedEvent.getAdminId()).toUri());
        Admin createdAdmin = adminResourceAssembler.toResource(adminCreatedEvent.getEventAdmin());
        ResponseEntity<Admin> responseEntity = new ResponseEntity<Admin>(createdAdmin, responseHeaders, HttpStatus.CREATED);
        return responseEntity;
    }

}
mvn clean install tomcat7:run -DskipTests

curl -H "Accept:application/json" --user joethebouncer:mignet http://localhost:8080/learnintouch-rest/admin -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d "{ \"firstname\" : \"Stephane\", \"lastname\" : \"Eybert\", \"email\" : \"\", \"login\" : \"short\", \"password\" : \"mignet\", \"passwordSalt\" : \"7bc7bf5f94fef7c7106afe5c3a40a2\" }"

亲切的问候,

斯蒂芬·艾伯特

共有1个答案

莘羽
2023-03-14

我尝试了您的代码,遵循了您提到的相同步骤,并且验证确实正确地发生了。

这是我使用与您发布的完全相同的curl命令得到的响应:

{“URL”:“http://localhost:8080/learnintouch-rest/admin”,“message”:“管理表单参数无效。”,“fielderrors”:[{“fieldname”:“login”,“fielder ror”:“length.admin.login”},{“fieldname”:“email”,“fielderrorr”:“notempty.admin.email”}]}

我建议您尝试清理maven存储库,从头开始构建项目。

我还应该提到,在testvalidation()集成测试中,您正在使用的admin0对象实际上是有效的,因此它通过验证是有意义的:)

 类似资料:
  • 我知道这在这个论坛上不是新问题,但我很困惑我该怎么做。 问题:我正在用spring mvc+Hibernate开发一个应用程序。对于服务器端验证,我在controller中使用@valid注释,在bean中使用@null和@notnull注释。 例如: 这个验证很好地进行,数据也保存在DB中。 但我想验证唯一约束,引用完整性和其他约束使用注释没有任何验证器类。 有可能吗?如果没有,那么什么是最好和

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

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

  • 我想验证请求参数。我已经浏览了很多博客并回答了问题,我也做了同样的事情。在控制器类上添加了@Validated。 控制器中的方法: 控制器建议 配置: 完成所有这些之后,现在我得到一个404错误。"状态":404,"错误":"未找到","消息":"没有可用的消息"

  • 问题内容: 我需要检查表单在控制器中是否有效。 视图: 在我的控制器中: 我收到此错误: 问题答案: 我已将控制器更新为:

  • 问题内容: 我正在尝试使用生成一个可编辑列表。我想提醒用户在继续操作之前更新所有编辑内容,因此我正在使用中动态创建“嵌套”表单,因为文档说我可以在这些动态创建的输入上使用验证。 尽管这似乎可以在HTML中运行,但我看不到如何在控制器中访问那些动态创建的表单和相关的验证字段。具体来说,当用户更改输入时,我使用$ dirty属性形式调出一个按钮来告诉用户提交更改。到目前为止,一切都很好。但是,一旦提交