| 前言:終于來(lái)了一篇有質(zhì)量的文章,我個(gè)人感覺(jué)非常不錯(cuò),《jfinal與bootstrap之間的登錄跳轉(zhuǎn)實(shí)戰(zhàn)》。具體內(nèi)容包含有點(diǎn)擊登錄彈出模態(tài)框、點(diǎn)擊登錄確認(rèn)按鈕后的validate、jfinal的validate、jfinal的session管理、ajax請(qǐng)求與返回信息處理、頁(yè)面間智能跳轉(zhuǎn)。 彈出模態(tài)框以及jQuery validate可以參照jquery weebox總結(jié)、彈出窗口不居中顯示?、jquery validate初上手系列文章。 從jfinal的validate說(shuō)起當(dāng)然你可以參考jfinal提供的幫助文檔,我當(dāng)然也必須是參照了官方文檔,當(dāng)然對(duì)于這種開源技術(shù)每個(gè)人在使用的過(guò)程中肯定有千奇百態(tài)的問(wèn)題,那么依據(jù)我的實(shí)戰(zhàn)結(jié)果,我想再贅述一遍也是非常有必要的。 1.指定config中的路由 me.add("/login", MembersController.class, "/pages/login");
 2.編寫conroller類 public class MembersController extends BaseController {
    @Before(MembersValidator.class)
    @ActionKey("/login")
    public void login() {
        // 獲取用戶名
        String name = getPara("username");
        // 獲取密碼
        String password = getPara("password");
        Members mem = Members.me.getMemByNamePasswd(name, CipherUtils.generatePassword(password));
        if (mem != null) {
            // 保存session
            getSession().setAttribute("username", name);
            // 最后登錄ip
            mem.set("lastip", getRequest().getRemoteHost());
            mem.set("lastvisit", DateUtils.getCurrentTime());
            mem.update();
            ajaxDoneSuccess("登錄成功!");
        } else {
            ajaxDoneError("用戶不存在!");
        }
        // 跳轉(zhuǎn)到前臺(tái)發(fā)起請(qǐng)求的路徑
        renderJson();
    }
}
 123456789101112131415161718192021222324252627282930313233
 123456789101112131415161718192021222324252627282930313233
 注意: 
使用before綁定validate使用actionkey綁定前端請(qǐng)求action名使用getSession().setAttribute來(lái)操作session,同時(shí)前端稍后介紹如何使用封裝ajaxDone系列方法進(jìn)行數(shù)據(jù)格式綁定,前端稍后介紹使用renderJson方法對(duì)ajax請(qǐng)求返回結(jié)果數(shù)據(jù)進(jìn)行json格式輸出接下來(lái)你需要看看我封裝的baseController 3.BaseController package com.hc.jf.controller;
import com.jfinal.core.Controller;
public class BaseController extends Controller {
    protected void ajaxDone(int statusCode, String message) {
        setAttr("statusCode", statusCode);
        setAttr("message", message);
        // 跳轉(zhuǎn)路徑
        String forwardUrl = getPara("forwardUrl");
        if (forwardUrl == null || forwardUrl.equals("")) {
            forwardUrl = getRequest().getRequestURL().toString();
        }
        setAttr("forwardUrl", forwardUrl);
        setAttr("callbackType", getPara("callbackType"));
    }
    protected void ajaxDoneSuccess(String message) {
        ajaxDone(200, message);
    }
    protected void ajaxDoneInfo(String message) {
        ajaxDone(201, message);
    }
    protected void ajaxDoneSuccess(String message, String forwarUrl) {
        ajaxDone(200, message);
    }
    protected void ajaxDoneError(String message) {
        ajaxDone(300, message);
    }
    protected void ajaxDoneError(String message, String forwarUrl) {
        ajaxDone(300, message);
    }
}
 1234567891011121314151617181920212223242526272829303132333435363738394041
 1234567891011121314151617181920212223242526272829303132333435363738394041
 注意: 
分別封裝成功、錯(cuò)誤、info級(jí)別的信息增加了statusCode、message、forwardUrl、callbackType四個(gè)屬性。以上兩個(gè)屬性和前端也有對(duì)應(yīng),稍后介紹。 4.MembersValidator package com.hc.jf.validator;
import com.hc.jf.entity.Members;
import com.jfinal.core.Controller;
import com.jfinal.validate.Validator;
public class MembersValidator extends Validator {
    @Override
    protected void validate(Controller controller) {
        validateRequiredString("username", "usernameMsg", "請(qǐng)輸入用戶名!");
        validateRequiredString("password", "passwordMsg", "請(qǐng)輸入密碼!");
    }
    @Override
    protected void handleError(Controller controller) {
        controller.keepModel(Members.class);
        controller.render("login.jsp");
    }
}
 12345678910111213141516171819202122
 12345678910111213141516171819202122
 注意: 
這個(gè)validate確實(shí)沒(méi)什么屌用,因?yàn)榍岸艘呀?jīng)使用jquery validate進(jìn)行了check,然而請(qǐng)注意,如果你沒(méi)有使用jquery的或者為了網(wǎng)絡(luò)安全等等,有這個(gè)也不錯(cuò)。好吧,我其實(shí)不想加入這個(gè)validate,但是我覺(jué)得可以我還沒(méi)有想到用處,但是心有戚戚焉,覺(jué)得它還是有用的。 jfinal的session管理其實(shí)說(shuō)到這,已經(jīng)不是jfinal的session了,其實(shí)要說(shuō)的是前端。 <c:choose>
<c:when test="${sessionScope.username!=null}">
        <span>
            <a href="javascript:void(0);" id="mycenter" style="">
                ${sessionScope.username}<s class="icon_arrow icon_arrow_down"></s>
            </a>
            <i class="line"></i>
            <a href="/logout" title="退出" id="user_login_out" style="padding: 0 6px;">退出</a>
        </span>
        </c:when>
    <c:otherwise>
        <span>
            <a title="登錄" href="javascript:show_pop_login();" id="show_pop_login">登錄</a>
        </span>
    </c:otherwise>
</c:choose>
 注意: 
這里使用了${sessionScope.username}獲取session數(shù)據(jù),這只是很簡(jiǎn)單的一個(gè)應(yīng)用。1中好像沒(méi)什么可說(shuō)的,但重要的是,你彈出登錄框后,需要重新回到對(duì)應(yīng)的跳轉(zhuǎn)頁(yè)面,然后顯示登錄的信息,好吧,我覺(jué)得沒(méi)有解釋清楚,那么上一張圖吧! 
  這個(gè)圖片為了商業(yè)機(jī)密,我只能截圖到這里了,哈哈。 就像很多互聯(lián)網(wǎng)網(wǎng)站一樣,你如果是游客的話,也可以打開很多頁(yè)面進(jìn)行相關(guān)的信息進(jìn)行查看,比如你可以打開1.html、2.html,但是這兩個(gè)頁(yè)面都可以點(diǎn)擊登錄按鈕彈出登錄框。那么問(wèn)題來(lái)了,
 你怎么保證從1.html打開登錄的時(shí)候還跳轉(zhuǎn)到1.html,從2.html打開登錄成功后還跳轉(zhuǎn)到2.html。 好吧,先說(shuō)到這,這里賣個(gè)關(guān)子,我們繼續(xù)看下個(gè)章節(jié)。 ajax請(qǐng)求與返回信息處理1.彈出登錄窗口 /**
 * 彈出登錄框
 */
function show_pop_login() {
    $.weeboxs.open(common.ctx + "/pages/login/login.jsp", {
        boxid : 'pop_user_login',
        contentType : 'ajax',
        showButton : false,
        showCancel : false,
        showOk : false,
        title : '會(huì)員登錄',
        width : 700,
        type : 'wee'
    });
}
 這是彈出登錄框,至于weebox,你可以查看jquery weebox總結(jié)。 注意: 這里可能是從1.html打開的,也可能是從2.html頁(yè)面打開的登錄框。 2.然后我們?cè)賮?lái)看看登錄的form表單 <form class="pop_login_form" action="${ctx}/login?callbackType=closeCurrent" method="post" onsubmit="return validateCallback(this, dialogAjaxDone);">
    <div class="row ">
        <div class="row">
            <label class="col-md-4" style="margin-top: 10px;" for="name">用戶登錄</label>
        </div>
        <div class="form-group">
            <div class="row">
                <div class="col-md-2 col-md-offset-2 tr th">
                    <label for="name">賬戶</label>
                </div>
                <div class="col-md-5">
                    <input type="text" style="" class="form-control required" id="username" name="username" placeholder="請(qǐng)輸入會(huì)員編號(hào)"
                        autocomplete="off">
                </div>
            </div>
        </div>
        <div class="form-group">
            <div class="row">
                <div class="col-md-2 col-md-offset-2 tr th">
                    <label for="name">密碼</label>
                </div>
                <div class="col-md-5">
                    <input type="password" class="form-control required" id="password" name="password" placeholder="請(qǐng)輸入登陸密碼">
                </div>
            </div>
        </div>
        <div class="row">
            <div class="checkbox">
                <label> <input type="checkbox"> 記住我(下次自動(dòng)登陸)
                </label>
            </div>
        </div>
        <div class="row">
            <button type="submit" style="margin-bottom: 10px;" class="btn btn-default">提交</button>
        </div>
    </div>
</form>
 12345678910111213141516171819202122232425262728293031323334353637
 12345678910111213141516171819202122232425262728293031323334353637
 注意: 
你需要關(guān)注action=”${ctx}/login?callbackType=closeCurrent”再關(guān)注onsubmit=”return validateCallback(this, dialogAjaxDone);” 好吧,我們先來(lái)看看登錄的界面吧。 
  很漂亮的登錄框,漂亮的不像實(shí)力派!嘻嘻。 然后關(guān)鍵的部分來(lái)了,請(qǐng)繼續(xù)關(guān)注下節(jié),我把發(fā)送ajax請(qǐng)求也放在下節(jié)的代碼中,就省得重復(fù)。 頁(yè)面間智能跳轉(zhuǎn)1.提交請(qǐng)求 /**
 * 普通ajax表單提交
 * 
 * @param {Object}
 *            form
 * @param {Object}
 *            callback
 * @param {String}
 *            confirmMsg 提示確認(rèn)信息
 */
function validateCallback(form, callback, confirmMsg) {
    var $form = $(form);
    if (!$form.valid()) {
        return false;
    }
    var _submitFn = function() {
        var forwardUrl = window.location.href;
        var formUrl = $form.attr("action");
        if (formUrl.indexOf("?") != -1) {
            formUrl += "&forwardUrl=" + forwardUrl;
        } else {
            formUrl += "?forwardUrl=" + forwardUrl;
        }
        $.ajax({
            type : form.method || 'POST',
            url : formUrl,
            data : $form.serializeArray(),
            dataType : "json",
            cache : false,
            success : callback || YUNM.ajaxDone,
            error : YUNM.ajaxError
        });
    }
    if (confirmMsg) {
        alertMsg.confirm(confirmMsg, {
            okCall : _submitFn
        });
    } else {
        _submitFn();
    }
    return false;
}
 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
 好吧,看到這,你也許會(huì)說(shuō)我剽竊了DWZ的靈感,OK,既然zhanghuihua同學(xué)開源了,有必要我們就好好的利用是吧。 注意: 
你看到了forwardUrl的相關(guān)代碼,沒(méi)錯(cuò),這個(gè)關(guān)鍵的字段就是來(lái)傳遞發(fā)起請(qǐng)求的頁(yè)面路徑,比如說(shuō)1.html,2.html。然后,ajax執(zhí)行成功后,也就是登陸成功后,我們要執(zhí)行callback方法,也就是dialogAjaxDone方法,那么你需要繼續(xù)看下去。 2.回調(diào)函數(shù) /**
 * dialog上的表單提交回調(diào)函數(shù) 服務(wù)器轉(zhuǎn)回forwardUrl,可以重新載入指定的頁(yè)面.
 * statusCode=YUNM.statusCode.ok表示操作成功, 自動(dòng)關(guān)閉當(dāng)前dialog
 */
function dialogAjaxDone(json) {
    YUNM.ajaxDone(json);
    if (json[YUNM.keys.statusCode] == YUNM.statusCode.ok || json[YUNM.keys.statusCode] == YUNM.statusCode.info) {
        if ("closeCurrent" == json.callbackType) {
            close_pop();
        }
        // 如果指定了后調(diào)轉(zhuǎn)頁(yè)面,進(jìn)行調(diào)轉(zhuǎn)
        if (json.forwardUrl) {
            location.href = json.forwardUrl;
        }
    }
}
     ajaxDone : function(json) {
        if (json[YUNM.keys.statusCode] == YUNM.statusCode.error) {
            if (json[YUNM.keys.message])
                $.showErr(json[YUNM.keys.message]);
            ;
        } else if (json[YUNM.keys.statusCode] == YUNM.statusCode.timeout) {
            alertMsg.error(json[YUNM.keys.message]);
        }
    },
 注意: 
第二串代碼就是出于錯(cuò)誤消息,諸如“用戶不存在的”,還有timeout。第一串代碼就是回調(diào)函數(shù),其作用就是成功后關(guān)閉彈出框,然后再跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面。   
 
 結(jié)語(yǔ):OK,這樣一篇文章希望能夠給熱愛(ài)jfinal和bootstrap的同學(xué)帶來(lái)靈感! |