access times limit

原创
2016/01/20 21:01
阅读数 61


//

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

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface PostTimesLimitContainer {

    PostTimesLimit[] value();

}


//

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"/>


展开阅读全文
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部