Redis 計數器 高併發的應用
阿新 • • 發佈:2018-11-28
計數器的基本使用
/**
* 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);
}
}