代码案列
配置Redis
@Slf4j
@Configuration
@EnableCaching // 开启缓存支持
public class RedisConfiguration extends CachingConfigurerSupport {
/**
* RedisTemplate配置
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(getJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(getJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private Jackson2JsonRedisSerializer<Object> getJackson2JsonRedisSerializer() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
return jackson2JsonRedisSerializer;
}
}
创建注解
@Target(value ={ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IpLimit {
}
添加拦截器
@Slf4j
@Component
public class IpLimitInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod;
try {
handlerMethod = (HandlerMethod) handler;
} catch (Exception e) {
this.checkFailResponse(response , "请求资源不存在");
return false;
}
//获取类上的注解 获取方法上注解
IpLimit ipLimit = handlerMethod.getBeanType().getAnnotation(IpLimit.class)==null?handlerMethod.getMethodAnnotation(IpLimit.class):handlerMethod.getBeanType().getAnnotation(IpLimit.class);
if(ipLimit==null){
return true;
}else{
//获取请求ip
String remoteAddr = request.getRemoteAddr();
//设置key ,key = 方法名 + ip地址,如果是想改成规定时间请求接口总数为5次,不加方法名即可
String key =handlerMethod.getMethod().getName()+":"+remoteAddr;
String s = redisTemplate.opsForValue().get(key);
log.info("ip limit key : {}",key);
if(ObjectUtil.isNotEmpty(s) && Integer.parseInt(s) >= 5){
this.checkFailResponse(response , "请求资源过于频繁,请稍后再试");
return false;
} else {
if(ObjectUtil.isEmpty(s)){
redisTemplate.opsForValue().set(key , String.valueOf(1), 10 , TimeUnit.SECONDS);
}else {
redisTemplate.opsForValue().set(key , String.valueOf(Integer.parseInt(s)+1), 10 , TimeUnit.SECONDS);
}
return true;
}
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
private void checkFailResponse(HttpServletResponse response , String message) throws Exception{
response.setHeader("Content-Type","application/json;charset=utf-8");
response.getWriter().print(message);
response.getWriter().flush();
}
}
将注解添加到接口或者接口类即可