Struts 2+Jquery+JSON(登录验证)

来源:互联网 发布:4.0绩点算法 编辑:程序博客网 时间:2024/05/17 01:09
 我先来重写登录模块中的loginform.jsp文件,原来的代码,请看Struts 2.1.6 精简实例系列教程(2):用户登录模块的实现,现在修改的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-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">

<title>登录页</title>

<script type="text/javascript" src="js/jquery.js"></script>

<script type="text/javascript">

    $(function(){

        $("#submit").click(function(){

            var loginName1 = $("input[name='loginName']").val();    //获取账号

            var password1 = $("input[name='password']").val();        //获取密码

 

            var jsonUser = {loginName:loginName1, password:password1};    //JSON对象

           

            //注意:jsonUser.toString()这种方法错误,javaScript中的toString是用于布尔型变量的,而应用以下方法

            var strUser = JSON.stringify(jsonUser);    //将JSON对象转变成JSON格式的字符串,

           

            $.post("user/login.action", {json: strUser}, callback, "json");

        });

 

        function callback(json){

            alert(json.msg);    //显示反馈信息

            if(json.suc == 1){    //如果返回"登录成功"

                window.location.href = "admin/index.action";    //跳转到后台主页

            }

        }

       

    });

</script>

</head>

<body>

 

<form action="user/login.action" method="post">

    账号<input type="text" name="loginName"/><br/>

    密码<input type="password" name="password"><br/>

    <input type="button" id="submit" value="登录"/>

</form>

 

</body>

</html>


关键的两句是:

var jsonUser = {loginName:loginName1, password:password1};    (1)
var strUser = JSON.stringify(jsonUser);                                         (2)

第(1)句是组装JSON对象,关于JSON对象的格式,建议大家到http://www.json.org/网站上学习一下,要验证你写的JSON对象是否正确,可在http://json.bloople.net/网站上验证。上面写的JSON对象其实是非常简单的一种,jsonUser对象里有两个属性,分别是loginName和password,而表示这两个属性,用key-value的形式,loginName1和password1分别是接收表单中的账号、密码的值。

第(2)句,相当重要,通过JavaScript内置对象JSON的stringify方法,将JSON对象转换成字符串。因为,我们传送给服务器端的要是JSON格式的字符串。

$.post("login!valid.action", {json: strUser}, callback, "json");

这一句,Jquery用POST方法向服务器端发送数据,login!valid.action是我们要发送到的目的URI,也即直达loginAction的valid方法。而{…}是我们要发送的数据(data),{json:strUser},其实也是一个JSON对象,Key:value的形式,大家注意,我们把strUser这个json串发过去,在Action那里接收时,要接收“json”这个变量,这个变量的值就是我们发送的strUser字符串。

回调函数(callback)是指服务器端成功发回时,在JS端执行的函数。最后一个参数“json”是返回数据类型的一种,另外,还有”text”、“xml”等。而function callback函数体的内容,大家看完LoginAction类后,自然会明白。

好,Show一下修改后的LoginAction.java,代码如下:


package cn.simple.action;

 

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import org.json.JSONObject;

import cn.simple.pojo.User;

import com.opensymphony.xwork2.ActionSupport;

 

//@Results({

//    @Result(name="success", location="admin/index.action", type="redirect"),

//    @Result(name="input", location="loginform.jsp", type="dispatcher")

//})

public class LoginAction extends ActionSupport {

 

    private String json;    //JSON字符串,JS与Action传递数据的载体

    public String getJson() {

        return json;

    }

    public void setJson(String json) {

        this.json = json;

    }

 

    /** *//**

     * 登录验证

     * @throws Exception

     */

    public void valid() throws Exception {

        JSONObject jsonObj = new JSONObject(json);    //将JSON格式的字符串构造成JSON对象

        String loginName = jsonObj.getString("loginName"); //获取JSON对象中的loginName属性的值

        String password = jsonObj.getString("password");    //获取JSON对象中的password属性的值

       

        if(loginName=="yutong"){

            //此时的JSON对象,有两个属性suc和msg,其中suc表示是否登录成功的状态

            json = "{suc:0, msg:'用户名不存在'}";    //构造JSON格式的字符串

        } else if( ! password.equals("123")){

            json = "{suc:0, msg:'密码不正确!'}";

        } else {

            json = "{suc:1, msg:'登录成功!'}";

        }

        sendMsg(json);    //发送JSON格式的字符串回JS端

    }

   

    /** *//**

     * 向客户端的JS发送字符串

     * @param content 发送的内容

     * @throws IOException

     */

    public void sendMsg(String content) throws IOException{

        HttpServletResponse response = ServletActionContext.getResponse();

        response.setCharacterEncoding("UTF-8");

        response.getWriter().write(content);

    }

   

}

 


我们说过了,JS与Action互相传送的是JSON格式的字符串,故在LoginAction里,我们定义了private String json这个成员属性及其getter和setter方法。


或者,打成jar包,放到项目lib目录下。我们就可以使用JSON类库提供给我们的方法了。

网上有另一个JSON的类库:json-lib,大家也可下载使用一下,不过,它要引进几个其他的jar包,详细请见http://json-lib.sourceforge.net/。个人使用它的感受,也真有点郁闷,测试它时,想找一个从JSON字符串转换成JSON对象的方法,找了半天也没找到。不过,它对Java的Bean,Map,List等与JSONObject的互转换做得还好。

sendMsg方法,是从Struts的Action中调用回原生Servlet的response来向浏览器端发送数据。

还有一点,大家应该注意到,我们在LoginAction中写的valid方法返回类型是void型的,跟我们以前做的返回“success”、”input”之类的String类型不同。当我们通过 “!valid”来方法它时,它不作跳转,而是像我们平时Servlet中那种直接显示HTML类似。这一点达成了Ajax与Struts的成功交互。而网上许多写jsonplugin插件使用的文章,所调用的方法都是返回String类型,然后,再来个<result type=”json”>,那样感觉挺麻烦的,不如直接让Ajax发来的请求与void类型的方法交互,不直接爽快?

好,让我们运行一下,看看效果吧:

Struts 2.1.6 精简实例系列教程(6):重写用户登录模块(整合Jquery+JSON) - 心梦帆影Java技术博客 - BlogJava - 于祥通 - 小鱼儿-于祥通

Struts 2.1.6 精简实例系列教程(6):重写用户登录模块(整合Jquery+JSON) - 心梦帆影Java技术博客 - BlogJava - 于祥通 - 小鱼儿-于祥通

大家看看fireFox的debug的控制台中显示的:

Struts 2.1.6 精简实例系列教程(6):重写用户登录模块(整合Jquery+JSON) - 心梦帆影Java技术博客 - BlogJava - 于祥通 - 小鱼儿-于祥通

好,我们来输入一个正确的账号和密码,如下:

Struts 2.1.6 精简实例系列教程(6):重写用户登录模块(整合Jquery+JSON) - 心梦帆影Java技术博客 - BlogJava - 于祥通 - 小鱼儿-于祥通

点确定后,网页就跳到了后台主页。

这样,Ajax(Jquery)与Struts2.1.6的交互,通过JSON格式的字符串传递数据,这一实践就完成了。有一点需要说明一下:本例中的JSON对象都是相对比较简单,还有一些复杂的JSON对象,如{company:{building:”五角大楼”,employees:[{name:”tom”,age:21},{name:”marry”,age:18} ] } }。至于这些,该怎么处理呢?其实,处理方法也一样的。只是在Action中调用JSON类库的一些对象和方法,就能很好地处理。

 

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1. action:

/**
* 会员登录
*/
public String login() {
   try {
    Object object = memberinfoManager.validate(memberinfoPO);
    if (object == null) {
     message = "failure";
    } else {
     memberinfoPO = (MemberinfoPO) object;
     Map<String, Object> session = ServletActionContext.getContext()
       .getSession();
     session.put("memberinfoPO", memberinfoPO);

     // 登录成功以后显示信息
     String s = "";
     if (memberinfoPO.getSex().equals("男")) {
      s = "先生";
     } else {
      s = "女士";
     }
     message = memberinfoPO.getUsername()
       + s + "&nbsp;"
       + "欢迎您登录&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;<a href='#'>进入会员中心</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='javascript:logout()'>退出登录</a>";
    }
   } catch (Exception e) {
    logger.error(e.toString(), e);
   }
   return SUCCESS;
}
/**
* 退出登录
*/
public String loginOut() {
   try {
    ServletActionContext.getContext().getSession().remove("memberinfoPO");
   } catch (Exception e) {
    logger.error(e.toString(),e);
   }
   return SUCCESS;
}

2 struts.xml

<result type="json">
        <param name="excludeProperties">logger,memberinfoManager,organizationpos,menuUtil
        ,organizationListMap,typeop,typeDao</param>
    </result>

3.jsp

<s:if test="#session.memberinfoPO == null">
<div id="loginResult"></div>
<div id="loginForm">
   用户名 <input type="text" name="memberinfoPO.loginname" id="username" />   &nbsp; &nbsp; 密码:
     <input type="password" name="memberinfoPO.loginpass" id="password" />
    
     <input type="checkbox" name="checkbox" value="checkbox" />
     自动登录
     <input type="submit"   value="登录" onclick="userLogin()"/>
     &nbsp; &nbsp; 免费注册
     &nbsp; &nbsp; &nbsp; &nbsp; 欢迎登录交通物流信息平台
</div>
</s:if>
<s:else>
<s:set value="#session.memberinfoPO" var="member" />
<div id="loginResult">
   <s:property value="#member.username"/><s:if test='#member.sex == "男"'>先生</s:if><s:else>女士</s:else>
   欢迎您登录&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;<a href='#'>进入会员中心</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='javascript:logout()'>退出登录</a>
</div>
<div id="loginForm" style="display: none;">
   用户名 <input type="text" name="memberinfoPO.loginname" id="username" />   &nbsp; &nbsp; 密码:
     <input type="password" name="memberinfoPO.loginpass" id="password" />
    
     <input type="checkbox" name="checkbox" value="checkbox" />
     自动登录
     <input type="submit"   value="登录" onclick="userLogin()"/>
     &nbsp; &nbsp; 免费注册
     &nbsp; &nbsp; &nbsp; &nbsp; 欢迎登录交通物流信息平台
</div>
</s:else>

4.js

function userLogin() {
var username = $("#username").val();
var password = $("#password").val();
if (username == "" || username == null) {
   alert("请输入用户名!");
} else if (password == "" || password == null) {
   alert("请输入密码!");
} else {
   $.ajax( {
    url :"memberinfo/memberinfo_login",
    type :"post",
    dataType :"json",
    data :"memberinfoPO.loginname=" + username
      + "&memberinfoPO.loginpass=" + password,
    timeout :20000,// 设置请求超时时间(毫秒)。
    error : function() {// 请求失败时调用函数。
     $("#loginResult").html("请求失败!");
    },
    success :callbackLogin
   });
}
}
function callbackLogin(json) {
$("#loginForm").hide();
if (json.message == 'failure') {
   $("#loginResult").html("用户名或密码错误!<a href='javascript:loginAgain()'>请重新登录</a>");
   $("#loginResult").show();
} else {
   alert("登录成功!");
   $("#loginResult").html(json.message);
   $("#loginResult").show();
}
}
function loginAgain() {
$("#loginResult").hide();
$("#loginForm").show();
}
function logout() {
$.ajax( {
   url :"memberinfo/memberinfo_loginOut",
   type :"post",
   dataType :"json",
   timeout :20000,// 设置请求超时时间(毫秒)。
   error : function() {// 请求失败时调用函数。
    $("#loginResult").html("请求失败!");
   },
   success :callbackLoginOut
});
}
function callbackLoginOut() {
$("#loginResult").hide();
$("#loginForm").show();
}

5,

将jquery.js,json-lib-2.1.jar,struts2-json-plugin-2.1.8.1.jar


 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

用户登录模块。Model层是融合了iBatis来开发的。关于iBatis的下载使用,请先看Struts 2.1.6 精简实例系列教程(3):新闻管理Model层的开发(整合iBatis)。

首先在MySQL中,新建一个user表,建表SQL语句为:

create table user
(
    ID int auto_increment not null primary key,
    LOGIN_NAME varchar(25),
    PASSWORD varchar(25)
);

将用户信息封装到一个POJO类里,User.java的代码如下:

package cn.simple.pojo;

/** *//**
* 用户类
* @author rongxinhua
*
*/
public class User {
   
    private int id;        //编号
    private String loginName;    //登录账号
    private String password;    //密码
   
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getLoginName() {
        return loginName;
    }
    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

}

User类与user表之间的属性列映射、查询语句、更新语句的定义等,我们写在配置文件User.xml里,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap     
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="User">
   
    <!-- 用"User"表示cn.simple.pojo.User类,下面用到此类时,用简称"User"即行 -->
    <typeAlias alias="User" type="cn.simple.pojo.User"/>
   
    <!-- 定义结果集,用户类与用户表的映射 -->
    <resultMap id="UserResult" class="User">
        <result property="id" column="ID"/>
        <result property="loginName" column="LOGIN_NAME"/>
        <result property="password" column="PASSWORD"/>
    </resultMap>
   
    <!-- 查询用户列表 -->
    <select id="selectAllUsers" resultMap="UserResult">
        select * from user
    </select>
   
    <!-- 根据ID单查用户 -->
    <select id="selectUserById" parameterClass="int" resultClass="User">
        select
        ID as id,
        LOGIN_NAME as loginName,
        PASSWORD as password
        from user
        where ID=#id#
    </select>
   
    <!-- 根据用户名查询用户 -->
    <select id="selectUserByLoginName" parameterClass="String" resultClass="User">
        select
        ID as id,
        LOGIN_NAME as loginName,
        PASSWORD as password
        from user
        where LOGIN_NAME=#loginName#
    </select>
   
    <!-- 添加用户 -->
    <insert id="insertUser" parameterClass="User">
        insert into user (
            LOGIN_NAME,
            PASSWORD
        ) values (
            #loginName#,
            #password#
        )
    </insert>
   
    <!-- 修改密码 -->
    <update id="updatePassword" parameterClass="User">
        update user set
        PASSWORD = #password#
        where ID=#id#
    </update>
   
    <!-- 删除用户 -->
    <delete id="deleteUserById" parameterClass="int">
        delete from user where ID=#id#
    </delete>
   
   

</sqlMap>

此时,我们须要将User.xml添加到SqlMapConfig.xml里去,即在SqlMapConfig.xml加入以下代码:

<sqlMap resource="cn/simple/pojo/User.xml"/>

处理用户增删查改的业务逻辑类,UserManager.java,代码如下:

package cn.simple.manager;

import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
import java.util.List;
import cn.simple.pojo.User;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

/** *//**
* 用户管理
* @author rongxinhua
*
*/
public class UserManager {
   
    private static SqlMapClient sqlMapper;
   
    static {
        try {
            Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
            sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
            reader.close();
        } catch (IOException e) {
            throw new RuntimeException("SqlMapClient创建失败!");
        }   
    }
   
    /** *//**
     * 查询用户列表
     * @return 用户对象列表
     * @throws SQLException
     */
    public static List<User> selectAllUsers() throws SQLException{
        return sqlMapper.queryForList("selectAllUsers");
    }
   
    /** *//**
     * 根据ID单查用户
     * @param id 用户ID
     * @return 用户对象
     * @throws SQLException
     */
    public static User selectUserById(int id) throws SQLException{
        return (User)sqlMapper.queryForObject("selectUserById", id);
    }
   
    /** *//**
     * 根据用户名单查用户对象
     * @param loginName
     * @return
     * @throws SQLException
     */
    public static User selectUserByLoginName(String loginName) throws SQLException{
        User user = (User)sqlMapper.queryForObject("selectUserByLoginName", loginName);
        return user;

    }
   
    /** *//**
     * 添加用户
     * @param user 用户对象
     * @throws SQLException
     */
    public static void insertUser(User user) throws SQLException{
        sqlMapper.insert("insertUser", user);
    }
   
    /** *//**
     * 删除用户
     * @param id 用户ID
     * @throws SQLException
     */
    public static void deleteUserById(int id) throws SQLException{
        sqlMapper.delete("deleteUserById", id);
    }
   
    /** *//**
     * 修改密码
     * @param user
     * @throws SQLException
     */
    public static void updatePassword(User user) throws SQLException{
        sqlMapper.update("updatePassword", user);
    }

}

好,你们来写我们的Action类RegisterAction.java,代码如下:

package cn.simple.action;

import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import cn.simple.manager.UserManager;
import cn.simple.pojo.User;
import com.opensymphony.xwork2.ActionSupport;

/** *//**
* 处理用户注册的Action
* @author rongxinhua
*
*/

@Results({
    @Result(name = "success", location = "register-success.jsp", type="dispatcher"),
    @Result(name = "input", location = "registerform.jsp", type = "dispatcher")
})
public class RegisterAction extends ActionSupport {
   
   
    private User user;
    private String loginName1;
   
    public String execute() throws Exception {
        UserManager.insertUser(user);
        return SUCCESS;
    }
   
    /** *//**
     * 判断用户名是否存在(用于Ajax异步验证)
     * @throws Exception
     */
    public void isExistLoginName() throws Exception {
        if(loginName1.length() < 4 || loginName1.length() > 8){
            sendMsg("用户名长度应在4-8之间!");
        }else if(null != UserManager.selectUserByLoginName(loginName1)){
            sendMsg("用户名" + loginName1 + "已存在!");
        }else{
            sendMsg("success");
        }
       
    }
   
    /** *//**
     * 向客户端发送数据
     * @param content
     * @throws IOException
     */
    public void sendMsg(String content) throws IOException{
        HttpServletResponse response = ServletActionContext.getResponse();
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(content);
    }

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

    public String getLoginName1() {
        return loginName1;
    }

    public void setLoginName1(String loginName1) {
        this.loginName1 = loginName1;
    }

   
   
   

}

最后,我们来写我们的注册页面registerform.jsp,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-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">
<title>用户注册页</title>
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
    $(function(){
        var state = false;    //表单是否允许submit的状态变量,全局变量
        //当id为"loginName"的表单域中输入东西,响应键盘弹起事件时,会触发此function
        $("#loginName").keyup(function(){
            var loginName = $("#loginName").val();    //获取id为"loginName"的表单域的值
            var url = "register!isExistLoginName.action?loginName1=" + loginName;
            $.get(url, null , callback);    //用get方式向服务器端发送数据

        });
        function callback(msg){
            if("success" == msg){    //收到服务器端返回的"success"字符串
                $("#result").html("");    //清空提示信息显示域
                state = true;    //设置submit状态为true,表示允许提交
            }else{
                state = false;    //设置submit状态为false,表示不允许提交
                $("#result").html(msg);        //将服务器端返回的提示信息渲染页面
            }
        }

        //当表单submit时,会触发此function.
        //若return true,则提交,若return false,则不提交
        $("form").submit(function(){
            return state;
        });
       
    });
</script>
</head>
<body>
<h2>用户注册页</h2>
<s:fielderror></s:fielderror>

<form action="register.action" method="post">
    账号<input type="text" id="loginName" name="user.loginName" value="${loginName}"/>
    <span id="result" style="color:red;"></span><br/>
    密码<input type="password" id="password" name="user.password"><br/>
    <input type="submit" value="注册"/>
</form>
</body>
</html>

好,我们来运行一下,看看效果怎么样。输入http://localhost:8060/SimpleWeb/registerform.action。运行效果截图如下:

当输入账号的长度小于4时,输入框右边会动态地显示如下的提示信息,而页面并不刷新、不重新加载。此时,点“注册”是提交不了的。

image

当输入长度为4-8之间时,如“blogjava”,点注册后,能成功提交。

image

当数据库中已存在输入的用户名时,会给出相应的提示信息,如再次注册时输入“blogjava”,会动态显示如下信息:

image

好,本期就介绍到这里,还是重复那一句,要学好Jquery的话,还得多看API文档,并多做些例子测试一下,感受一下。

原创粉丝点击