parameterhandler 拦截用于 sql 执行前参数加密,resultsethandler 拦截用于结果集解密;需结合 @sensitive 注解、字段名或类型精准识别敏感数据,避免全局污染与重复加解密。

理解 MyBatis 插件拦截目标与时机
ParameterHandler 是 MyBatis 执行 SQL 前封装参数的核心组件,负责将方法入参映射为 PreparedStatement 的占位符值。在 SQL 执行前的 prepare 阶段,它调用 setParameter 方法逐个设置参数。此时拦截,可在参数真正写入数据库前完成加密;同理,在结果映射阶段(通过 ResultSetHandler)可对密文字段做透明解密。关键在于:插件必须作用于 ParameterHandler 实例,且需确保只对标注敏感的字段或类型生效,避免全局污染。
编写 ParameterHandler 拦截插件
实现 Interceptor 接口,指定拦截签名 @Intercepts(@Signature(type = ParameterHandler.class, method = "setParameter", args = {Statement.class, int.class, Object.class}))。在 intercept 方法中获取原始参数值,判断是否属于需加密的字段(例如通过注解 @Sensitive、字段名如 "idCard"、"phone" 或类型如 String 且匹配正则),再调用统一加解密服务(如 AES/GMSSL)处理。注意:仅处理非 null、非空字符串、且未被标记为已加密的值,防止重复加密。
- 使用 Plugin.wrap() 包装原 ParameterHandler,保证链式调用
- 避免在拦截器中硬编码密钥,应从 Spring Environment 或配置中心读取
- 对 byte[]、BigDecimal 等非 String 类型,按业务约定转换后再加解密(如 phone 存为 String 再加密)
结合注解与元数据精准识别敏感字段
定义 @Sensitive 注解,标注在实体类字段上(如 private String idCard;),并在拦截时通过反射获取该字段的声明类型和名称。若当前参数是实体对象,则遍历其所有 @Sensitive 字段,提取值并加密;若参数是 Map,则检查 key 是否匹配敏感字段名;若参数是单值(如 String phone),则根据方法签名中的参数名(通过 @Param 或参数顺序推断)判断是否敏感。这样既保持 DAO 层无感,又避免误加密无关字段。
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
解密逻辑放在 ResultSetHandler 更合理
ParameterHandler 只管“出参”,解密应由 ResultSetHandler 在结果映射时完成。同样编写插件拦截 handleResultSets 方法,遍历 ResultMap 中每个 ResultMapping,若其 property 对应字段有 @Sensitive 注解,则对 ResultSet 中对应列的值执行解密。这样能保证返回给业务层的对象字段已是明文,调用方完全无感知。注意:解密失败时应记录告警但不抛异常,避免影响主流程;同时缓存已解密字段,避免重复解密。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










