SpringBoot自定义注解实现防止接口重复访问

需求

接口或者表单不允许重复访问或提交。

实现

  • 用户每次登录系统获得JSESSION_ID
  • 每次访问自选时携带JSESSION_ID
  • 编写自定义注解JSESSION_ID
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;

 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface RequestLimit {
   /**
    * @timeout 指定时间内不允许重复提交
    **/
   long timeout() default 3000;
 }
  • 通过AOP切面实现功能增强
package com.jeesite.modules.config.aspect;

import com.jeesite.modules.config.annotation.RequestLimit;
import com.jeesite.modules.yige.app.bean.AppResult;
import org.aspectj.lang.ProceedingJoinPoint;
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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class RequestLimitAspect {

    /**
     * 横切点
     * @param requestLimit
     */
    @Pointcut("@annotation(requestLimit)")
    public void repeatPoint(RequestLimit requestLimit) {
    }

    @Around(value = "repeatPoint(requestLimit)")
    public Object requestLimit(ProceedingJoinPoint joinPoint, RequestLimit requestLimit) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        ServletContext servletContext = request.getServletContext();
        Map limits = (Map) servletContext.getAttribute("requestLimits");
        String[] keys = request.getParameterMap().get("__sid");
        String key = null;
        if(keys != null){
            key = keys[0];
            if(limits == null){
                limits = new HashMap<>();
            }
            Long time = limits.get(key);
            if(time != null && System.currentTimeMillis() - time < requestLimit.timeout()){
                return AppResult.fail("访问频繁,请稍后重试!");
            }
        }
        if(key != null){
            limits.put(key,System.currentTimeMillis());
        }
        return joinPoint.proceed();
    }

}

  • 使用
@RestController
@RequestMapping(value = "board")
public class BoardController{

    @Autowired
    private BoardService boardService;

    @RequestLimit(timeout = 1000)
    @RequestMapping(value = "orderTrace")
    public AppResult orderTraceData(){
        return AppResult.success(boardService.orderTrace());
    }

你可能感兴趣的:(SpringBoot自定义注解实现防止接口重复访问)