Spring Aop 修改目標方法參數和返回值

1、新建註解數據庫

@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 "";

}

2、創建切面app

@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"));
    }
}

3、註解使用框架

@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);
    }
}
相關文章
相關標籤/搜索