防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
一、思路:
1、首先自定义注解;
2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor);
3、创建类:配置拦截器路径(拦截URL规则);
二、代码示例:
1、首先自定义注解;
import java.lang.annotation.*;
/**
* @ClassName Resubmit
* @Descripition 自定义注解-防重复提交
* @Author
* @Date 2023/8/31 10:38
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Resubmit {
/**
* 默认过期时间
* 单位:秒
*
* @return
*/
int value() default 100;
/**
* 频繁请求提示语
*
* @return
*/
String messge() default "请求过于频繁,请稍后再试!";
}
2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor);
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName ResubmitInterceptorUtil
* @Descripition 防重复提拦截器工具类
* @Author
* @Date 2023/8/31 10:52
*/
@Slf4j
@Component
public class ResubmitInterceptorUtil implements HandlerInterceptor {
// key: 固定前缀
private static final String FIXED_SESSION = "repeatData";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
try {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 请求方法
Method method = handlerMethod.getMethod();
// 获取自定义注解-防重复注解(@Resubmit)
Resubmit annotation = method.getAnnotation(Resubmit.class);
// 判断方法是否添加自定义注解(@Resubmit)
if (annotation != null) {
//如果重复相同数据
if (repeatDataValidator(request)) {
// 自定义返回结果类
Result result = new Result();
result.setCode(500);
result.setMessage(annotation.messge());
// 设置字符集编码
response.setCharacterEncoding("UTF-8");
// response.getWriter().write(JSON.toJSONString("请勿频繁提交请求,稍后再试."));
response.getWriter().write(JSON.toJSONString(result));
return false;
} else {
return true;
}
}
return true;
} else {
return true;
}
} catch (IOException e) {
log.error("防重复提拦截器工具类异常", e);
return false;
}
}
/**
* 验证同一个url数据是否相同提交,相同返回true
*
* @param request
* @return
*/
private boolean repeatDataValidator(HttpServletRequest request) {
// 获取POST请求体-body-入参
String params = getRequestBodyParam(request);
// 获取请求路径
String url = request.getRequestURI();
Map<String, String> map = new HashMap<>();
// 组装Map key: url、 value:url+请求方法体+时间
map.put(url, params);
String nowUrlParams = JSON.toJSONString(map);
Object preUrlParams = request.getSession().getAttribute(FIXED_SESSION);
//如果上一个数据为null,表示还没有访问页面
if (preUrlParams == null) {
//如果上一个数据为null,表示还没有访问页面
request.getSession().setAttribute(FIXED_SESSION, nowUrlParams);
return false;
} else {
//如果上次url+数据和本次url+数据相同,则表示重复添加数据
if (preUrlParams.equals(nowUrlParams)) {
log.info("[请求频繁提交 repeatDataValidator URL :{}; param :{}]", url, params);
return true;
} else {
//如果上次 url+数据 和本次url加数据不同,则不是重复提交
request.getSession().setAttribute(FIXED_SESSION, nowUrlParams);
return false;
}
}
}
/**
* 获取请求体-body-入参
*
* @param request
* @return
*/
private String getRequestBodyParam(HttpServletRequest request) {
BufferedReader bufferedReader = null;
StringBuffer stringBuffer = new StringBuffer();
try {
bufferedReader = request.getReader();
String str = null;
while ((str = bufferedReader.readLine()) != null) {
stringBuffer.append(str);
}
bufferedReader.close();
} catch (IOException e) {
log.error("解析入参异常!!!", e);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
log.error("解析入参异常!!!", e);
}
}
}
return stringBuffer.toString();
}
}
3、创建类:配置拦截器路径(拦截URL规则);
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @ClassName WebMvcConfig
* @Descripition 配置拦截路径
* @Author
* @Date 2023/9/1 10:08
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private ResubmitInterceptorUtil resubmitInterceptorUtil;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 配置拦截类
registry.addInterceptor(resubmitInterceptorUtil)
// 设置拦截路径URL
.addPathPatterns("/**");
}
}
本文介绍了如何在SpringMVC中使用自定义注解和拦截器来防止重复提交,包括自定义注解的定义、拦截器的实现以及如何配置拦截器以拦截特定URL。
&spm=1001.2101.3001.5002&articleId=132627545&d=1&t=3&u=65e9784eff9e43abacb59a5c459e216d)
796

被折叠的 条评论
为什么被折叠?



