在实际的项目中,系统由运维人员去配置,生产数据库的用户名和密码对开发者是保密的。提供给开发者的数据库的用户名和密码是经过加密的,但是在创建SqlSessionFactory时需要提供明文密码。因此需要对加密的数据进行解密。
数据库配置文件
假设数据库配置文件为jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/forum
jdbc.username=root
jdbc.password=563739007
代码示例
以下便是创建SqlSessionFactory时对数据库配置中的加密用户名和密码进行解密操作示例。
代码已进行注释,不再进行讲解。
package forum.dao;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Enumeration;
import java.util.Properties;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
public class PropertiesRead {
private static SqlSessionFactory sqlSessionFactory;
@Test
public void init() {
InputStream cfgStream = null;
Reader cfgReader = null;
InputStream proStream = null;
Reader proReader = null;
Properties properties = new Properties();
System.out.println("PropertiesRead statup");
try {
//读入Mybatis配置文件
cfgStream = Resources.getResourceAsStream("res/mybatis/mybatis-config.xml");
cfgReader = new InputStreamReader(cfgStream);
//读入属性文件
proStream = Resources.getResourceAsStream("config/jdbc.properties");
proReader = new InputStreamReader(proStream);
properties.load(proReader);
//打印properties数据
printProperties(properties);
//解密操作
String newUserName = sqlNameAndPasswordDecode("jdbc.username",properties.getProperty("jdbc.username"));
String newUserPassword = sqlNameAndPasswordDecode("jdbc.password",properties.getProperty("jdbc.password"));
//将新的用户名和密码写入配置文件
properties.setProperty("jdbc.username",newUserName);
properties.setProperty("jdbc.password",newUserPassword);
printProperties(properties);
//创建sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader,properties);
cfgReader.close();
proReader.close();
}
catch(IOException ex) {
ex.printStackTrace();
}
}
public SqlSession getSqlSession() {
return PropertiesRead.sqlSessionFactory.openSession();
}
//打印属性信息
public void printProperties(Properties properties){
Enumeration<String> enu = (Enumeration<String>)properties.propertyNames();
while(enu.hasMoreElements()) {
String name = enu.nextElement();
System.out.println( name + ":" + properties.getProperty(name));
}
}
//对加密的用户名和密码进行解密
//仅作为简单示例
public String sqlNameAndPasswordDecode(String decodename,String decodevalue) {
if(decodename.equals("jdbc.username") ) {
return "newusername";
}
else if(decodename.equals("jdbc.password")) {
return "newpassword";
}
else {
return null;
}
}
}
区别
与未进行解密操作的区别在于创建SqlSessionFactory时传入的参数不同
可参考未进行解密操作的写法
//未进行解密操作,也就是未对属性文件未进行更改`
//创建sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader);
//进行解密操作,也就是已对属性文件未进行更改`
//多传入参数properties,也就是新的配置
//创建sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader,properties);
优先级
Mybatis支持的3种配置方式可能同时出现,并且属性还是会重复配置。
这三种方式是存在优先级的,Mybatis会按照下面的顺序来进行加载。
1.在properties元素体内的属性首先被读取;
2.根据properties元素中的resource属性读取类路径下的属性文件,或者根据url属性指定的路径读取配置文件,并覆盖已读取的同名属性。
3.读取作为方法参数传递的属性,并覆盖已读取的同名属性。
因此通过方法参数传递的属性具有最高优先级,resource/url读取的属性次之,最低优先级为properties属性中指定的属性。
本示例中在创建SqlSessionFactory传入的properties属性便会覆盖掉在XML文件中属性。