如何使用 @NotNull等注解校验 并全局异常处理

本文介绍了如何在Spring Boot应用中使用@Valid和自定义注解@NotBlank/@IsMobile进行参数验证,以及如何通过全局异常处理类和拦截器捕获并返回统一的错误响应。

@NotNul 等注解的使用

代码:码云
1、添加依赖

        <!-- validation组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

2、在 controller 请求参数前 + @Vaild

    @RequestMapping("/doLogin")
    @ResponseBody
    public RespBean doLogin(@Valid LoginRequestParam param){}

3、在参数实体类上 加注解

@Data
public class LoginRequestParam {

    @NotBlank(message = "mobile不能为空")
    @IsMobile
    private String mobile;

    @NotBlank(message = "password不能为空")
    @Length(min = 32,message = "password 长度不对")
    private String password;

}

此时 的异常不会在页面显示 而是会 报400错误,并在 后台打印出错误,这就需要对异常进行拦截

在这里插入图片描述
后台保错信息,可知 注解拦截的异常为 BindException

Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors<EOL>Field error in object 'loginRequestParam' on field 'mobile': rejected value [11]; codes [IsMobile.loginRequestParam.mobile,IsMobile.mobile,IsMobile.java.lang.String,IsMobile]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [loginRequestParam.mobile,mobile]; arguments []; default message [mobile],true]; default message [手机号码 格式错误]]

全局异常处理

1、 首先 定义 异常的枚举信息

package com.example.seckill.common;

/**
 * 公共返回对象枚举
 *
 * @author: LC
 * @date 2022/3/2 1:44 下午
 * @ClassName: RespBean
 */

public enum RespBeanEnum {

    //通用
    SUCCESS(200, "SUCCESS"),
    ERROR(500, "服务端异常"),

    //登录模块
    LOGIN_ERROR(500210, "用户名或者密码不正确"),
    MOBILE_ERROR(500211, "手机号码格式不正确"),
    BIND_ERROR(500212, "参数校验异常"),
    MOBILE_NOT_EXIST(500213, "手机号码不存在"),
    PASSWORD_UPDATE_FAIL(500214, "更新密码失败"),
    SESSION_ERROR(500215, "用户SESSION不存在"),


    //秒杀模块
    EMPTY_STOCK(500500, "库存不足"),
    REPEATE_ERROR(500501, "该商品每人限购一件"),
    REQUEST_ILLEGAL(500502, "请求非法,请重新尝试"),
    ERROR_CAPTCHA(500503, "验证码错误,请重新输入"),
    ACCESS_LIMIT_REACHED(500504, "访问过于频繁,请稍后重试"),
    //订单模块5003xx
    ORDER_NOT_EXIST(500300, "订单不存在"),


    ;

    private final Integer code;
    private final String message;

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    RespBeanEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

2、 定义 返回信息的格式

package com.example.seckill.common;

/**
 * 公共返回对象
 *
 * @author: LC
 * @date 2022/3/2 1:50 下午
 * @ClassName: RespBean
 */
public class RespBean {

    private long code;
    private String message;
    private Object object;

    public static RespBean success() {
        return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), null);
    }

    public static RespBean success(Object object) {
        return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), object);
    }

    public static RespBean error(RespBeanEnum respBeanEnum) {
        return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), null);
    }

    public static RespBean error(RespBeanEnum respBeanEnum, Object object) {
        return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), object);
    }

    public RespBean(long code, String message, Object object) {
        this.code = code;
        this.message = message;
        this.object = object;
    }

    public RespBean() {

    }

    public long getCode() {
        return code;
    }

    public void setCode(long code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

3、 定义 全局异常处理类

package com.example.seckill.exception;

import com.example.seckill.common.RespBeanEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 *
 * 全局异常
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GlobalException extends RuntimeException{

    RespBeanEnum respBeanEnum;

}

4、 定义 异常拦截器

package com.example.seckill.exception;

import com.example.seckill.common.RespBean;
import com.example.seckill.common.RespBeanEnum;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


/**
 * 全局异常拦截器
 *
 */

@RestControllerAdvice
public class GlobalExceptionHandle {


    // 异常拦截
    @ExceptionHandler(Exception.class)
    public RespBean ExceptionHandler(Exception e){

        if (e instanceof GlobalException){
            // 如果拦截的异常是我们定义的异常 则直接return
            GlobalException ex = (GlobalException) e;
            return RespBean.error(ex.getRespBeanEnum());

        }else if (e instanceof BindException){ // 如果是注解拦截的异常 绑定异常
            BindException e1 = (BindException) e;
            RespBean respBean = RespBean.error(RespBeanEnum.BIND_ERROR);
            respBean.setMessage("参数检验异常" + e1.getBindingResult().getAllErrors().get(0).getDefaultMessage()); //显示 具体错误信息
            return respBean;

        }
        return RespBean.error(RespBeanEnum.ERROR);
    }

}

此时就会对 代码中的异常进行拦截 返回到前端,进行展示~

`@NotNull` 和 `@Length` 注解通常用于 Spring 框架中对数据进行校验,若这些注解未生效,可尝试以下解决方案: ### 1. 检查依赖 确保项目中添加了 JSR-303(Bean Validation)相关依赖,在 Maven 项目中,需添加如下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> ``` ### 2. 检查注解使用位置 `@NotNull` 和 `@Length` 注解应正确添加到实体类的字段上,示例如下: ```java import javax.validation.constraints.NotNull; import javax.validation.constraints.Length; public class User { @NotNull(message = "用户名不能为空") @Length(min = 3, max = 20, message = "用户名长度应在 3 到 20 之间") private String username; // Getters and Setters public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } } ``` ### 3. 检查控制器方法参数 在控制器方法中,需要使用 `@Valid` 或 `@Validated` 注解来触发校验,示例如下: ```java import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class UserController { @PostMapping("/users") public String createUser(@Valid @RequestBody User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "校验失败"; } // 处理用户创建逻辑 return "用户创建成功"; } } ``` ### 4. 全局校验配置 若使用了自定义的校验器或配置,需确保配置正确。 ### 5. 检查 Spring 上下文 确保 Spring 上下文能够正确扫描到实体类和控制器类。 ### 6. 检查方法调用 确保调用的方法是通过 Spring MVC 进行的,因为只有在 Spring MVC 环境下,`@Valid` 或 `@Validated` 注解才会生效。 ### 7. 检查 Java 版本 确保使用Java 版本支持 JSR-303 规范。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值