一、新建注解

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

Spring Aop 修改目标方法参数和返回值的更多相关文章

  1. Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API

    不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...

  2. 学习spring第6天(aop获取目标方法参数)

    关于<aop:around>中的方法,需要第一个参数为ProceedJoinPoint,在方法体中通过该参数调用proceed()才能使目标方法得到调用. 当一个切面中有多个<aop ...

  3. 基础才是重中之重~Emit动态构建方法(参数和返回值)

    回到目录 对于Emit我们知道它的可以动态构建程序集,类型,方法,属性等,或者说只要手动使用C#创建的东西使用Emit也都可以动态创建它们,Emit由于它的特别之处,所以在很多领域得到了广泛的应用,像 ...

  4. 【#】Spring3 MVC (三)---请求处理方法 参数及返回值总结

    博客分类:  spring MVCJSPServletCC++ @RequestMapping("/xxxx") public String  aaa(){ } 在处理用户请求的方 ...

  5. JAVA 类中方法参数与返回值

    无参无返回值的方法,用public void 方法名,来声明: 有参无返回值的方法,用public void 方法名,来声明: 有参有返回值的方法,用public int 方法名(int i,int ...

  6. MVC – 6.控制器 Action方法参数与返回值

      6.1 Controller接收浏览器数据   a.获取Get数据 : a1:获取路由url中配置好的制定参数: 如配置好的路由: 浏览器请求路径为: /User/Modify/1 ,MVC框架获 ...

  7. MVC – 6.控制器 Action方法参数与返回值

    6.1 Controller接收浏览器数据 a.获取Get数据 : a1:获取路由url中配置好的制定参数: 如配置好的路由: 浏览器请求路径为: /User/Modify/1 ,MVC框架获取请求后 ...

  8. Spring框架下的 “接口调用、MVC请求” 调用参数、返回值、耗时信息输出

    主要拦截前端或后天的请求,打印请求方法参数.返回值.耗时.异常的日志.方便开发调试,能很快定位到问题出现在哪个方法中. 前端请求拦截,mvc的拦截器 import java.util.Date; im ...

  9. 2. Bean Validation声明式校验方法的参数、返回值

    你必须非常努力,才能干起来毫不费力.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众 ...

随机推荐

  1. python全栈开发day77-博客主页

    1.文章分类 2.标签 3.归档 1) MySQL的日期格式化函数 DATE_FORMAT(字段名,格式) 2) Django ORM中如何执行SQL原生语句 (1) models.Article.o ...

  2. Vue2.0学习——axios用法详解

    功能特性 在浏览器中发送 XMLHttpRequests 请求 在 node.js 中发送 http请求 支持 Promise API 拦截请求和响应 转换请求和响应数据 自动转换 JSON 数据 客 ...

  3. new Vue 发生了什么

    new Vue 发生了什么 new vue 我们从入口分析,我们new 一个实例化对象,是由Funcction实现的,来看一下源码,在src/core/instance/index.js 中. imp ...

  4. 00-JAVA语法基础--动手动脑

    1.运行EnumTest.java,并分析结果,得出结论. 其源代码以及运行结果截图如下: 枚举类型的常量以字符串的形式顺序储.源代码中s和t不是原始数据类型.getCLass():取得当前对象所属的 ...

  5. HDU 2444 二分图判断 (BFS染色)+【匈牙利】

    <题目链接> 题目大意: 有N个人,M组互相认识关系互相认识的两人分别为a,b,将所有人划分为两组,使同一组内任何两人互不认识,之后将两个组中互相认识的人安排在一个房间,如果出现单人的情况 ...

  6. poj 1386 Play on Words门上的单词【欧拉回路&&并查集】

    题目链接:http://poj.org/problem?id=1386 题目大意:给你若干个字符串,一个单词的尾部和一个单词的头部相同那么这两个单词就可以相连,判断给出的n个单词是否能够一个接着一个全 ...

  7. React Native 打包 Apk

    第一步:生成秘钥库 keytool -genkey -v -keystore opsmart-android-release-key.keystore -alias opsmart-android - ...

  8. SpringBoot2使用WebFlux函数式编程

    本文只是简单使用SpringBoot2使用WebFlux的函数式编程简单使用,后续会继续写关于Webflux相关的文章. 最近一直在研究WebFlux,后续会陆续出一些相关的文章. 首先看一下Srpi ...

  9. 使用IntelliJ Idea新建SpringBoot项目

    简单给大家介绍一下我来创建SpringBoot项目使用的工具,本人使用IntelliJ Idea来创建项目,利用其中的Spring Initializr工具来快速创建项目. 步骤如下: 菜单栏中选择F ...

  10. XamarinSQLite教程创建数据表

    XamarinSQLite教程创建数据表 新创建的数据库没有任何表.开发者需要手动添加数据表,并添加测试所需的数据. 1.创建数据表 为了存储数据,开发者需要添加自己的表,并设计表的结构.操作步骤如下 ...