MyBatis自定義TypeHandler實現(xiàn)字段加密解密
前言
今天簡單介紹利用MyBatis的TypeHandler接口實現(xiàn)字段的加解密。
字段的加密和解密,實現(xiàn)方式確實有好幾種。比如,在業(yè)務(wù)層實現(xiàn)、在數(shù)據(jù)庫層面實現(xiàn)等等,但是這些相對來說,耦合性稍微強(qiáng)那么一點點,而且涉及到改動的話,改動的地方比較多;所以最好的就是統(tǒng)一管理這些功能。
一、TypeHandler接口
Mybatis的TypeHandler類型轉(zhuǎn)換器是負(fù)責(zé)Java類和jdbc類型之間的轉(zhuǎn)換。
主要涉及到下面這幾個類:
TypeHandler類型轉(zhuǎn)換器的頂層接口。BaseTypeHandler抽象類繼承自TypeHandler,Mybatis中所有的類型轉(zhuǎn)換器實現(xiàn)均繼承他。TypeHandlerRegistry類型轉(zhuǎn)換器注冊器,負(fù)責(zé)存儲類型轉(zhuǎn)換器。TypeAliasRegistry類型別名轉(zhuǎn)換器,用來存儲類型與別名的對應(yīng)關(guān)系。
其主要作用就是:
- 可以指定我們在Java實體類所包含的自定義類型存入數(shù)據(jù)庫后的類型是什么。
- 從數(shù)據(jù)庫中取出該數(shù)據(jù)后自動轉(zhuǎn)換為我們自定義的Java類型。
所以來實現(xiàn)簡單的字段加密和解密比較方便。
二、實現(xiàn)
- 1、定義一個
實體類包裝對象表示我們要加密的數(shù)據(jù)對象。
/**
* 編寫一個實體類,凡是此實體類的數(shù)據(jù)都表示需要加解密
*/
@Data
public class Encrypt {
private String value;
}
- 2、實現(xiàn)
TypeHandler<T>接口,我們這實現(xiàn)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);
/**
* 設(shè)置參數(shù)
*/
@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
至此,關(guān)于自定義TypeHandler的開發(fā)就此完成,直接使用即可。
另外,基于自定義TypeHandler不僅可以實現(xiàn)自定義加解密,還可以實現(xiàn)特定數(shù)據(jù)類型的轉(zhuǎn)換,這里以數(shù)據(jù)庫類型為varchar映射Java對象類型的List集合類型為例說明。
還是自定義TypeHandler類,以逗號[,]分割為集合如下:
/**
* 特定類型轉(zhuǎn)換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、使用
定義數(shù)據(jù)庫對象類,如下:
@Data
public class Customer {
private Integer id;
private Encrypt phone; // 表示要加密的字段
private List<String> address; // 對應(yīng)數(shù)據(jù)庫字段address
}
建表語句:
CREATE TABLE `customer` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵', `phone` varchar(64) DEFAULT NULL COMMENT '手機(jī)號', `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 "添加結(jié)果: " + result;
}
@GetMapping("/findCustomer")
public Customer findCustomer(@RequestParam("phone") String phone) {
return customerMapper.findCustomer(new Encrypt(phone));
}
}
數(shù)據(jù)庫數(shù)據(jù):

電話phone字段是加密之后的,address字段是 以逗號分隔的多個地址。
API調(diào)用結(jié)果如下:

可以看到電話號碼,已經(jīng)解密;地址成為字符串?dāng)?shù)組。
總結(jié)
MyBatis給我們提供了很多擴(kuò)展類,MP和MB是一樣的。所以關(guān)于數(shù)據(jù)結(jié)果類型的處理,可以使用TypeHandler接口。
到此這篇關(guān)于MyBatis自定義TypeHandler實現(xiàn)字段加密解密的文章就介紹到這了,更多相關(guān)MyBatis TypeHandler字段加密解密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MyBatis類型處理器TypeHandler的作用及說明
- MyBatis中TypeHandler的使用教程詳解
- MyBatis-Plus?中?typeHandler?的使用實例詳解
- SpringBoot中MyBatis使用自定義TypeHandler的實現(xiàn)
- 解決Mybatis-plus自定義TypeHandler查詢映射結(jié)果一直為null問題
- Mybatis中TypeHandler使用小結(jié)
- Mybatis的TypeHandler實現(xiàn)數(shù)據(jù)加解密詳解
- Mybatis中自定義TypeHandler處理枚舉的示例代碼
- MyBatisPlus自定義JsonTypeHandler實現(xiàn)自動轉(zhuǎn)化JSON問題
- MyBatis自定義TypeHandler如何解決字段映射問題
- MyBatis中TypeHandler基本用法與示例
相關(guān)文章
java 遞歸查詢所有子節(jié)點id的方法實現(xiàn)
在多層次的數(shù)據(jù)結(jié)構(gòu)中,經(jīng)常需要查詢一個節(jié)點下的所有子節(jié)點,本文主要介紹了java 遞歸查詢所有子節(jié)點id的方法實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-03-03
SpringBoot配置連接兩個或多個數(shù)據(jù)庫的常用方法
在Spring Boot應(yīng)用中連接多個數(shù)據(jù)庫或數(shù)據(jù)源可以使用多種方式,本文講給大家介紹兩種常用的方法:使用Spring Boot官方支持的多數(shù)據(jù)源配置和使用第三方庫實現(xiàn)多數(shù)據(jù)源,文章通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08
Java復(fù)雜表頭的Excel導(dǎo)入功能實現(xiàn)
本篇文章主要介紹如何使用Java相關(guān)的技術(shù),來實現(xiàn)復(fù)雜表頭的excel導(dǎo)入功能,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-09-09
Java基礎(chǔ)之ArrayList的擴(kuò)容機(jī)制
這篇文章主要介紹了Java基礎(chǔ)之ArrayList的擴(kuò)容機(jī)制,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下2021-05-05
Java基于socket服務(wù)實現(xiàn)UDP協(xié)議的方法
這篇文章主要介紹了Java基于socket服務(wù)實現(xiàn)UDP協(xié)議的方法,通過兩個簡單實例分析了java通過socket實現(xiàn)UDP發(fā)送與接收的技巧,需要的朋友可以參考下2015-05-05
java servlet獲得客戶端相關(guān)信息的簡單代碼
這篇文章主要介紹了java servlet獲得客戶端相關(guān)信息的簡單代碼,有需要的朋友可以參考一下2013-12-12

