@InterceptorIgnore
是 MyBatis-Plus 提供的一个非常实用的注解,用于在特定的 CRUD 操作中临时忽略某些全局拦截器的行为。它能帮助开发者在需要时灵活绕过如分页、租户、数据权限、SQL 性能监控等全局拦截逻辑,适用于特定场景下的性能优化或业务绕行。
一、核心概念
1. 什么是 @InterceptorIgnore
?
@InterceptorIgnore
是一个作用于 Mapper 接口方法 或 Service 方法(需配合 AOP)上的注解,用于在执行 SQL 时临时关闭某些全局拦截器的功能。
2. 主要作用
- 跳过分页拦截:某些查询不需要分页,避免
PageHelper
或 MP 分页插件生效。 - 绕过租户拦截:多租户系统中,某些操作需要跨租户查询。
- 禁用数据权限:管理员操作时绕过数据权限控制。
- 跳过性能监控:对高频、简单 SQL 关闭慢 SQL 监控,减少性能损耗。
3. 支持的拦截器类型(常见)
拦截器类型 | 对应 @InterceptorIgnore 属性 |
说明 |
---|---|---|
分页拦截器 | pagination |
跳过分页逻辑 |
租户拦截器 | tenantLine |
忽略租户字段自动注入 |
动态表名 | dynamicTableName |
不进行表名动态替换 |
数据权限 | dataPermission |
跳过数据权限过滤 |
SQL 性能分析 | blockAttack |
禁用 SQL 防注入攻击检查 |
二、操作步骤(非常详细)
步骤 1:引入 MyBatis-Plus 依赖
确保项目中已引入 MyBatis-Plus(以 Spring Boot 为例):
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
步骤 2:配置全局拦截器(以分页和租户为例)
示例:配置分页和租户拦截器
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 1. 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 2. 租户插件
TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
tenantInterceptor.setTenantLineHandler(new TenantLineHandler() {
@Override
public String getTenantId() {
return "10001"; // 实际应从上下文获取
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
});
interceptor.addInnerInterceptor(tenantInterceptor);
return interceptor;
}
}
步骤 3:使用 @InterceptorIgnore
忽略特定拦截器
场景 1:忽略分页拦截器
在 Mapper 接口方法上使用:
public interface UserMapper extends BaseMapper<User> {
/**
* 此方法不进行分页处理,即使外部调用了分页
*/
@InterceptorIgnore(pagination = "true")
List<User> selectAllWithoutPage();
}
说明:调用此方法时,即使 ThreadLocal 中有分页参数,也不会生效。
场景 2:忽略租户拦截器
@InterceptorIgnore(tenantLine = "true")
List<User> selectAllAcrossTenants();
说明:查询所有租户的数据,不自动添加
tenant_id = ?
条件。
场景 3:同时忽略多个拦截器
@InterceptorIgnore(pagination = "true", tenantLine = "true")
List<User> selectAllForAdmin();
说明:管理员操作,既不分页也不受租户限制。
场景 4:在 Service 层使用(需开启 AOP)
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@InterceptorIgnore(pagination = "true")
public List<User> getAllUsers() {
return userMapper.selectList(null); // 此调用将忽略分页
}
}
注意:Service 方法使用
@InterceptorIgnore
需确保 AOP 生效(方法不能是private
,且在同一类中调用会失效)。
三、常见错误
错误 | 原因 | 解决方案 |
---|---|---|
@InterceptorIgnore 不生效 |
注解位置错误或拦截器未正确配置 | 确保注解在 Mapper 方法 上,且对应拦截器已注册 |
租户条件仍被添加 | tenantLine = "true" 拼写错误或大小写问题 |
使用 "true" 字符串,注意大小写 |
分页仍生效 | 其他地方手动设置了分页 | 检查是否在代码中显式调用 PageHelper.startPage() 或 new Page<>() |
Service 层注解无效 | AOP 未生效(如 self-invocation) | 使用 @Autowired 调用代理对象,避免直接调用本类方法 |
四、注意事项
- 作用范围:
@InterceptorIgnore
只对当前方法生效,不影响其他方法。 - 字符串值:属性值为
"true"
或"false"
,不是布尔类型。 - 优先级:
@InterceptorIgnore
优先级高于全局拦截器配置。 - 不支持嵌套:若 A 方法调用 B 方法,B 有
@InterceptorIgnore
,但 A 没有,则可能不生效(AOP 限制)。 - 谨慎使用:绕过租户或数据权限可能带来安全风险,仅用于可信场景(如后台管理)。
五、使用技巧
1. 动态控制(结合 SpEL,需自定义)
MyBatis-Plus 原生不支持 SpEL,但可通过自定义注解 + AOP 实现:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@InterceptorIgnore
public @interface DynamicIgnore {
String pagination() default "";
}
进阶:结合 Spring AOP 解析 SpEL 表达式动态决定是否忽略。
2. 与 @DS
数据源切换结合
@DS("slave")
@InterceptorIgnore(pagination = "true")
List<User> selectFromSlaveWithoutPage();
用途:从从库查询大量数据,不分页,减轻主库压力。
3. 高频查询关闭监控
@InterceptorIgnore(blockAttack = "true") // 关闭 SQL 防攻击检查
User findByIdFast(Long id);
适用:极高频的查询接口,减少拦截器开销。
六、最佳实践与性能优化
最佳实践
- 最小化使用:仅在必要时使用
@InterceptorIgnore
,避免滥用导致逻辑混乱。 - 命名规范:方法名体现“忽略”语义,如
selectWithoutPagination
、queryAcrossTenants
。 - 权限控制:绕过租户或权限的方法必须进行严格的访问控制(如
@PreAuthorize
)。 - 文档说明:在方法上添加注释,说明为何忽略拦截器。
性能优化
- 减少拦截器开销:对简单查询(如根据主键查)关闭不必要的拦截器,提升吞吐量。
- 批量操作优化:批量插入/更新时,可考虑关闭 SQL 性能分析拦截器。
- 异步任务绕行:定时任务或数据同步任务中,使用
@InterceptorIgnore
避免被业务拦截器干扰。
总结
@InterceptorIgnore
是 MyBatis-Plus 中一个“精准控制拦截器行为”的利器。通过它,你可以在特定方法中:
✅ 跳过分页
✅ 绕过租户隔离
✅ 关闭数据权限
✅ 提升高频查询性能