springmvc之表单重复提交问题

表单重复提交问题有多种方法控制,以下主要说明后台控制。

原理:通过唯一标识来判断,通常采用UUID来生成唯一标识。当表单提交时会传一个Token(唯一标识)参数,该参数是保存在后台服务器session中,通过传递的Token值与后台服务器session值作比较来解决该问题,代码如下:

一、声明一个自定义注解类Token
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Token {

	/**
	 * 获取token值
	 * @return
	 */
	boolean token() default false;
	/**
	 * 标识哪些方法需要验证重复提交
	 * @return
	 */
	boolean remove() default false;
}
 
二、声明一个拦截器

public class TokenInterceptor extends HandlerInterceptorAdapter {

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		
		if(handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod)handler;
			Method method = handlerMethod.getMethod();
			Token annotation = AnnotationUtils.findAnnotation(method, Token.class);
			if(annotation != null) {
				boolean isGetToken = annotation.token();
				if(isGetToken) {
					request.getSession(false).setAttribute("token", UUID.randomUUID().toString());
				}
				boolean isRemoveSession = annotation.remove();
				if(isRemoveSession) {
					if(isRepeatSubmit(request)) {
						return false;
					}
					request.getSession(false).removeAttribute("token");
				}
			}
		    return true;	
		} else{
			return super.preHandle(request, response, handler);
		}
	}

	private boolean isRepeatSubmit(HttpServletRequest request) {
		
		String serverToken = (String) request.getSession(false).getAttribute("token");
		if(serverToken == null) {
			return true;
		}
		String clientToken = request.getParameter("token");
		if(clientToken == null) {
			return true;
		}
		if(!serverToken.equals(clientToken)) {
			return true;
		}
		return false;
	}

}

三、在保存的Controller方法加下@Token注解即可

1.获取UUID方法

	@Token(token = true)
	@RequestMapping(value = "getToken",method = RequestMethod.GET)
	@ResponseBody
	public String getToken(HttpServletRequest request, HttpServletResponse response) {
		
		String token = request.getSession(false).getAttribute("token").toString();
		JsonBean jb = new JsonBean(token, "");
		return getJson(jb); 
	}

2.表单提交的方法(父类)
	@Token(remove = true)
	@RequestMapping(method = { RequestMethod.POST })
	@ResponseBody
	public String create(HttpServletRequest request, HttpServletResponse response, @RequestBody Entity model) {
		throw new UnsupportedOperationException("not yet implement");
	}

说下需要注意的地方:

注意这句代码: Token annotation = AnnotationUtils.findAnnotation(method, Token.class);

这里是通过spring提供的AnnotationUtils类来获取方法上声明的注解类,非Token annotation = method.getAnnotation(Token.class);

因为我们要拦截的表单请求Controller的Token注解是写在父类上,如果使用method.getAnnotation(Token.class)会得不到该Token值,如果该注解不是写在父类上,则两种方式都没问题。


微笑

CSDN第一篇博客,写得不好的地方请见谅哈。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值