使用Spring AOP註解方式實現表單重複提交驗證功能
阿新 • • 發佈:2019-01-04
防重複提交常見解決方案:http://patrick002.iteye.com/blog/2197521
定義註解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FormRepeatSubmitValidation {
String value() default "表單重複提交驗證";
}
定義切面
新增配置spring-aop.xml@Aspect @Component public class FormRepeatSubmitAspect { /** * 日誌記錄 */ private static final Logger logger = LoggerFactory.getLogger(FormRepeatSubmitAspect.class); @Autowired private RedisTemplate<String, Object> redisTemplate; /** * 定義切入點 */ @Pointcut("@annotation(com.geekymv.FormRepeatSubmitValidation)") public void doAspect() { } @Before("doAspect()") public void doBefore(JoinPoint pjp) { Object[] args = pjp.getArgs(); MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); Object target = pjp.getTarget(); String params = JSON.toJSONString(args); if(logger.isDebugEnabled()) { logger.debug("before methodName: {}", method.getName()); logger.debug("before args: {}", params); logger.debug("before target: {}", target); } boolean flag = method.isAnnotationPresent(FormRepeatSubmitValidation.class) ; if(flag) { FormRepeatSubmitValidation formRepeatSubmitValidation = method.getAnnotation(FormRepeatSubmitValidation.class); logger.info("FormRepeatSubmitValidation-->{}", formRepeatSubmitValidation.value()); // 將入參作為key自增值存入redis ValueOperations<String, Object> value = redisTemplate.opsForValue(); Long result = value.increment(params, 1); // 判斷返回值是否大於1,如果是則重複提交 if(result > 1) { throw new BaseException(ErrorMessage.FORM_REPEAT_SUBMIT); } redisTemplate.expire(params, 5, TimeUnit.SECONDS); // 設定過期時間5秒 } } @After("doAspect()") public void doAfter(JoinPoint pjp) { Object[] args = pjp.getArgs(); MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); Object target = pjp.getTarget(); String params = JSON.toJSONString(args); if(logger.isDebugEnabled()) { logger.debug("after methodName: {}", method.getName()); logger.debug("after args: {}", params); logger.debug("after target: {}", target); } boolean flag = method.isAnnotationPresent(FormRepeatSubmitValidation.class) ; if(flag) { // 清除redis中key為入參的資料,對於引用型別的變數有可能在業務程式碼中被修改 redisTemplate.delete(params); } } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 啟動@AspectJ支援 --> <aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true" /> </beans>