MyBatis自定义TypeHandler实现字段加密解密
前言
今天简单介绍利用MyBatis的TypeHandler接口实现字段的加解密。
字段的加密和解密,实现方式确实有好几种。比如,在业务层实现、在数据库层面实现等等,但是这些相对来说,耦合性稍微强那么一点点,而且涉及到改动的话,改动的地方比较多;所以最好的就是统一管理这些功能。
一、TypeHandler接口
Mybatis的TypeHandler类型转换器是负责Java类和jdbc类型之间的转换。
主要涉及到下面这几个类:
TypeHandler类型转换器的顶层接口。BaseTypeHandler抽象类继承自TypeHandler,Mybatis中所有的类型转换器实现均继承他。TypeHandlerRegistry类型转换器注册器,负责存储类型转换器。TypeAliasRegistry类型别名转换器,用来存储类型与别名的对应关系。
其主要作用就是:
- 可以指定我们在Java实体类所包含的自定义类型存入数据库后的类型是什么。
- 从数据库中取出该数据后自动转换为我们自定义的Java类型。
所以来实现简单的字段加密和解密比较方便。
二、实现
- 1、定义一个
实体类包装对象表示我们要加密的数据对象。
/**
* 编写一个实体类,凡是此实体类的数据都表示需要加解密
*/
@Data
public class Encrypt {
private String value;
}
- 2、实现
TypeHandler<T>接口,我们这实现BaseTypeHandler<T>。
@MappedJdbcTypes(JdbcType.VARCHAR) // 表示该Handler处理的java类型
@MappedTypes(Encrypt.class) // 表示处理器处理的Jdbc类型
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {
private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);
/**
* 设置参数
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null || parameter.getValue() == null) {
ps.setString(i, null);
return;
}
AES aes = SecureUtil.aes(KEYS);
String encrypt = aes.encryptHex(parameter.getValue());
ps.setString(i, encrypt);
}
/**
* 获取值
*/
@Override
public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
return decrypt(rs.getString(columnName));
}
/**
* 获取值
*/
@Override
public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return decrypt(rs.getString(columnIndex));
}
/**
* 获取值
*/
@Override
public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return decrypt(cs.getString(columnIndex));
}
public Encrypt decrypt(String value) {
if (null == value) {
return null;
}
return new Encrypt(SecureUtil.aes(KEYS).decryptStr(value));
}
}
- 3、配置
Handler,配置的方式有集中;如果是MyBatisPlus,直接在字段注解上面添加即可;
这里是MyBatis,所以可以写在配置文件中,也可以写在XML映射文件中,我们这里写在配置文件中。
# 指定自定义TypeHandler的包位置 mybatis.type-handlers-package=com.mybatis.typehandler
至此,关于自定义TypeHandler的开发就此完成,直接使用即可。
另外,基于自定义TypeHandler不仅可以实现自定义加解密,还可以实现特定数据类型的转换,这里以数据库类型为varchar映射Java对象类型的List集合类型为例说明。
还是自定义TypeHandler类,以逗号[,]分割为集合如下:
/**
* 特定类型转换TypeHandler
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class ListTypeHandler extends BaseTypeHandler<List<String>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
if (null == parameter || parameter.isEmpty()) {
ps.setString(i, null);
return;
}
ps.setString(i, String.join(",", parameter));
}
@Override
public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
final String value = rs.getString(columnName);
if (StringUtils.hasText(value)) {
return Arrays.asList(value.split(","));
}
return null;
}
@Override
public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
final String value = rs.getString(columnIndex);
if (StringUtils.hasText(value)) {
return Arrays.asList(value.split(","));
}
return null;
}
@Override
public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
final String value = cs.getString(columnIndex);
if (StringUtils.hasText(value)) {
return Arrays.asList(value.split(","));
}
return null;
}
}
- 4、使用
定义数据库对象类,如下:
@Data
public class Customer {
private Integer id;
private Encrypt phone; // 表示要加密的字段
private List<String> address; // 对应数据库字段address
}
建表语句:
CREATE TABLE `customer` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `phone` varchar(64) DEFAULT NULL COMMENT '手机号', `address` varchar(200) DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户表';
Mapper接口:
public interface CustomerMapper {
int addCustomer(@Param("phone") Encrypt phone, @Param("address") String address);
Customer findCustomer(@Param("phone") Encrypt phone);
}
Mapper接口XML:
<insert id="addCustomer">
insert into customer(phone,address) values (#{phone},#{address})
</insert>
<select id="findCustomer" resultMap="BaseResultMapper">
select * from customer where phone = #{phone}
</select>
Controller接口:
@RestController
public class CustomerController {
@Autowired
private CustomerMapper customerMapper;
@GetMapping("/addCustomer")
public String addCustomer(@RequestParam("phone") String phone, @RequestParam("address") String address) {
int result = customerMapper.addCustomer(new Encrypt(phone), address);
return "添加结果: " + result;
}
@GetMapping("/findCustomer")
public Customer findCustomer(@RequestParam("phone") String phone) {
return customerMapper.findCustomer(new Encrypt(phone));
}
}
数据库数据:

电话phone字段是加密之后的,address字段是 以逗号分隔的多个地址。
API调用结果如下:

可以看到电话号码,已经解密;地址成为字符串数组。
总结
MyBatis给我们提供了很多扩展类,MP和MB是一样的。所以关于数据结果类型的处理,可以使用TypeHandler接口。
到此这篇关于MyBatis自定义TypeHandler实现字段加密解密的文章就介绍到这了,更多相关MyBatis TypeHandler字段加密解密内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
- MyBatis类型处理器TypeHandler的作用及说明
- MyBatis中TypeHandler的使用教程详解
- MyBatis-Plus 中 typeHandler 的使用实例详解
- SpringBoot中MyBatis使用自定义TypeHandler的实现
- 解决Mybatis-plus自定义TypeHandler查询映射结果一直为null问题
- Mybatis中TypeHandler使用小结
- Mybatis的TypeHandler实现数据加解密详解
- Mybatis中自定义TypeHandler处理枚举的示例代码
- MyBatisPlus自定义JsonTypeHandler实现自动转化JSON问题
- MyBatis自定义TypeHandler如何解决字段映射问题
- MyBatis中TypeHandler基本用法与示例
相关文章
从application.properties配置文件获取的汉字乱码的解决方法
平时从配置文件各种读取配置参数都正常,但是有时候放了个中文就乱码,你肯定试过网上好多方法,都没解决,那么来看下面,恭喜你终于找这里了,本文给大家介绍了从application.properties配置文件获取的汉字乱码的解决方法,需要的朋友可以参考下2024-03-03
详解Spring数据缓存注解@Cacheable、@CachePut、@CacheEvict
这篇文章主要介绍了详解Spring数据缓存注解@Cacheable、CachePut、@CacheEvict,当以一组参数第一次调用某个方法时,返回值会被保存在缓存中,如果这个方法再次以相同的参数进行调用时,这个返回值会从缓存中查询获取,需要的朋友可以参考下2023-07-07
Springboot+hibernate实现简单的增删改查示例
今天小编就为大家分享一篇Springboot+hibernate实现简单的增删改查示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2018-08-08


最新评论