1. 程式人生 > >Spring MVC 回退重新整理表單重複提交

Spring MVC 回退重新整理表單重複提交

    基於Spring MVC進行Java Web開發時,如果使用表單進行提交資料,然後跳轉到某個URL由Controller進行處理,最後返回邏輯檢視,框架會通過viewResolver來解析具體的View,然後向返回給瀏覽器顯示【參考】。

    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
        <property name="viewClass" value="com.tplink.cloud.web.IcomJstlView"/>
        <property name="order" value="1"/>
    </bean>

    比如最開始的登陸介面使用表單提交,其URL為 http://ip:port//app/account/, 表單內容如下:

                        <form id="loginForm" name="loginForm"
                            method="post" action="login">
                            <div id="login_form">
                                <p class="inputPrompt"></p>
                                <input name="username" class="username"
                                    type="text" placeholder="郵箱" /> <input
                                    name="password" class="password"
                                    type="password" placeholder="密碼" />
                                <input class="buttonsubmit"
                                    type="submit" value="登陸" />
                            </div>
                        </form>
    當用戶名輸入使用者名稱和密碼,點選登陸按鈕,form表單提交,URL變為 http://ip:port/app/account/login,由對應的Controller進行處理:
@Controller
@RequestMapping("/account")
@SessionAttributes({"username", "accountType", "resetUsername",
        "resetVeriCode"})
public class AccountController {
    private AccountService accountService;

    @Autowired
    public AccountController(AccountService accountService) {
        this.accountService = accountService;
    }

    @RequestMapping("/login")
    public String login(
            @RequestParam String username,
            @RequestParam(value = "password", required = false) String password,
            @CookieValue(required = false) String token,
            HttpServletRequest request, HttpServletResponse response,
            ModelMap model) {
        //******
        return "index";
    }
    之後瀏覽器頁面顯示為 /WEB-INF/jsp/index.jsp ,但是由於 InternalResourceViewResolver 是使用forward進行轉發的,所以URL還是 http//ip:port/app/account/login。

    此時如果點選瀏覽器回退鍵,頁面跳轉到最初的登陸介面URL:http://ip:port//app/account/  , 然後點選 前進按鍵,頁面出現 “重新整理重複提交表單” 的提示,點選重新整理,表單就重複提交然後跳轉到URL:http://ip:port/app/account/login了。

    網上搜索可知,有很多處理方式,如使用PRG方法,即 Post - Redirect - Get 方式,還可以直接不適用表單Form,而是用javascript+ajax進行提交。

方法一:

    PRG方法,只要在Controller中新增一個action如下:

    @RequestMapping("/go")
    public String go(@RequestParam String type) {
        return type;
    }
    然後修改開始的action的return內容如下:
    @RequestMapping("/login")
    public String login(
            @RequestParam String username,
            @RequestParam(value = "password", required = false) String password,
            @CookieValue(required = false) String token,
            HttpServletRequest request, HttpServletResponse response,
            ModelMap model) {
        //******
        return "redirect:/account/go?type=index";
    }
    由於此時使用redirect方法進行轉發,登陸之後對應的URL為:http://ip:port/app/account/go?type=index , 這樣點選回退再前進,頁面直接跳轉到 重定向之後的 URL,從而解決問題,從此也可以看出 forward 和 redirect 的區別【參考

方法二:

    不使用表單From提交,直接用javascript+ajajx提交,然後redirect(用到JQuery, 同時刪除登陸介面的from標籤):

var login = {
  init : function(){
    // validate input and password
    $('.buttonsubmit').click(login.submitCheck);
  },
  submitCheck : function(){
        var checkAccount = resetPassword.checkAccount();

        if (checkAccount) {
            var codeCheck = CheckUtil.ajaxCheckAccountPassword($(
                    '.username').val(), $('.password').val());
            if (codeCheck == CheckUtil.STATUS.FAILED) {
                $('.inputPrompt').html('使用者名稱密碼不匹配!');
                return false;
            }
            if (codeCheck == CheckUtil.STATUS.PASSED) {
                location.href = "go?type=index";
            }
        }
  }
};

$(document).ready(login.init);