Java 类级验证问题

Java 类级验证问题,java,spring,annotations,Java,Spring,Annotations,我正在尝试验证几个字段。如果两者都包含无效字符,我需要输出一条错误消息 我正在尝试使用类级验证。但是,在运行单元测试时,我遇到了NoTouchElement异常 正在验证的类: @JsonIgnoreProperties(ignoreUnknown = true) @TwoFieldPattern(accountNumber = "accountNumber", sortCode = "sortCode") public class AccountDetails { @Pattern(

我正在尝试验证几个字段。如果两者都包含无效字符,我需要输出一条错误消息

我正在尝试使用类级验证。但是,在运行单元测试时,我遇到了NoTouchElement异常

正在验证的类:

@JsonIgnoreProperties(ignoreUnknown = true)
@TwoFieldPattern(accountNumber = "accountNumber", sortCode = "sortCode")
public class AccountDetails {

    @Pattern(regexp = "^[-0-9]*$", message="Fields contain invalid characters: account number '${validatedValue}'")
    private String accountNumber;

    @Pattern(regexp = "^[-0-9]*$", message="Fields contain invalid characters: sort code '${validatedValue}'")
    @NotBlank
    private String sortCode;

    public AccountDetails() {}

    public String getSortCode() {
        return sortCode;
    }

    public void setSortCode(String sortCode) {
        this.sortCode = sortCode;
    }

    public String getAccountNumber() {
        return accountNumber;
    }

    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }
}
验证类:

@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = TwoFieldPatternValidator.class)
public @interface TwoFieldPattern {

    String message() default "Fields contain invalid characters: account number '${validatedValue.accountNumber}', sort code '${validatedValue.sortCode}";

    String accountNumber();

    String sortCode();

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

public class TwoFieldPatternValidator implements ConstraintValidator<TwoFieldPattern, Object> {

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext cvc) {
        AccountDetails account = (AccountDetails) obj;
        return (!account.getAccountNumber().matches("^[-0-9]*$")&& !account.getSortCode().matches("^[-0-9]*$"));
    }
}

@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers,
                                                                  HttpStatus status, WebRequest request) {

        String errorMessage = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .findFirst()
                .map(FieldError::getDefaultMessage)
                .get();

        final BankDetailsValidationModel validationResult = new BankDetailsValidationModel(false, false, errorMessage, "");
        return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(validationResult);
    }
}
@Target(类型)
@保留(运行时)
@约束(validatedBy=TwoFieldPatternValidator.class)
公共@接口模式{
String message()默认值“字段包含无效字符:帐号“${validatedValue.accountNumber}”,排序代码“${validatedValue.sortCode}”;
字符串accountNumber();
字符串sortCode();
类[]组()默认值{};
类假设到目前为止您的“类验证器”设置正确,异常堆栈跟踪会将您指向
handleMethodArgumentNotValid()
方法-调用(
可选。
get
,让我们假设
getFieldErrors()
为空

由于它是一个“类vlaidator”,它不是由
fieldErrors
提供的,但是我们在
allErrors
()中“更幸运”

这将引导您找到一个:

无法将“org.springframework.validation.beanvalidation.SpringValidatorAdapter$ViolationObjectError”强制转换为“org.springframework.validation.beanvalidation.SpringValidatorAdapter$ViolationFieldError”

可以通过将
字段错误:getDefaultMessage
替换为
错误:getDefaultMessage
(+fix imports)来修复此问题

找不到局部变量“ex”


与原始帖子不一致…可能是您在重构时弄坏了某些东西。(编译器消息相当于“变量'ex'未声明”)

您尝试过吗?…至少对于调试BindingResult。-
getErrorCount、hasErrors、hasFieldErrors、hasGlobalErrors
似乎很有用。(…也许你会发现,
Error:getDefaultMessage
FieldError:…
效果很好,谢谢!我仍然看到
((ViolationFieldError)((java.util.LinkedList)((BeanPropertyBindingResult)ex.bindingResult)。错误。get(0)).violation=无法将“org.springframework.validation.beanvalidation.SpringValidatorAdapter$ViolationObjectError”强制转换为“org.springframework.validation.beanvalidation.SpringValidatorAdapter$ViolationFieldError”
(ViolationFieldError)((java.util.LinkedList)((BeanPropertyBindingResult)ex.bindingResult)。错误)。获取(0)).violation=在TwoFieldPatternValidator中找不到局部变量“ex”
。“无法强制转换”(重新阅读我的第二条评论):将
FieldError:getDefaultMessage
替换为
Error:getDefaultMessage
“找不到局部变量“ex””对于发布的代码来说有点奇怪/意外(修复了吗?)Thaks!我完全没有注意到类验证器没有字段错误。帮了大忙!
java.util.NoSuchElementException: No value present
    at java.base/java.util.Optional.get(Optional.java:148) ~[na:na]
    at uk.co.cdl.account.bankdetailsvalidation.service.controller.ExceptionHandler.handleMethodArgumentNotValid(ExceptionHandler.java:27) ~[classes/:na]
    at org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(ResponseEntityExceptionHandler.java:168) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:412) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:61) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:140) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:79) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1298) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1110) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1056) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:665) ~[javax.servlet-api-4.0.1.jar:4.0.1]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:750) ~[javax.servlet-api-4.0.1.jar:4.0.1]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

2020-03-07 11:26:04.187  WARN 21456 --- [o-auto-1-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<uk.co.cdl.account.bankdetailsvalidation.model.BankDetailsValidationModel> uk.co.cdl.account.bankdetailsvalidation.service.controller.BankDetailsValidatorController.validate(uk.co.cdl.account.bankdetailsvalidation.model.AccountDetails): [Error in object 'accountDetails': codes [TwoFieldPattern.accountDetails,TwoFieldPattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [accountDetails.,]; arguments []; default message [],accountNumber,sortCode]; default message [Fields contain invalid characters: account number '15764273', sort code '938063]] ]

org.opentest4j.AssertionFailedError: 
Expected :422
Actual   :400