access times limit


//java

import com.XXX.base.annotation.safety.PostTimesLimit;redis

import java.lang.annotation.ElementType;spring

import java.lang.annotation.Retention;apache

import java.lang.annotation.RetentionPolicy;app

import java.lang.annotation.Target;post


@Retention(RetentionPolicy.RUNTIME)url

@Target({ElementType.METHOD})spa

public @interface PostTimesLimitContainer {.net

    PostTimesLimit[] value();code

}


//

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import org.springframework.core.annotation.Order;


@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

@Documented

@Order(-2147483648)

public @interface PostTimesLimit {

    int count() default 2147483647;


    long time() default 60000L;


    String key();

}




//

import com.XXX.base.annotation.safety.PostTimesLimit;

import com.XXX.base.annotation.safety.PostTimesLimitContainer;

import org.apache.commons.lang3.ArrayUtils;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.core.ValueOperations;

import org.springframework.stereotype.Component;


import javax.servlet.http.HttpServletRequest;

import java.util.concurrent.TimeUnit;


@Aspect

@Component

public class PostTimesLimitAspect {

    private final static org.slf4j.Logger logger = LoggerFactory.getLogger(PostTimesLimitAspect.class);


    @Autowired

    private RedisTemplate redisTemplate;


    private void limit(PostTimesLimit limit, String ip, String url) {

        String key = limit.key().concat(url).concat(ip);

        ValueOperations operations= redisTemplate.opsForValue();


        //計數器加一

        long count = operations.increment(key, 1);

        if (count == 1) {

            redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS);

        }

        if (count > limit.count()) {

            String msg = String.format("IP[%s]在規定的時間內[%d]ms,訪問地址[%s]超過了限定的次數[%d]",ip,limit.time(),url,limit.count());

            logger.info(msg);

            throw new PostTimesLimitException(msg);

        }

    }


    // 切面

    //@before  通知

    //"@annotation(limit)" 切入點

    @Before("@annotation(limit)")

    public void postTimesLimit(final JoinPoint joinPoint,PostTimesLimit limit) {


        try {

            Object[] args = joinPoint.getArgs();

            if(ArrayUtils.isEmpty(args)){

                throw new PostTimesLimitException("方法中缺失參數");

            }



            HttpServletRequest request = null;

            for (int i = 0; i < args.length; i++) {

                if (args[i] instanceof HttpServletRequest) {

                    request = (HttpServletRequest) args[i];

                    break;

                }

            }

            if (request == null) {

                throw new PostTimesLimitException("方法中缺失HttpServletRequest參數");

            }

            String ip = getClientIp(request);

            String url = request.getServletPath().toString();


            limit(limit, ip, url);


        } catch (PostTimesLimitException e) {

            throw e;

        } catch (Exception e) {

            logger.error("訪問限制發送錯誤: ", e);

        }

    }



    @Before("@annotation(limits)")

    public void postTimesLimits(final JoinPoint joinPoint,PostTimesLimitContainer limits) throws PostTimesLimitException {

        try {

            Object[] args = joinPoint.getArgs();

            if(ArrayUtils.isEmpty(args)){

                throw new PostTimesLimitException("方法中缺失參數");

            }


            if(limits==null||limits.value()==null){

                throw new PostTimesLimitException("annotation中缺失參數");

            }


            HttpServletRequest request = null;

            for (int i = 0; i < args.length; i++) {

                if (args[i] instanceof HttpServletRequest) {

                    request = (HttpServletRequest) args[i];

                    break;

                }

            }

            if (request == null) {

                throw new PostTimesLimitException("方法中缺失HttpServletRequest參數");

            }

            String ip = getClientIp(request);

            String url = request.getServletPath().toString();



            for (PostTimesLimit limit : limits.value()) {

                limit(limit, ip, url);

            }


        } catch (PostTimesLimitException e) {

            throw e;

        } catch (Exception e) {

            logger.error("訪問限制發送錯誤: ", e);

        }

    }



}


//

@PostTimesLimitContainer({

@PostTimesLimit(key="SMS_60S_Rule",count=1,time=60000),

@PostTimesLimit(key="SMS_5M_Rule",count=3,time=300000),

@PostTimesLimit(key="SMS_1H_Rule",count=30,time=3600000)})

@RequestMapping(value = "/mobile/sendcode", method = RequestMethod.GET)





  <!-- Enable AspectJ style of Spring AOP -->

<aop:aspectj-autoproxy proxy-target-class="true"/>

相關文章
相關標籤/搜索