记@NotEmpty不生效问题解决

项目场景:

问题:Controller层添加@NotEmpty或者@NotNull不生效,像下面这样:


问题描述

@ApiOperation(value = "测试")
@GetMapping("/test")
public String test(@NotEmpty(message = "desc不能为空") String name,
                               @NotNull(message = "age不能为空") Long age,
                               @NotEmpty(message = "desc不能为空") String desc) {
    return "test";
}

但是这样使用实体类,里面的属性使用@NotEmpty就是生效的:

@ApiOperation(value = "测试")
@PostMapping("/test")
public String test(@RequestBody @Valid NoticeParam noticeParam) {
    return "test";
}

@ApiModel(description = "测试")
@Data
public class NoticeParam {
    @NotEmpty(message = "name不能为空")
    private String name;

    @NotNull(message = "desc不能为空")
    private Long age;

    @NotEmpty(message = "desc不能为空")
    private String desc;
}

原因分析:

提示:这里填写问题的分析:

1.检查两者的区别,发现参数前面有个@Valid,于是在参数前面同样加了个@Valid

@ApiOperation(value = "测试")
@GetMapping("/test")
public String test(@Valid @NotEmpty(message = "desc不能为空") String name,
                               @NotNull(message = "age不能为空") Long age,
                               @NotEmpty(message = "desc不能为空") String desc) {
    return "test";
}

postman测试:
name,age,desc都没传,但是仍然返回了成功。说明@Valid在这里不生效。
在这里插入图片描述
  2.将@NotEmpty换成了@RequestParam,@RequestParam的源码如下,可以看到required是默认为true的。

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

但是加上了@RequestParam之后,虽然是被拦截了,但是没有将错误信息抛出来:

在这里插入图片描述
  只是抛出了系统的默认错误:
在这里插入图片描述
  而且@RequestParam不够灵活,没办法自定义抛出错误信息。所以还是从@NotEmpty下手。

3.从网上找资料,发现使用@Validated标记Controller层,然后再在参数中添加@NotEmpty,就可以抛出错误:

@Api(tags = "通知接口")
@RestController
@RequestMapping("/api/notice")
@Validated
public class TestApi {

    @ApiOperation(value = "测试")
    @GetMapping("/test")
    public String test(@NotEmpty(message = "name不能为空")  String name,
                     @NotNull(message = "age不能为空") Long age,
                     @NotEmpty(message = "desc不能为空") String desc) {
        return "test";
    }
}

测试之后控制台打印出了错误

在这里插入图片描述
但是在返回参数中,并未返回最终错误信息:
在这里插入图片描述
抛出来的错误并不是我们添加的错误信息,而是系统的默认错误。很明显,系统中有对这种异常专门的处理,但是漏掉了ConstraintViolationException这种异常的错误。我通过打印日志排查,找到了处理系统错误的代码:


解决方案:

@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResult<?> exceptionHandler(Exception ex, HttpServletRequest request) {
    log.error("", ex);
    if (StringUtils.containsIgnoreCase(ExceptionUtils.getRootCauseMessage(ex), "Broken pipe")) {
        return null;
    }
    //处理异常
    ErrorConstants error = ErrorHandler.handle(ex);
    BaseResult<?> res = BaseResult.failure(error.getCode(), error.getMsg());
    logResponse(res);
    return res;
}

public class ErrorHandler {
   
    public static ErrorConstants handle(Throwable e) {
        //UNKNOWN_ERROR("未知错误", 101,  "抱歉,我们遇到一点问题,请您稍后再试。"),
        ErrorConstants error = ErrorConstants.UNKNOWN_ERROR;
        //异常处理判断,项目代码不便展示
        ...
        //处理ConstraintViolationException异常时,前面的if都没进去,默认给了系统错误。
        return error;
    }

}

处理方式:
  添加一个@ExceptionHandler针对ConstraintViolationException的处理,代码如下:

@ExceptionHandler({ConstraintViolationException.class})
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResult<?> bindExceptionHandler(ConstraintViolationException ex) {
    log.error("", ex);
    String message = ErrorConstants.ILLEGAL_PARAM.getMsg();
    //取出@NotEmpty后面message的自定义错误信息
    Optional<ConstraintViolation<?>> aa = ex.getConstraintViolations().stream().findFirst();
    if (aa.isPresent()) {
        message = aa.get().getMessage();
    }
    //赋值并抛出
    BaseResult<?> res = BaseResult.failure(ErrorConstants.ILLEGAL_PARAM.getCode(), message);
    logResponse(res);
    return res;
}

效果:
在这里插入图片描述
结论:

1.@ExceptionHandler用于处理全局异常的,也可以处理单独的异常类。
  2.上面在Controller类上面使用@Validated是生效的,但是使用@Valid是不生效的,原因还不清楚。
  3.@RequestParam未直接抛出对应异常,和@NotEmpty处理方式一样,可以加个@ExceptionHandler({MissingServletRequestParameterException.class})可以抛出异常。如下

org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'name' is not present
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中,@Valid和@NotEmpty是用于数据校验的注解。@Valid注解用于标需要进行数据校验的对象,而@NotEmpty注解用于标字段不能为空。 如果在使用@Valid和@NotEmpty注解时发现不生效,可能有以下几个原因: 1. 未引入相关依赖:在使用数据校验注解时,需要引入相关的依赖包。在Java中,常用的数据校验框架是Hibernate Validator,因此需要引入相关的依赖,例如在Maven项目中可以添加以下依赖: ```xml <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.0.Final</version> </dependency> ``` 2. 未配置校验器:在使用@Valid注解时,需要配置校验器。可以通过在Spring Boot项目中添加以下配置来启用校验器: ```java @Configuration public class ValidationConfig { @Bean public Validator validator() { return Validation.buildDefaultValidatorFactory().getValidator(); } } ``` 3. 未开启校验功能:在使用@Valid注解时,需要确保校验功能已经开启。可以通过在Controller类或方法上添加@Validated注解来开启校验功能: ```java @RestController @Validated public class UserController { @PostMapping("/user") public void addUser(@Valid @RequestBody User user) { // 处理用户添加逻辑 } } ``` 如果以上步骤都已正确配置,但仍然发现@Valid和@NotEmpty注解不生效,可能是因为其他原因导致的。可以提供更多的代码或错误信息,以便更好地帮助您解决问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值