All Downloads are FREE. Search and download functionalities are using the official Maven repository.

wang.ramboll.extend.request.limit.autoconfigure.RequestLimitAutoConfiguration Maven / Gradle / Ivy

The newest version!
package wang.ramboll.extend.request.limit.autoconfigure;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import wang.ramboll.extend.basic.content.SpringBeanNames;
import wang.ramboll.extend.basic.exception.ExtendRuntimeException;
import wang.ramboll.extend.data.cache.CacheWrapper;
import wang.ramboll.extend.data.cache.autoconfigure.CacheAutoConfiguration;
import wang.ramboll.extend.request.limit.RequestFrequencyLimitAnnotationScanner;
import wang.ramboll.extend.request.limit.filter.ServletRequestFilter;
import wang.ramboll.extend.request.limit.interceptor.RequestFrequencyLimitInterceptor;
import wang.ramboll.extend.request.limit.interceptor.RequestFrequencyLimitWork;
import wang.ramboll.extend.request.limit.wrapper.LimitReturnObjWrapper;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 请求防刷/限量拦截自动配置类
 * @author WangRuibo
 */
@Configuration(
        proxyBeanMethods = false
)
@EnableConfigurationProperties(RequestLimitProperties.class)
@ConditionalOnMissingBean(RequestLimitAutoConfiguration.class)
@DependsOn(SpringBeanNames.DATA_CACHE_WRAPPER_BEAN_NAME)
@AutoConfigureAfter(CacheAutoConfiguration.class)
public class RequestLimitAutoConfiguration implements WebMvcConfigurer {
    private static final Logger logger = LoggerFactory.getLogger(RequestLimitAutoConfiguration.class);
    private static final String REQUEST_FREQUENCY_LIMIT_KEY_TEMPLATE = "RAMBOLL_REQUEST_FREQUENCY_LIMIT:%s";

    private RequestLimitProperties requestLimitProperties ;

    private CacheWrapper cacheWrapper;

    private LimitReturnObjWrapper defaultReturnObj = new LimitReturnObjWrapper();

    /**
     * 请求防刷/限量拦截自动配置类 构造器
     */
    @Autowired
    public RequestLimitAutoConfiguration(RequestLimitProperties requestLimitProperties,@Qualifier(SpringBeanNames.DATA_CACHE_WRAPPER_BEAN_NAME) CacheWrapper cacheWrapper) {
        logger.info("Init RequestLimitAutoConfiguration...");
        this.requestLimitProperties = requestLimitProperties;
        this.cacheWrapper = cacheWrapper;
    }

    @ConditionalOnProperty(name = "wang.ramboll.request.limit.use-fail-return-bean",havingValue = "true")
    @DependsOn(SpringBeanNames.REQUEST_LIMIT_DEFAULT_FAIL_RETURN_BEAN_NAME)
    @Bean(name = SpringBeanNames.REQUEST_LIMIT_DEFAULT_FAIL_RETURN_BEAN_NAME + ".TEMP")
    public Object setDefaultReturnObj(@Qualifier(SpringBeanNames.REQUEST_LIMIT_DEFAULT_FAIL_RETURN_BEAN_NAME) Object defaultReturnObj) {
        logger.info("Auto set DefaultLimitReturnBean ... ");
        this.defaultReturnObj.setObj(defaultReturnObj);
        return this.defaultReturnObj;
    }

    @Bean(name = SpringBeanNames.HTTP_SERVLET_REQUEST_FILTER)
    @ConditionalOnMissingBean(name = SpringBeanNames.HTTP_SERVLET_REQUEST_FILTER)
    public ServletRequestFilter servletRequestFilter(){
        logger.info("Init ServletRequestFilter...");
        return new ServletRequestFilter();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        try {
            if(requestLimitProperties.isEnable()){
                List scanRequestLimitAnnotationMappingUrlList = RequestFrequencyLimitAnnotationScanner.scanRequestFrequencyLimitAnnotationMappingUrl(requestLimitProperties.getControllerPackageArray());
                if(scanRequestLimitAnnotationMappingUrlList.size()>0){
                    scanRequestLimitAnnotationMappingUrlList.forEach(s->logger.info("Find request mapping url with @RequestFrequencyLimit -> {}",s));
                    if(requestLimitProperties.isUseFailReturnBean()){
                        logger.info("Use user set default-limit-return-bean -> {}",SpringBeanNames.REQUEST_LIMIT_DEFAULT_FAIL_RETURN_BEAN_NAME);
                    } else if(null!=requestLimitProperties.getDefaultLimitReturnClass()){
                        logger.info("Use user set default-limit-return-class -> {}",requestLimitProperties.getDefaultLimitReturnClass());
                        defaultReturnObj.setObj(requestLimitProperties.getDefaultLimitReturnClass().newInstance());
                    } else {
                        logger.info("Use default default-limit-return-class -> {}",DefaultLimitReturn.class.getName());
                        logger.info("Use default default-limit-return-code -> {}",requestLimitProperties.getDefaultLimitReturnCode());
                        logger.info("Use default default-limit-return-message -> {}",requestLimitProperties.getDefaultLimitReturnMessage());
                        defaultReturnObj.setObj(new DefaultLimitReturn(requestLimitProperties.getDefaultLimitReturnCode(),requestLimitProperties.getDefaultLimitReturnMessage()));
                    }
                    logger.info("Add RequestFrequencyLimitInterceptor ...");
                    registry.addInterceptor(new RequestFrequencyLimitInterceptor(new RequestFrequencyLimitWork() {
                        @Override
                        public boolean work(String unionContent, long delay, long maxTimes) {
                            String cacheKey = String.format(REQUEST_FREQUENCY_LIMIT_KEY_TEMPLATE,unionContent);
                            if(cacheWrapper.getCacheOperations().get(cacheKey)==null){//没有拦截,创建记录,放行
                                cacheWrapper.getCacheOperations().increment(cacheKey,delay,TimeUnit.MILLISECONDS);
                                return true ;
                            } else {//有记录增加次数
                                Long l = cacheWrapper.getCacheOperations().increment(cacheKey,delay,TimeUnit.MILLISECONDS);
                                if(l>maxTimes) return false ;//超出限制,拦截
                                else return true ;//未超出,放行
                            }
                        }

                        @Override
                        public void cancelLimit(String unionContent, long maxTimes) {
                            if(maxTimes>1){
                                //解除拦截
                                cacheWrapper.getCacheOperations().remove(String.format(REQUEST_FREQUENCY_LIMIT_KEY_TEMPLATE,unionContent));
                            }
                        }
                    }, defaultReturnObj)).addPathPatterns(scanRequestLimitAnnotationMappingUrlList);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            throw new ExtendRuntimeException(e.getMessage(),e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy