创建AutoIdempotent 拦截注解,后面使用在方法直接注解即可
@Target(ElementType.METHOD) //应用在方法级别上
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface AutoIdempotent {
}
创建拦截器
public class AutoIdempotentInterceptor implements HandlerInterceptor{
@Autowired
private TokenServiceImpl tokenService; //token生成类
/**
* 预处理
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
//被ApiIdempotment标记的扫描
AutoIdempotent methodAnnotation = method.getAnnotation(AutoIdempotent.class);
if (methodAnnotation != null) {
try {
return tokenService.checkToken(request);// 幂等性校验, 校验通过则放行, 校验失败则抛出异常, 并通过统一异常处理返回友好提示
}catch (Exception ex){
response.setContentType("text/html;charset=UTF-8");
Map<String,Object> responseData = new HashMap<>();
Map<String,Object> map = new HashMap<>();
if(ex instanceof BusinessException){
BusinessException businessException = (BusinessException) ex;//自定义异常类
responseData.put("code",businessException.getCode());
responseData.put("msg",businessException.getMsg());
}else {
responseData.put("code",EmCommonError.SYSTEM_EXCEPTION.getCode());
responseData.put("msg",EmCommonError.SYSTEM_EXCEPTION.getMsg());
}
map.put("status","success");
map.put("data",responseData);
writeReturnJson(response, JSON.toJSONString(map));
}
}
//必须返回true,否则会被拦截一切请求
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
/**
* 返回的json值
* @param response
* @param json
* @throws Exception
*/
private void writeReturnJson(HttpServletResponse response, String json) throws Exception{
response.setContentType("text/html;charset=UTF-8");
PrintUtil printUtil = new PrintUtil(response); //统一print格式返回类处理返回前端json数据
printUtil.print(json);
}
}
注册拦截器
/**
* 设置拦截路径
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(exceptionInterceptor()).addPathPatterns("/**"); //其他异常的拦截器,此处不用管
registry.addInterceptor(autoIdempotentInterceptor()).addPathPatterns("/**");
}
}
controller处使用,需要防止重复提交表单的方法@AutoIdempotent 注解即可
/*
* @RequestBody ShopModel shopModel 接收前端post请求的参数,
* @RequestHeader(name="token")接收前端request.header请求头的token
* @AutoIdempotent //此处防重方法注解
*/
@PostMapping("setShop")
@AutoIdempotent
@ResponseBody
public CommonReturnType setShop(@RequestBody ShopModel shopModel,@RequestHeader(name = "token") String myHeader,HttpServletResponse response) throws BusinessException{
public class MyConstants {
public static final String Constant_TOKEN_PREFIX_USER = "user:";
public static final String Constant_TOKEN_NAME = "token";
public static final String Constant_NO_TOKEN = "参数不合法";
public static final String Constant_REPETITIVE_OPERATION = "重复性操作";
}
public interface EmBase {
public int getCode();
public String getMsg();
public EmBase setMsg(String msg);
}
public enum EmUser implements EmBase {
GET_TOKEN_SUCCESS(11001,"获取token成功"),//for-api
;
private Integer code;
private String msg;
private EmUser(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
@Override
public EmBase setMsg(String msg) {
this.msg = msg;
return this;
}
}
public enum EmUserError implements EmBase {
NO_TOKEN_EXCEPTION(1009,"参数不合法"),
REPETITIVE_OPERATION(1010,"重复提交了,请稍等"),;
private Integer code;
private String msg;
private EmUserError(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
@Override
public EmBase setMsg(String msg) {
this.msg = msg;
return this;
}
}
此外:
token生成工具类
public class TokenService
redis工具类
public class RedisUtil
如果需要全部文件请到csdn下载。