2019独角兽企业重金招聘Python工程师标准>>>

业务概要:

1、表单验证。

2、短信验证码验证,如果是认证用户需要校验接收验证码的手机号和认证的手机号是否一致。

这种通用代码抽取,大家自然想起来用AOP解决。我先去处理的 业务2 这就造成了一个问题。表单验证在这个业务处理之后进行。很尴尬。就想着在这个AOP类中把表单验证的逻辑添加进去。但是代码越写越繁琐。逻辑混杂。看着就不爽。想了想用两个AOP去解决这个问题。果然很爽。这样代码减少了一大半。

具体的思路 :

1、自定义注解在方法上使用。

2、spring 扫描这个注解切面。

3、执行业务1 @Before。

4、执行业务2 @Around(这里其实使用@Before也没啥问题)。

http://blog.csdn.net/rainbow702/article/details/52185827 感谢此文的指导!

遇见问题:

代码莫名其妙不知道去了哪里不继续流转了。这里就该

注意@Order ( Lower values have higher priority.更低的值具有更高的优先级。)执行顺序了!

网上有个两个圈圈的图(应该百度就能看见),更能很好的解释AOP的执行顺序,对理解AOP很有用!

以下代码仅供参考 无复制价值

/*** 描述 验证码手机认证信息验证 标记注解* @author lienbo*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WorkOrderVerify {}

以下代码仅供参考 无复制价值

package com.lienbo.interceptor;import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;import com.lienbo.exceptions.FormValidException;@Aspect
@Component
@Order(1)
public class ValidFormInterceptor {private final static Logger LOGGER = LoggerFactory.getLogger(ValidFormInterceptor.class);@Pointcut("@annotation(com.lienbo.handler.WorkOrderVerify)")public void pointcut() {}@Before("pointcut()")public void verifyForm(JoinPoint joinPoint) {LOGGER.info("【工单表单参数校验----------------开始】");Object[] args = joinPoint.getArgs();if (args == null || args.length < 1) {LOGGER.info("【获取方法参数失败】");return;}List<Object> argsList = Arrays.asList(args);// 对参数进行过滤List<Object> list = argsList.stream().filter(x -> x instanceof BindingResult).collect(Collectors.toList());if (list.size() != 1) {LOGGER.info("【获取表单vo失败】");return;}BindingResult result = (BindingResult) list.get(0);// 表单验证if (result.hasErrors()) {String errorMsg = result.getAllErrors().get(0).getDefaultMessage();LOGGER.info("【工单表单参数校验----------------{}】", errorMsg);throw new FormValidException(errorMsg);}LOGGER.info("【工单表单参数校验----------------完毕】");}
}

以下代码仅供参考 无复制价值

package com.lienbo.interceptor;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;/*** 通用逻辑验证 验证手机认证 验证手机验证* * @author lienbo*/
@Aspect
@Component
@Order(2)
public class WoVerifyInterceptor {private final static Logger LOGGER = LoggerFactory.getLogger(HttpRequestInterceptor.class);/** 获取vo中的 phone 属性的值 */private final static String PHONE = "phone";/** 获取vo中的 askAccount 属性的值 */private final static String ASK_ACCOUNT = "askAccount";/** 获取vo中的 verifyCode 属性的值 */private final static String VERIFY_CODE = "verifyCode";/** 获取vo中的 isNeedAuthPhone 方法的返回值 */private final static String IS_NEED_AUTH_PHONE = "isNeedAuthPhone";@AutowiredAgentService agentService;/*** <p>* 方法说明 : 切点* </p>*/@Pointcut("@annotation(com.lienbo.interceptor.WorkOrderVerify)")public void pointcut() {}/*** * <p>* 方法说明 : 环绕切面* </p>** @param joinPoint*            void*/@Around("pointcut()")public void verifyByAgent(JoinPoint joinPoint) {LOGGER.info("【WorkOrderVerify 工单认证和短信验证码验证 ------------ 验证开始】");// 获取参数 PHONE ASK_ACCOUNT VERIFY_CODE IS_NEED_AUTH_PHONEMap<String, String> voValueMap = getVoValueMap(joinPoint);String string = voValueMap.get(IS_NEED_AUTH_PHONE);LOGGER.info("【WorkOrderVerify IS_NEED_AUTH_PHONE={}】", string);WoWorkOrder wo = new WoWorkOrder();if (StringUtils.isNotBlank(string) && "true".equals(string)) {// 方法说明 : 获取手机认证信息并设置到wo_work_orderLOGGER.info("【获取手机认证信息并设置到wo_work_order】");wo = verifyAuth(voValueMap);// 方法说明 : 验证 认证手机账户 的短信验证码;业务要求 接收验证码的手机号码必须是认证手机号码agentService.verifrAuthPhoneMessageCaptcha(voValueMap.get(ASK_ACCOUNT), voValueMap.get(VERIFY_CODE),voValueMap.get(PHONE));} else {LOGGER.info("【WorkOrderVerify  不需要验证认证手机号码和接收验证码手机号码是否一致】");if (StringUtils.isNotBlank(voValueMap.get(VERIFY_CODE))&& StringUtils.isNotBlank(voValueMap.get(PHONE))) {boolean result = agentService.verifyMessageCaptcha(voValueMap.get(VERIFY_CODE), voValueMap.get(PHONE));if (!result) {throw new BizException("验证码验证失败");}}}// 方法说明 : 从VO表单获取数据保存到wo_work_order中LOGGER.info("【从VO表单获取数据保存到wo_work_order中】");setWoWithVo(joinPoint, wo);LOGGER.info("【WorkOrderVerify 工单认证和短信验证码验证------------ 验证完成】");}/*** * <p>* 方法说明 : 从VO表单获取数据保存到wo_work_order中* </p>** @param joinPoint* @param wo* @return WoWorkOrder*/private WoWorkOrder setWoWithVo(JoinPoint joinPoint, WoWorkOrder wo) {Object[] args = joinPoint.getArgs();if (args == null || args.length < 1) {LOGGER.info("【获取方法参数失败】");return wo;}List<Object> argsList = Arrays.asList(args);// 表单VO均实现了 CreateWorkOrderVo 接口,对参数进行过滤List<Object> list = argsList.stream().filter(x -> x instanceof CreateWorkOrderVo).collect(Collectors.toList());// 一个工单只用一个 VO 对象提交if (list.size() != 1) {LOGGER.info("【获取表单vo失败:无实现CreateWorkOrderVo的VO对象】");return wo;}Object obj = list.get(0);Class<?> clz = obj.getClass();Field[] fields = clz.getDeclaredFields();for (Field field : fields) {// 获取属性的名字String name = field.getName();if (WO.equals(name)) {// 将属性的首字符大写, 构造get,set方法String suffix = name.substring(0, 1).toUpperCase()+ name.substring(1);// 获取属性的类型String type = field.getGenericType().toString();// 如果type是wo_work_order类型,则前面包含"class ",后面跟类名 String 类型if (type.equals("class com.lienbo.beans.wo.WoWorkOrder")) {try {Method m = clz.getMethod("set" + suffix,WoWorkOrder.class);LOGGER.info("【为wo赋值{}】", wo);return (WoWorkOrder) m.invoke(obj, wo);} catch (Exception e) {e.printStackTrace();}}break;}}return wo;}/*** * <p>* 方法说明 : 获取手机认证信息并设置到wo_work_order* </p>** @param voValueMap* @return WoWorkOrder*/private WoWorkOrder verifyAuth(Map<String, String> voValueMap) {// 获取手机认证信息 认证时间 已认证时间ResultBean<AuthPhoneBean> userPhone = agentService.verifyAuthPhone(voValueMap.get(ASK_ACCOUNT).toString());WoWorkOrder wo = new WoWorkOrder();LOGGER.info("【userPhone={} 】", userPhone);if (userPhone.isSuccess()) {if (PhoneAuthStatus.AUTHFINISH.equals(userPhone.getData().getStatus())|| PhoneAuthStatus.AUTHING.equals(userPhone.getData().getStatus())) {wo.setIsAuthPhone(true);wo.setPhoneAuthTime(userPhone.getData().getValidateTime());wo.setPhoneAuthDiffday(userPhone.getData().getPhoneAuthDiffday());LOGGER.info("【设置认证手机账号setIsAuthPhone={},setPhoneAuthTime={},setPhoneAuthDiffday={}】",true, userPhone.getData().getValidateTime(),userPhone.getData().getPhoneAuthDiffday());return wo;}}LOGGER.info("【设置未认证手机账号默认值】");wo.setIsAuthPhone(DefaultCode.DEFAULT_IS_AUTH_PHONE);wo.setPhoneAuthTime(DefaultCode.DEFAULT_PHONE_AUTH_TIME);wo.setPhoneAuthDiffday(DefaultCode.DEFAULT_PHONE_AUTH_DIFF_DAY);return wo;}/*** * <p>* 方法说明 : 从VO获取 PHONE VERIFY_CODE ASK_ACCOUNT 的值* </p>** @param joinPoint* @return Map<String,String>*/private Map<String, String> getVoValueMap(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();if (args == null || args.length < 1) {LOGGER.info("【获取方法参数失败】");return Collections.emptyMap();}List<Object> argsList = Arrays.asList(args);// 表单VO均实现了 CreateWorkOrderVo 接口,对参数进行过滤List<Object> list = argsList.stream().filter(x -> x instanceof CreateWorkOrderVo).collect(Collectors.toList());// 一个工单只用一个 VO 对象提交if (list.size() != 1) {LOGGER.info("【获取表单vo失败:无实现CreateWorkOrderVo的VO对象】");return Collections.emptyMap();}Map<String, String> map = new HashMap<>();Object obj = list.get(0);Class<?> clz = obj.getClass();try {Method m = clz.getMethod(IS_NEED_AUTH_PHONE);map.put(IS_NEED_AUTH_PHONE, m.invoke(obj).toString());} catch (Exception e) {e.printStackTrace();}Field[] fields = clz.getDeclaredFields();for (Field field : fields) {// 获取属性的名字String name = field.getName();if (PHONE.equals(name) || VERIFY_CODE.equals(name)|| ASK_ACCOUNT.equals(name)) {// 将属性的首字符大写, 构造get,set方法String suffix = name.substring(0, 1).toUpperCase()+ name.substring(1);// 获取属性的类型String type = field.getGenericType().toString();// 如果type是字符串类型,则前面包含"class ",后面跟类名 String 类型if (type.equals("class java.lang.String")) {try {Method m = clz.getMethod("get" + suffix);String value = m.invoke(obj).toString();map.put(name, value);} catch (Exception e) {e.printStackTrace();}}} else {continue;}}return map;}}

以下代码仅供参考 无复制价值

    @WorkOrderVerify@PostMapping("resume/info/createResume")public ResultBean<String> saveResume(@Valid CreateResumeVo vo, BindingResult result) {resumeService.saveWorkOrder(wo);return ResultBean.ok("SUCCESS", null);}

转载于:https://my.oschina.net/u/3418748/blog/1596327

多层AOP 解决AOP执行顺序相关推荐

  1. react学习(50)--解决异步执行顺序问题

    this.props.dispatch({type: 'activity/addActivityPopup',payload: params,callback: (res) => {if (re ...

  2. linux shell顺序执行,shell 执行顺序

    shell script 到今天,我还只能一个劲顺序执行,尝试探索下其更加强大的功能. 一个主文件 main ,三个调用文件 shell1.shell2.shell3,调用文件差别仅仅在于显示内容不同 ...

  3. java 判断顺序_通过指令码来判断Java代码的执行顺序(++问题与return和finally的问题)...

    问题 在<深入理解Java虚拟机>一书中遇到了如下代码: public int method() { int i; try { i = 1; return i; } catch (Exce ...

  4. Spring AOP之坑:完全搞清楚advice的执行顺序

    目录 文章目录 目录 AOP的核心概念 模拟aspect advice的执行过程 同一aspect,不同advice的执行顺序 不同aspect,advice的执行顺序 同一aspect,相同advi ...

  5. spring aop的@Before,@Around,@After,@AfterReturn,@AfterThrowing执行顺序

    1.AOP的基本概念 切面(Aspect) :通知和切入点共同组成了切面(aspect).可以从注解方式来理解,代码如下. @aspect为类上面的注解--切面  @pointcut(-)--切入点. ...

  6. Spring Aop 常见注解和执行顺序

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:juejin.cn/post/7062506923194581029 Spring 一开始最强大的就是 IOC / AOP 两 ...

  7. 顺序执行_执行流程 | 你真的了解Spring AOP的执行顺序吗?

    Hi! 我是小小,我们又见面了,今天的主要内容是,你真的了解Spring AOP的执行顺序吗?跟随着我的脚步,一块丈量世界,了解世界,重新认识,重新了解Spring AOP的执行顺序. 聊一聊毕业四个 ...

  8. gtw-050090|执行拦截器时发生异常_执行流程 | 你真的了解Spring AOP的执行顺序吗?...

    Hi! 我是小小,我们又见面了,今天的主要内容是,你真的了解Spring AOP的执行顺序吗?跟随着我的脚步,一块丈量世界,了解世界,重新认识,重新了解Spring AOP的执行顺序. 聊一聊毕业四个 ...

  9. 你真的确定Spring AOP的执行顺序吗

    本文内容重点: 问题描述 Spring AOP执行顺序 探究顺序错误的真相 代码验证 结论   问题描述 公司新项目需要搭建一个新的前后分离HTTP服务,我选择了目前比较熟悉的SpringBoot W ...

最新文章

  1. 最近邻插值实现:图像任意尺寸变换
  2. 关于网站根目录下面robots.txt文件的作用
  3. java反射有什么用_java反射的作用知识点总结
  4. 安卓案例:演示广播接受者
  5. zip安装mysql没有软件,windows10系统安装mysql-8.0.13(zip安装) 的教程详解
  6. [BZOJ]1003 物流运输(ZJOI2006)
  7. paip.TechExcel DevSuite IIS 根目录结构
  8. 计算机CG技术未来发展前景,CG就业前景怎么样?
  9. Java算法-堆排序
  10. C语言烟花代码,C语言实现烟花表白代码
  11. c语言编程简单教学,C语言入门教程-最简单的C程序
  12. 时钟的同步与异步问题
  13. 微分几何、黎曼几何思想
  14. Failed to load C:\SDK\android-sdk-windows\build-tools\27.0.2\lib\dx.jar
  15. 51Talk-Level 7 Unit 2 L3
  16. css-图片闪烁效果
  17. Python成品:运用turtle模块绘画
  18. 刑事犯罪中连续犯与继续犯的区分
  19. 雷电2接口_中国连城 | 总结关于USB、TypeC、雷电接口的冷知识
  20. 电脑上的计算机可以加密码,如何给电脑上的文件夹加密

热门文章

  1. SpringBoot实用小技巧之动态设置SpringBoot日志级别
  2. Exchange Log Collector Script
  3. 用perl获取可用的代理服务器地址
  4. Scala学习(二)练习
  5. SCVMM2008的P2V后 MAC地址冲突
  6. OPNFV — Overview
  7. 云计算技术 — 云计算的未来
  8. C 语言编程 — uint8_t / uint16_t / uint32_t /uint64_t
  9. Linux 操作系统原理 — 零拷贝技术
  10. BC26通过MQTT协议连接ONENET,AT流程