1. 程式人生 > >Redis 計數器 高併發的應用

Redis 計數器 高併發的應用

 計數器的基本使用

    /**
     * redis計數器
     * @param key 鍵
     * @return
     */
    public Long test(String key){
        //key為key,delta為遞增數目,返回值為增長後的數量。
        Long increment = redisTemplate.opsForValue().increment(key, 1);
        return increment;
    }

 

 簡訊傳送請求次數限制

    /**
     *  簡訊驗證碼請求次數限制
     * @param mobile
     * @return
     */
    public String sendVerifyCode(String mobile){
        Long increment = redisTemplate.opsForValue().increment(mobile, 1);
        if (increment == 1) {
            //設定有效期一分鐘
            redisTemplate.expire(mobile, 60, TimeUnit.SECONDS);
        }
        if (increment > 1) {
            return "每分鐘只能傳送一次簡訊";
        }

        //傳送驗證碼


        return "驗證碼已傳送";
    }

IP請求次數限制

定義訊息傳送類

/**
 * 攔截器訊息傳送
 * @author 向振華
 * @date 2018/11/28 10:52
 */
public class BaseInterceptor extends HandlerInterceptorAdapter {

    /**
     * 傳送異常資訊
     * @param request
     * @param response
     * @param code
     * @param msg
     * @param data
     */
    public void sendMsg(HttpServletRequest request, HttpServletResponse response, int code, String msg, String data) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        //封裝成返回給前端的固定格式
        ResponseMessage responseMessage = new ResponseMessage(code, msg, data);
        String jsonObject = JSONObject.toJSONString(responseMessage);
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.append(jsonObject);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}
@Data
public class ResponseMessage<T> implements Serializable {
    private static final long serialVersionUID = -2988364810346364595L;

    /**
     * 1:成功 -1:失敗
     */
    private int code;
    /**
     * 錯誤資訊
     */
    private String errorMsg;
    /**
     * 返回資料
     */
    private T data;

    public ResponseMessage(int code, String errorMsg, T data) {
        this.code = code;
        this.errorMsg = errorMsg;
        this.data = data;
    }

    public ResponseMessage(int code, String errorMsg) {
        this.code = code;
        this.errorMsg = errorMsg;
    }

    public ResponseMessage() {
    }
}

攔截器編寫

/**
 * IP請求次數限制
 * @author 向振華
 * @date 2018/11/28 10:55
 */
public class CounterInterceptor extends BaseInterceptor {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = getRemoteHost(request);
        String key = ip + request.getRequestURI() + request.getSession().getId();
        Long increment = redisTemplate.opsForValue().increment(key, 1);
        if (increment == 1) {
            //設定有效期一分鐘
            redisTemplate.expire(key, 60, TimeUnit.SECONDS);
        }
        //次數限制為5次
        if (increment > 5) {
            sendMsg(request, response, -1, "次數限制", request.getRequestURI());
            return false;
        }
        return true;
    }

    /**
     * 獲取請求IP地址
     * @param request
     * @return
     */
    public String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }
}

攔截器配置

/**
 *  攔截器配置
 * @author 向振華
 * @date 2018/11/28 11:30
 */
@Configuration
@EnableTransactionManagement
public class MyWebAppConfig extends WebMvcConfigurerAdapter {

    @Bean
    CounterInterceptor counterInterceptor() {
        return new CounterInterceptor();
    }

    /**
     * 攔截器配置
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //配置IP請求次數限制
        registry.addInterceptor(counterInterceptor());

        super.addInterceptors(registry);
    }
}