Spring Aop 修改目标方法参数和返回值
一、新建注解
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface HandleField { //方法参数加密字段(顺序与方法参数顺序一致;字段类型为string) public String[] encrypFieldNameInfo(); //解密方法返回值字段(支持 map的key domain 和list<domain>) 字段类型为string public String decrypResultFieldName() default ""; }
二、建立切面
@Component("changeIdNoAopHandler") public class ChangeIdNoAopHandler { private static Logger logger = LoggerFactory.getLogger(ChangeIdNoAopHandler.class); private static final String SECRET_KEY = "12345678"; //秘钥 private String HANDLE_FIELD_NAME = "idNo"; //加密解密字段 private static final String ENCRYPT_FLAG = "encrypt"; //加密标识 (判断对值进行加密或者解密的操作) private static final String DECRYPT_FLAG = "decrypt"; //解密标识(判断对值进行加密或者解密的操作) @Autowired private InetxValDualService netxValDualService; @Autowired private IThemisCryptoIdnoService themisCryptoIdnoService; /*** * * @Description(功能描述) : 切面方法 (修改目标方法参数中带有 idNo字段的值;修改目标方法返回值带有idNo的字段) * @author(作者) : * @date (开发日期) : 2017-9-13 下午5:30:24 * @exception : * @param joinPoint * @return * @throws Throwable Object */ public Object parameterCheck(ProceedingJoinPoint joinPoint) throws Throwable{ logger.info("开始执行aop方法修改参数。。。"); Object target = joinPoint.getTarget();//返回被织入增强处理的目标对象 getThis:返回AOP框架为目标对象生成的代理对象 Object[] args = joinPoint.getArgs(); //获取目标对象方法参数 //遍历参数 修改带有idNo字段对象的值 (map list<domain> domain) for (Object _obj : args) { try{ changValue(_obj,ENCRYPT_FLAG); //加密参数 }catch (Exception e) { //使用异常机制来验证 _obj中 是否有idNo 字段 logger.error("修改目标方法参数字段值异常。目标类:" +target.getClass()+"方法:"+joinPoint.getSignature().getName()+"修改的值:"+_obj,e); } } //执行方法,以新的参数(如果不带args就是用原先的参数;这里带不带都可以是,上面方法获取原先参数的引用做的修改) Object returnValue = joinPoint.proceed(args); //若未设置,则不需要解密 if(!ObjectIsNullUtil.isNullOrEmpty(returnValue)){ try{ //修改 returnValue = changValue(returnValue,DECRYPT_FLAG); //解密参数 }catch (Exception e) { //使用异常机制来验证 _obj中 是否有idNo 字段 logger.error("修改目标方法返回值异常。目标类:" +target.getClass()+"方法:"+joinPoint.getSignature().getName()+"修改的值:"+returnValue,e); } } return returnValue; } /*** * * @Description(功能描述) : 修改对象idNo字段的值 * @author(作者) : * @date (开发日期) : 2017-9-13 下午5:30:07 * @exception : * @param _obj * @param flag 加密解密字段 * @throws Exception void */ private Object changValue(Object _obj, String flag) throws Exception{ //基本类型不作操作 if(_obj instanceof Map){ changeMapValue(_obj,flag); }else if(_obj instanceof List){ @SuppressWarnings("unchecked") List<Object> list = (List<Object>) _obj; for (Object obj : list) { if(obj instanceof Map){ changeMapValue(_obj,flag); }else{ changObjectValue(_obj,flag); } } }else{ changObjectValue(_obj,flag); } return _obj; } /** * * @Description(功能描述) : 当对象为Map 修改key的值 * @author(作者) : 吴桂镇 * @date (开发日期) : 2017-9-14 上午11:17:50 * @exception : * @param _obj * @param flag * @return Object * @throws Exception */ @SuppressWarnings("unchecked") private Object changeMapValue(Object _obj, String flag) throws Exception{ Map<String,Object> map = (Map<String,Object>) _obj; if(map.containsKey(HANDLE_FIELD_NAME)){ Object fieldValue = map.get(HANDLE_FIELD_NAME); String afterValue = crypto(fieldValue, flag); if(!ObjectIsNullUtil.isNullOrEmpty(afterValue)){ map.put(HANDLE_FIELD_NAME, afterValue); } } return _obj; } /*** * * @Description(功能描述) : 修改Object对象field的值 * @author(作者) : * @date (开发日期) : 2017-9-14 上午11:37:07 * @exception : * @param _obj * @param flag * @return * @throws Exception Object */ private Object changObjectValue(Object _obj, String flag) throws Exception{ Class<?> resultClz = _obj.getClass(); Field[] fieldInfo = resultClz.getDeclaredFields(); //获取class里的所有字段 父类字段获取不到 注:如果出现加密解密失败 请先查看idno是否在父类中 for (Field field : fieldInfo) { if(HANDLE_FIELD_NAME.equals(field.getName())){ field.setAccessible(true); //成员变量为private,故必须进行此操 Object fieldValue = field.get(_obj); String afterValue = crypto(fieldValue, flag); if(!ObjectIsNullUtil.isNullOrEmpty(afterValue)){ field.set(_obj, afterValue); } break; } } return _obj; } /*** * * @Description(功能描述) : 加密操作 * @author(作者) : * @date (开发日期) : 2017-9-14 下午3:20:32 * @exception : * @param value * @param flag * @return String * @throws Exception */ private String crypto(Object value,String flag) throws Exception{ if(ObjectIsNullUtil.isNullOrEmpty(value)){ return null; } //加密操作;加密之前先去查询一下数据库 有没有 如果没有 则insert if (ENCRYPT_FLAG.equals(flag)) { String encodeValue = Encryption.encode(SECRET_KEY, value.toString()); //加密 ThemisCryptoIdno idnoDomain = new ThemisCryptoIdno(); idnoDomain.setCryptoIdno(encodeValue); idnoDomain = themisCryptoIdnoService.selectOneByObject(idnoDomain); if(ObjectIsNullUtil.isNullOrEmpty(idnoDomain)){ //若空 则生成 seq 然后入库 返回seq String tr_date = DateOperation.convertToDateStr2(DateOperation.currentTimeMills()); //获取有流水号 String inextValDual=netxValDualService.findIdNoSeq(); //组流水:日期+ 7位流水 其他表储存的就是这个idnoSeq String idnoSeq=(tr_date+DateOperation.fill(inextValDual, '0', 7, true)).replaceAll("-", ""); idnoDomain = new ThemisCryptoIdno(); idnoDomain.setOptTime(DateOperation.convertToDateStr1(DateOperation.currentTimeMills())); idnoDomain.setCryptoIdno(encodeValue); idnoDomain.setCryptoSeq(idnoSeq); themisCryptoIdnoService.insert(idnoDomain); return idnoSeq; }else{ //不为空 直接返回seq return idnoDomain.getCryptoSeq(); } }else{ //解密操作 通过seq 查询 然后解密返回明文 ThemisCryptoIdno idnoDomain = new ThemisCryptoIdno(); idnoDomain.setCryptoSeq(value.toString()); idnoDomain = themisCryptoIdnoService.selectOneByObject(idnoDomain); if(!ObjectIsNullUtil.isNullOrEmpty(idnoDomain)){ return Encryption.decodeValue(SECRET_KEY, idnoDomain.getCryptoIdno()); //解密 } } return null; } public static void main(String[] args) throws Exception { System.out.println(Encryption.encode(SECRET_KEY, "142701197605091275")); } }
三、注解使用
@Component public class SusrService implements ISusrService{ @Autowired private SusrDao susrDao; @Override @HandleField(encrypFieldNameInfo={"usrCde"},decrypResultFieldName="usrCde") public sUsr selectOneByObject(sUsr su) { return susrDao.selectOneByObject(su); } }