1.自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE}) // 作用到方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
/**
* TODO
*
* @author songtianxiong
* @version 1.0
* @date 2021/11/18 10:14
*/
public @interface RepeatSubmit {
}
2.拦截器(redis失效时间来控制)
package com.lc.gansu.framework.core;
import com.lc.gansu.framework.utility.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* TODO
*
* @author songtianxiong
* @version 1.0
* @date 2021/11/18 10:34
*/
// 设置自定义拦截器
@Slf4j
@Component
public class RepeatSubmitInterceptor extends HandlerInterceptorAdapter {
@Resource
private RedisTemplate<String, String> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
// 判断请求的方法是否被自定义的注解标记
// HandlerMethod handlerMethod = (HandlerMethod) handler;
// Method method = handlerMethod.getMethod();
// RepeatSubmit methodAnnotation = method.getAnnotation(RepeatSubmit.class);
RepeatSubmit methodAnnotation = ((HandlerMethod) handler).getMethodAnnotation(RepeatSubmit.class); //方法注解
RepeatSubmit classAnnotation = ((HandlerMethod) handler).getBean().getClass().getAnnotation(RepeatSubmit.class); //类注解
if (Objects.nonNull(methodAnnotation) || Objects.nonNull(classAnnotation)) {
// 验证是否为重复性请求
if (this.isRepeatSubmit(request, response))
return false;
return true;
}
return true;
} else {
return super.preHandle(request, response, handler);
}
}
public boolean isRepeatSubmit(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (Objects.isNull(redisTemplate)) {
redisTemplate = (RedisTemplate<String, String>) SpringContextUtil.getBean("redisTemplate");
}
String authenticationOfjwt = request.getHeader("jwt");
String url = request.getRequestURL().toString();
String old = redisTemplate.opsForValue().get(RedisKey.getJwtAndUrl(authenticationOfjwt, url));
if (Objects.nonNull(old)) {
log.info("{}被拦截", url);
return true;
}
redisTemplate.opsForValue().set(RedisKey.getJwtAndUrl(authenticationOfjwt, url), "1", 1, TimeUnit.SECONDS);
return false;
}
}
3.拦截器里无法获取spring管理的bean
package com.lc.gansu.framework.utility;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* TODO 通过name方式获取spring里管理的bean(getBean因为返回值是object所以调用后需要强转)
*
* @author songtianxiong
* @version 1.0
* @date 2021/9/24 11:08
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* 获得spring上下文
*
* @return ApplicationContext spring上下文
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 获取bean
*
* @param name service注解方式name为小驼峰格式
* @return Object bean的实例对象
*/
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException {
return applicationContext.getBean(clz);
}
}
4.加在方法上