好的,下面來講一下如何在Spring MVC里面解決此問題(其它框架也一樣,,邏輯一樣,,思想一樣,和具體框架沒什么關(guān)系),。要解決重復(fù)提交,,有很多辦法,比如說在提交完成后redirect一下,,也可以用本文提到的使用token的方法(我不使用redirect是因為那樣解決不了ajax提交數(shù)據(jù)或者移動應(yīng)用提交數(shù)據(jù),,另一個原因是現(xiàn)在比較通行的方法是使用token,像python里的django框架也是使用token來解決),。
使用token的邏輯是,,給所有的url加一個攔截器,在攔截器里面用java的UUID生成一個隨機(jī)的UUID并把這個UUID放到session里面,,然后在瀏覽器做數(shù)據(jù)提交的時候?qū)⒋薝UID提交到服務(wù)器,。服務(wù)器在接收到此UUID后,檢查一下該UUID是否已經(jīng)被提交,,如果已經(jīng)被提交,,則不讓邏輯繼續(xù)執(zhí)行下去…
好的,來點實際代碼,,也許實際代碼才是最好的老師:
注解Token代碼:
@Target (ElementType.METHOD)
@Retention (RetentionPolicy.RUNTIME)
public @interface Token {
boolean save() default false ;
boolean remove() default false ;
}
|
攔截器TokenInterceptor代碼:
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 = method.getAnnotation(Token. class );
if (annotation != null ) {
boolean needSaveSession = annotation.save();
if (needSaveSession) {
request.getSession( false ).setAttribute( "token" , UUID.randomUUID().toString());
}
boolean needRemoveSession = annotation.remove();
if (needRemoveSession) {
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 clinetToken = request.getParameter( "token" );
if (clinetToken == null ) {
return true ;
}
if (!serverToken.equals(clinetToken)) {
return true ;
}
return false ;
}
}
|
然后在Spring MVC的配置文件里加入:
<!-- 攔截器配置 -->
< mvc:interceptors >
<!-- 配置Shiro攔截器,,實現(xiàn)注冊用戶的注入 -->
< mvc:interceptor >
< mvc:mapping path = "/**" />
< bean class = "com.storezhang.video.shiro.ShiroInterceptor" />
</ mvc:interceptor >
<!-- 配置Token攔截器,防止用戶重復(fù)提交數(shù)據(jù) -->
< mvc:interceptor >
< mvc:mapping path = "/**" />
< bean class = "com.storezhang.web.spring.TokenInterceptor" />
</ mvc:interceptor >
</ mvc:interceptors >
|
相關(guān)代碼已經(jīng)注釋,,相信你能看懂,。
關(guān)于這個方法的用法是:在需要生成token的controller上增加@Token(save=true),而在需要檢查重復(fù)提交的controller上添加@Token(remove=true)就可以了,。
另外,,你需要在view里在form里增加下面代碼:
< input type = "hidden" name = "token" value = "${token}" />
|
已經(jīng)完成了,去試試看你的數(shù)據(jù)還能重復(fù)提交了吧,。
|