@ControllerAdvice统一管理异常/错误
- 软件开发
- 2025-08-03 20:09:02

@ControllerAdvice 统一管理异常/错误 文章目录 @ControllerAdvice 统一管理异常/错误一、注意事项二、统一管理异常/错误的好处三、代码实现1. 普通方法2. 统一管理@ControllerAdvice3. PostMan测试结果 一、注意事项
1. 如果校验注解不指定 message 属性 ,会返回默认消息, 这些消息是配置在 ValidationMessages_zh_CN.properties 文件中的, 这个文件是框架提供的(如图) 2. 写完验证注解后, 不要忘了在控制器开启校验, 将 @Validated 写在要校验的 Entity前, 否则不会生效 3. @NotNull 注解可以接受任意类型, @NotBlank(String) 和@ NotEmpty(数组、集合) 都有要求, 具体看源码即可
二、统一管理异常/错误的好处1. 如果每一个 Controller 都分别写对数据校验异常的处理代码,非常繁琐,扩展性不高 2. 我们可以使用@ControllerAdvice 统一管理异常/错误
三、代码实现 1. 普通方法实体类BrandEntity.java
package com.xjz.xjzliving.commodity.entity; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.util.Date; import lombok.Data; import org.hibernate.validator.constraints.URL; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; /** * 家居品牌 * * @author xjz * @email xjz@gmail.com * @date 2024-02-20 19:03:08 */ @Data @TableName("commodity_brand") public class BrandEntity implements Serializable { private static final long serialVersionUID = 1L; /** * id */ @TableId private Long id; /** * 品牌名 * 代码解读 * 1. @NotBlank 表示 name 必须包括一个非空字符 * 2. message = "品牌名不能为空" 是我指定的一个校验消息 * 3. 如果不指定 message = " 品牌名不能为空" ,会返回默认消息 * javax.validation.constraints.NotBlank.message * 4. 这个消息是配置在 ValidationMessages_zh_CN.properties 文件中的 * 5. 下面其它的校验注解规则一样,也很好理解 */ @NotBlank(message = "品牌名不能为空") private String name; /** * logo * 1. @NotBlank 和 @URL 同时修饰 logo 是两个校验注解都要满足 */ @NotBlank(message = "logo不能为空") @URL(message = "logo不是一个合法的URL") private String logo; /** * 说明 */ private String description; /** * 显示 * 代码解读 * 1.这里使用了@NotNull 注解,该注解可以接受任意类型 * 2.如果使用@NotBlank 注解,会报错,因为@NotBlank 不支持校验 Integer * 3.在开发时,要注解注解可以接受哪些类型,直接看注解源码即可 * 4.如果是数字类型,不支持@Pattern, 后面再想办法 */ @NotNull(message = "显示状态不能为空") private Integer isshow; /** * 检索首字母 * 代码解读 * 1. @Pattern 是使用自己写的正则表达式来校验, 非常有用 */ @NotBlank(message = "检索字母不能为空") @Pattern(regexp = "^[a-zA-Z]$",message = "检索字母必须是a-z或者A-Z") private String firstLetter; /** * 排序 * 代码解读 * 1. @Min(value = 0) 表示 sort 这个字段最小值为 0 */ @NotNull(message = "排序值不能为空") @Min(value = 0,message = "排序值要求大于等于0") private Integer sort; }控制层BrandController
/** * @author xjz_2002 */ @RestController @RequestMapping("commodity/brand") public class BrandController { @Autowired private BrandService brandService; /** * 保存 * 代码解读 * 1. @Validated 标注在 这里表示启用对 BrandEntity 字段的校验 * 2. 注意: 如果不写 @Validated 即使在 BrandEntity 写了校验注解, 也不会生效 * 3. BindingResult result: springboot 会将校验的结果 放入到 result * 4. 程序员可以通过 BindingResult result 取出自己关系的错误信息 */ @RequestMapping("/save") public R save(@Validated @RequestBody BrandEntity brand, BindingResult result) { if (result.hasErrors()) { Map<String, String> map = new HashMap<>(); //1. 获取校验的错误结果 result.getFieldErrors().forEach((item) -> { //2. FieldError 获取到错误提示 String message = item.getDefaultMessage(); //3. 获取错误的属性的名字 String field = item.getField(); //4. 放入map map.put(field, message); }); return R.error(400, "品牌表单数据不合法").put("data", map); } else { //没有校验错误,则正常入库 brandService.save(brand); return R.ok(); } } } 2. 统一管理@ControllerAdvice统一管理数据异常工具类
package com.xjz.xjzliving.commodity.exception; import com.xjz.common.utils.R; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindingResult; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; /** * @author xjz_2002 * @version 1.0 */ /** * 代码解读 * 1. @ResponseBody 都以 json 格式返回数据 * 2. @ControllerAdvice * (basePackages = "com.xjz.xjzliving.commodity.controller")统一接管 * com.xjz.xjzliving.commodity.controller 包下 抛出的异常 */ @Slf4j @ResponseBody @ControllerAdvice(basePackages = "com.xjz.xjzliving.commodity.controller") public class XjzlivingExceptionControllerAdvice { /** * 代码解读 * 1. 数据校验错误属于 MethodArgumentNotValidException * 2. 可 以 通 过 log.error(" 数 据 校 验 出 现 问 题 {} , 异 常 类 型 : * {}",e.getMessage(),e.getClass()); 得到 * 3. 异常匹配的规则是先精确匹配,然后匹配范围更大的异常类型 * 4. 写清楚精确匹配的异常后,我们可以更加准确的定制提示异常信息 */ @ExceptionHandler(value = MethodArgumentNotValidException.class) public R handleVaildException(MethodArgumentNotValidException e) { log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass()); BindingResult bindingResult = e.getBindingResult(); Map<String , String> errorMap = new HashMap<>(); bindingResult.getFieldErrors().forEach(fieldError -> { errorMap.put(fieldError.getField(), fieldError.getDefaultMessage()); }); return R.error(400,"方法参数异常").put("data",errorMap); } /** * 这里再写一个处理 Throwable 类型的异常的方法, * 没有精确匹配到的异常, 走这里 */ @ExceptionHandler(value = Throwable.class) public R handleException(Throwable throwable){ return R.error(40000,"系统未知错误"); } } 3. PostMan测试结果数据校验异常
其他异常
@ControllerAdvice统一管理异常/错误由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“@ControllerAdvice统一管理异常/错误”