需求:
1、只导入绩效基础数据,有些数据需要计算得出(excel公式一键生成的东西,硬要这样玩,真是无语)
2、绩效数据全要加密。
期间碰到了
1、关于org.apache.commons.beanutils.BeanUtils中 String转Date的问题。
2、des对称加密。
3、由于字段太多(50多个。。),所以利用反射去加密,不然写的累死了
第一个问题:关于org.apache.commons.beanutils.BeanUtils中 String转Date的问题。
因为有些数据需要计算,所以一开始关于绩效的数据是用float类型去接的(利用easypoi),计算是利用BigDecimal(不然精度会有误),然后因为要加密,之后会转换成String的类型。
根据BeanUtils.copyProperties( , ) float类型是可以成功转成String类型的,但是String类型不能转成Date类型。
所以在执行copyProperties方法之前,注册一个转换器。
ConvertUtils.register(new Converter()
{
@SuppressWarnings("rawtypes")
@Override
public Object convert(Class arg0, Object arg1)
{
if(arg1 == null)
{
return null;
}
if(!(arg1 instanceof String))
{
throw new ConversionException("只支持字符串转换 !");
}
String str = (String)arg1;
if(str.trim().equals(""))
{
return null;
}
SimpleDateFormat sd = new SimpleDateFormat("yyyyMM"); //这里自定义转换
try{
return sd.parse(str);
}
catch(ParseException e)
{
throw new RuntimeException(e);
}
}
}, java.util.Date.class);
第二个问题:des加密,写了一个类,代码如下
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
/**
*
* des加密解密
* @author gzc
*
*/
public class DesUtil {
/**
* 获得秘钥
* @return
* @throws InvalidKeySpecException
*/
public static Key getDesKey() {
//1.初始化key秘钥
Key key=null;
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(new SecureRandom());
SecretKey secretKey= keyGenerator.generateKey();
//转换key秘钥
DESedeKeySpec deSedeKeySpec=new DESedeKeySpec(secretKey.getEncoded());
SecretKeyFactory secretKeyFactory=SecretKeyFactory.getInstance("DESede");
key= secretKeyFactory.generateSecret(deSedeKeySpec);
} catch (Exception e) {
e.printStackTrace();
}
return key;
}
/**
* 对秘钥进行编码保存
* @param key
* @return
*/
public static String getHexKey(Key key){
return HexBin.encode(key.getEncoded());
}
/**
* 加密float類型
* @param key 秘钥
* @param f
* @return
*/
public static String desEncode(Key key,float f){
String desEncodeStr=null;
try {
Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result= cipher.doFinal((f+"").getBytes());
desEncodeStr=HexBin.encode(result);
} catch (Exception e) {
e.printStackTrace();
}
return desEncodeStr;
}
/**
* 通过16位的编码秘钥,反推秘钥
* @param hexKey
* @return
*/
public static Key getDesKey(String hexKey){
Key key=null;
try {
//解码,重新生成key
byte[] keybyte= HexBin.decode(hexKey);
DESedeKeySpec deSedeKeySpec=new DESedeKeySpec(keybyte);
SecretKeyFactory secretKeyFactory=SecretKeyFactory.getInstance("DESede");
key= secretKeyFactory.generateSecret(deSedeKeySpec); //获取到key秘钥
} catch (Exception e) {
e.printStackTrace();
}
return key;
}
/**
* 解密
* @param key 秘钥
* @param encodeStr 需要解码的字符串
* @return
*/
public static String desDecode(Key key,String encodeStr){
String resultStr=null;
try {
//进行解密
Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(HexBin.decode(encodeStr));
resultStr=new String(result);
} catch (Exception e) {
e.printStackTrace();
}
return resultStr;
}
}
第三个问题:利用反射去设置字段的加密、解密 写了一个工具类:
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Key;
import java.util.Arrays;
public class ReflectEncryption {
/**
*
* @param entity 需要加密的一个对象
* @param strs 需要加密的属性名数组
* @param key 秘钥
* @throws Exception
*/
public static <T> void encode(T entity,String[] strs,Key key) throws Exception{
//得到Class
Class clazz =entity.getClass();
//得到属性名数组
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
if(Arrays.asList(strs).contains(f.getName())){
//用来得到属性的get和set方法
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
//得到set方法
Method setMethod=pd.getWriteMethod();
//得到get方法
Method getMethod=pd.getReadMethod();
//加密
setMethod.invoke(entity, DesUtil.desEncode(key, Float.parseFloat((String)getMethod.invoke(entity))));
}
}
}
public static <T> void decode(T entity,String[] strs,Key key) throws Exception {
Class clazz =entity.getClass();
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
if(Arrays.asList(strs).contains(f.getName())){
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
Method setMethod=pd.getWriteMethod();
Method getMethod=pd.getReadMethod();
setMethod.invoke(entity, DesUtil.desDecode(key, (String)getMethod.invoke(entity)));
}
}
}
}