SSH2 AJAX LoginDemo 项目添加验证体系

01/17/2011

在前一篇文章中 SSH2 AJAX LoginDemo 项目添加 国际化信息,我们为 LoginDemo 添加了国际化方面的支持,今天我们增加验证体系。

Struts2 框架的验证体系主要分为:

  • action 中重写 validate() 进行 action类全局校验
  • action 中添加 validateXxx() 为 Xxx() 方法专门做的前置校验。(Strut2 利用反射自动映射)
  • 使用Struts2 验证框架 进行校验


我们在 LoginDemo 中对这几种方法都会有举例:

LoginAction.java

package com.track2web.demo.action;

import com.opensymphony.xwork2.ActionSupport;
import com.track2web.demo.entity.User;
import com.track2web.demo.service.IUserService;

public class LoginAction extends ActionSupport {

    //定义登录是否成功状态,验证错误信息国际化信息常量
    public static final String LOGIN_STATUS_SUCCESS = "login.status.message.success";
    public static final String LOGIN_STATUS_FAIL = "login.status.messsage.fail";
    public static final String USERNAME_VALIDATE_LENGTH = "input.minlenth.username";
    public static final String USERPASS_VALIDATE_LENGTH = "input.minlenth.userpass";

    //user对象接受页面传值
    private User user;
    //loginMessage 回传登录是否成功的状态
    private String loginMessage;
    //IOC接口
    private IUserService userService;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getLoginMessage() {
        return loginMessage;
    }

    public void setLoginMessage(String loginMessage) {
        this.loginMessage = loginMessage;
    }

    public IUserService getUserService() {
        return userService;
    }

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    /**
     * action 全局验证
     */
    @Override
    public void validate() {
        if (this.user.getUserName().length()<4) {
            addFieldError("user.userName", getText(USERNAME_VALIDATE_LENGTH));
        }
    }

    /**
     * 通过反射(Reflection)调用 validateLoginAjax()方法(为 loginAjax 方法验证数据)
     */
    public void validateLoginAjax() {
        if (this.user.getUserPass().length()<4) {
            addFieldError("user.userPass", getText(USERPASS_VALIDATE_LENGTH));
        }
    }

    /**
     * Ajax 方式所调用的 Action 方法
     * @return 返回调用成功信号
     */
    public String loginAjax() {
        //将 登录信息保存至 user 属性,如果校验失败,user 属性值为 NULL
        this.user = this.userService.login(user);
        if (user==null) {
            this.loginMessage = getText(LOGIN_STATUS_FAIL);
        }
        else {
            this.loginMessage = getText(LOGIN_STATUS_SUCCESS);
        }
        return SUCCESS;
    }
}

struts.xml

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <!-- AJAX方式登录 注意 extends 自 json-default 时 result 的 type 值才有 json 类型-->
    <package name="login-ajax" extends="json-default">
        <!-- method 指定了 请求 Action 中哪个具体方法-->
        <action name="loginAjax" class="LoginAction" method="loginAjax">
            <!-- JSON 格式的结果 拦截器 -->
            <interceptor-ref name="jsonValidationWorkflowStack" />
            <!-- 返回值类型为 json -->
            <result type="json">
                <param name="excludeNullProperties">true</param>
                <!-- 序列化 json 值时,不包括 的属性,userSerive 为 Spring 注入属性-->
                <param name="excludeProperties">
                    userService
                </param>
            </result>
            <!-- 为验证失败配置返回路径 -->
            <result name="input">/index.jsp</result>
        </action>
    </package>

</struts>

配置 STRUTS2 验证框架 (action类名称)-(action name)-validation.xml,依据 struts.xml 中的配置,存放于ACTION类同包中

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE validators PUBLIC
          "-//OpenSymphony Group//XWork Validator 1.0//EN"
          "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
    <field name="user.userName">
        <field-validator type="requiredstring">
            <message key="input.required.username" />
        </field-validator>
    </field>
    <field name="user.userPass">
        <field-validator type="requiredstring">
            <message key="input.required.userpass" />
        </field-validator>
    </field>
</validators>

今天对整个登录页面 index.jsp 做了较大的改动。使用了基本的HTML 标签,只是提交按钮使用了 STRUTS-JQUERY 插件的标签.样式全部转移到 style.css .所用到的 Javascript 全部转移到 login.js 保持了 index.jsp 的清爽

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<%@taglib prefix="sj" uri="/struts-jquery-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <sj:head locale="zh_CN" jqueryui="true" />
        <!-- AJAX 方式登录 callback 函数响应 login.js -->
        <script type="text/javascript" src="js/login/login.js"></script>
        <!-- 载入样式表 -->
        <link rel="stylesheet" type="text/css" href="css/style.css" />
        <title><s:text name="index.title" /></title>
    </head>
    <body>
        <div id="login_div">
            <form action="login-ajax/loginAjax.action" method="post" id="login_form">
                <fieldset class="login-fieldset">
                    <legend><s:text name="form.ajax.title" /></legend>
                    <label for="input_username" class="login-label">
                        <s:text name="text.label.username" />
                        <span id="user_username_error" class="error-message"></span>
                    </label>
                    <span class="input-span-block">
                        <input type="text" id="input_username" name="user.userName" />
                    </span>
                    <label for="input_userpass" class="login-label">
                        <s:text name="text.label.userpass" />
                        <span id="user_userpass_error" class="error-message"></span>
                    </label>
                    <span class="input-span-block">
                        <input type="password" id="input_userpass" name="user.userPass" />
                    </span>
                    <span class="button-span-block">
                        <sj:submit id="login_submit"
                                targets="result_message"
                                validate="true"
                                validateFunction="customLoginValidate"
                                onBeforeTopics="clearFieldErrors"
                                onSuccessTopics="success"
                                dataType="json"
                                value="%{getText('button.label.loginbyajax')}" />
                    </span>
                </fieldset>
            </form>
        </div>
        <div id="result_message" class="error-message"></div>
    </body>
</html>

login.js

//JSON 格式错误返回值中,KEY 中保存的是 input name的值,自定义函数进行同输出错误信息元素的映射
//本例中将 "user.userName" 转化为 "#user_username_error"
function formatErrorElementId(value) {
    var elem = value.toLowerCase();
    elem = elem.replace(/\./g , "_");
    elem += "_error"
    elem = "#"+elem;
    return elem;
}

//处理 JSON 格式的 validate 失败返回值
function customLoginValidate(form , errors) {
    if (errors.fieldErrors) {
        $.each(errors.fieldErrors , function(key,value) {
            var elem = formatErrorElementId(key);
            if (elem) {
                $(elem).html(value[0]);
            }
        });
    }
}

//清除前次留下的错误信息
$.subscribe("clearFieldErrors", function() {
    $("#user_username_error").html("");
    $("#user_userpass_error").html("");
});

//登录陈功后,输出的登录状态信息
$.subscribe("success" , function(event) {
    $("#result_message").html(event.originalEvent.data.loginMessage);
});

style.css

body {
    margin: 0;
    padding: 0;
    text-align: center;
    font-family: Georgia,'Times New Roman',times,serif;
}

#login_div {
    width:300px;
    margin: 2em auto;
    padding: 0.5em;
}

#login_div .error-message {
    font-size: 0.8em;
    font-style: italic;
    color: red;
    font-weight: bold;
}

#login_div .login-fieldset {
    padding: 0.3em;
    text-align: left;
    font-weight: bold;
}

#login_div .login-label {
    display: block;
}

#login_div .input-span-block {
    display: block;
}

#login_div .button-span-block {
    display: block;
    text-align: right;
}

#input_username , #input_userpass {
    width: 98%;
}

#login_submit {
    margin: 0.3em 0;
    padding: 0.3em 1em;
    font-weight: bold;
}

#result_message {
    width: 400px;
    margin: 0 auto;
    padding: 1em;
    font-weight: bold;
    font-size: 1.5em;
    color: red;
}

Struts2 数据提交的步骤是:

  • 校验框架
  • validate()
  • validateXxx()
  • action()

当然在生产环境中,最前端我们一般还要加上 JavaScript 校验。将在下一篇文章中涉及。以下是相关图片

ssh2-logindemo-validate_1

ssh2-logindemo-validate_2

ssh2-logindemo-validate_3

ssh2-logindemo-validate_4

ssh2-logindemo-validate_5

ssh2-logindemo-validate_6