注解
注解
自定义注解
//枚举
public enum OperationType {
INSERT, UPDATE
}
// 注解
package com.sky.annotation;
import com.sky.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解 用来标识某个方法需要进行功能字段总填充
*/
@Target(ElementType.METHOD)// 标识这个注解只能用于方法
@Retention(RetentionPolicy.RUNTIME)// 标识这个注解在哪个阶段生效 RUNTIME 表示运行时
public @interface AutoFill {
//定义了一个名为 value 的属性(默认属性)
//类型为枚举 OperationType(需import)
//无默认值 → 使用时必须显式指定值
//定义注解的value 数据库操作类型
//定义默认值 Insert
OperationType value() default OperationType.INSERT;
}
@Target注解
- 作用:指定注解的作用范围。
参数
| 参数名称 | 参数描述 |
|---|---|
| ElementType.TYPE | 用于类、接口或枚举 |
| ElementType.FIELD | 用于字段 |
| ElementType.METHOD | 用于方法 |
| ElementType.CONSTRUCTOR | 用于构造方法 |
| ElementType.PARAMETER | 用于参数 |
@Retention注解
- 作用:指定注解的保留策略(即注解的生命周期)。
- 保留策略:
参数
RetentionPolicy.SOURCE
- 描述:源代码阶段保留,注解在编译时会被丢弃,不会写入
.class文件,运行时无法通过反射读取 - 用途:1. 提供给编译器使用的注解(如
@Override、@SuppressWarnings)。2. 代码生成工具(如Lombok)在编译前处理源码时使用。
RetentionPolicy.CLASS
- 描述:类文件阶段保留,注解在编译时会被保留在
.class文件中,但不会写入.class文件,运行时无法通过反射读取 - 用途:
- 字节码分析工具(如 ASM)在编译后处理字节码时使用。
- 默认的保留策略(如果未显式指定
@Retention)。
RetentionPolicy.RUNTIME
- 描述:运行时保留,注解在编译时和运行时都会被保留,运行时可以通过反射读取注解信息。
- 用途:
- 需要运行时动态处理的注解(如
Spring的@Controller、自定义校验注解@NotEmpty)。 - 框架的依赖注入(如
@Autowired)、AOP切面逻辑等。
- 需要运行时动态处理的注解(如
自定义注解中的属性
格式:数据类型 属性名称() [default 默认值] //[]中的内容表示可选
- 属性名称+括号 ():这是
Java语言规范要求的语法,用于区分注解属性和普通字段。表示是注解的可配置参数 - 后面使用
@注解名称(属性名=属性值)的形式传递参数注意
如果注解中定义了名为
value的属性,且它是唯一需要赋值的属性,可以省略属性名直接赋值:
@AutoFill(OperationType.UPDATE) // 等价于 @AutoFill(value=OperationType.
:::
全局异常处理
@RestControllerAdvice- 作用:
- 是 Spring 提供的一个组合注解,结合了 @ControllerAdvice 和 @ResponseBody。
- 用于定义全局异常处理器,可以捕获整个应用中控制器(Controller)抛出的异常。
- 标记的类中定义的方法可以直接返回数据(JSON 或 XML),而不需要在每个方法上加 @ResponseBody。
- 用法:
- 将该注解应用于类级别。
- 结合多个 @ExceptionHandler 方法,实现对不同异常类型的统一处理。
- 示例:
@RestControllerAdvice
public class GlobalExceptionHandler {
// 异常处理方法
}
@ExceptionHandler- 作用:
- 用于标记一个方法作为异常处理方法。
- 可以捕获并处理指定类型及其子类的异常。
- 在 @RestControllerAdvice 标记的类中,它能够捕获全局控制器中的异常;在普通 @Controller 类中,则只能捕获当前控制器及其子类中的异常。
- 用法:
- 应用于方法级别。
- 指定要处理的异常类型(可选),如 @ExceptionHandler(SQLIntegrityConstraintViolationException.class)。
- 方法参数可以包括具体的异常对象、HttpServletRequest 等,返回值通常是错误响应对象(例如 Result.error(...))。
- 示例:
@ExceptionHandler(BaseException.class)
public Result exceptionHandler(BaseException ex) {
return Result.error(ex.getMessage());
}
综合示例
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
public Result exceptionHandler(BaseException ex) {
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex) {
log.error("异常信息:{}", ex.getMessage());
String message = ex.getMessage();
if (message.contains("Duplicate entry")) {
String[] split = message.split(" ");
return Result.error(split[2] + "已存在");
}
return Result.error("Sql异常");
}
}
@RestControllerAdvice使得这个类成为一个全局异常处理器。- 第一个
@ExceptionHandler方法捕获所有BaseException类型的异常。 - 第二个
@ExceptionHandler方法专门捕获SQLIntegrityConstraintViolationException,并根据异常信息进行定制化处理(如检测唯一性冲突)。 - 所有异常处理的结果都会直接返回给客户端,格式为
Result对象(通常包含状态码和错误信息)。
| 注解 | 作用范围 | 返回值是否自动序列化 | 使用场景 |
|---|---|---|---|
@RestControllerAdvice | 全局(整个应用的控制器) | 是(自动添加 @ResponseBody) | 全局异常处理 |
@ControllerAdvice | 全局 | 否(需手动添加 @ResponseBody) | 全局异常处理(返回视图名称时使用 |
@ExceptionHandler | 局部(所在类或其子类控制器) | 否 | 控制器内部异常处理 |
注意
若想实现统一的错误响应结构,推荐使用 @RestControllerAdvice 配合多个 @ExceptionHandler。
myBites注解
CRUD相关注解
| 注解 | 等效 XML 标签 | 作用 | 示例 |
|---|---|---|---|
@Select | <select> | 查询 | @Select("SELECT * FROM user WHERE id = #{id}") |
@Insert | <insert> | 插入 | @Insert("INSERT INTO user (name, age) VALUES (#{name}, #{age})") |
@Update | <update> | 更新 | @Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}") |
@Delete | <delete> | 删除 | @Delete("DELETE FROM user WHERE id = #{id}") |
@Options | <selectKey> | 置主键生成、超时等选项 | @Options(useGeneratedKeys = true, keyProperty = "id") |
参数处理注解
| 注解 | 作用 |
|---|---|
@Param | 用于给 SQL 中的参数起别名,区分参数名 |
@MapKey | 指定返回 Map 的键字段(用于结果集转为 Map 时) |
@ConstructorArgs | 绑定结果集到构造方法参数(替代 <constructor>) |
其他实用注解
| 注解 | 作用 |
|---|---|
@Flush | 强制立即执行 SQL(用于批量操作后立即刷新) |
@Lang | 指定自定义语言驱动(如实现动态 SQL 方言) |
@Param
它是 MyBatis 框架中的一个注解,主要用于 给 Mapper 接口方法的参数命名,以便在 XML 映射文件或注解 SQL 中引用。
核心作用
- 参数绑定:将
Java方法的参数与SQL中的变量名绑定。 - 解决多参数问题:当方法有多个参数时,避免
MyBatis默认使用param1, param2...或arg0, arg1...这种不直观的命名(在-parameters编译选项开启的情况下Spring Boot默认开启)。
使用场景
Lambda 表达式支持:在 MyBatis-Plus 的 LambdaQueryWrapper 中,@Param(Constants.WRAPPER) 用于绑定条件构造器。
@Update("UPDATE emp SET username = CONCAT(username, #{admin}) ${ew.customSqlSegment}")
void setAddAdmin(
@Param(Constants.WRAPPER) LambdaQueryWrapper<EmpPo> wrapper, // 绑定为 ${ew}
@Param("admin") String suffix
);
Mapper 接口方法(在参数名和 使用名不一致时必须使用@Param)
// Mapper 接口方法
@Select("SELECT * FROM user WHERE name = #{name} AND age = #{age}")
void User findUser(
@Param("name") String username, // 参数绑定为 #{name}
@Param("age") int userAge // 参数绑定为 #{age}
);
在动态 SQL 中引用参数
<!-- XML 映射文件 -->
<select id="findUser" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="name != null"> <!-- 直接使用 @Param 定义的名称 -->
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
注意事项
注意
- 单参数可省略:如果方法只有一个参数且没有动态
SQL,可以省略@Param。
// 以下两种方式等效
User findById(@Param("id") int id);
User findById(int id); // XML 中直接写 #{id}
- 与
Spring的@RequestParam区别:
@Param 是 MyBatis 注解,用于 SQL 参数绑定。@RequestParam 是 Spring MVC 注解,用于 HTTP 请求参数绑定。