在上一篇博文中已经学习了如何整合mybatis和spring,实现持久层的CRUD操作、业务层的事务管理和spring的IoC。
现在我们这个demo的基础上,继续整合struts2,并利用json插件和jquery实现ajax,完成后系统将实现登录与注册的简单功能。
浏览器端如何简单、高效地与服务器端进行数据交互是web开发者最为关心的内容。在客户端构造intput表单数据或者拼凑URL参数名称/参数值,然后在服务器端笨拙地用request.getParameter(“参数名称”)获取参数显然已经过时了,在struts2中,只要在action 里定义了input表单名称/URL参数名称对应的String类型属性,并设置getter和setter 方法,struts2在调用action的时候就可以根据参数值自动帮你设置好action中对应的属性值供你使用,这极大地方便了开发者。
但是json更为强大——它可以根据浏览器端上传的符合格式的数据设置action中对象的值,也就是说,struts2自动封装的数据只有一层,而json是无限层。
json给页面参数的传递带来极大的方便,结合jquery来使用,可以轻易地做到页面局部刷新、页面无跳转进行友好的系统异常提示等,其中后者是我觉得最有必要做到的一点,在action中定义一个message变量,把action方法执行的结果或者系统异常信息放到里面以json的方式返回给客户端,客户端根据这个变量的结果来进行下一步的操作或者提示系统异常信息,非常地好用。
json由javascript中的对象和数组构成,基本形式是{key:value},key为属性名称,value 为属性值,value可以为数字、字符串、数组、对象,value可以为数组和对象是json可以封装无限层数据的关键所在。至于如何建构和解析json不是本篇博文的详细表述范围,请参考其他资料。
现在就让我们利用struts2作为MVC框架,整合json插件,在浏览器端使用jquery解析和系列化json数据,由此制作一个具有登陆/注册功能的小demo。本demo中的数据持久层的实现用到了mybatis3和spring3,请参考本人的上一篇博文。
首先我们需要在eclipse中新建一个web工程,并把以下jar包拷贝到工程WEB-INF/lib 下:
aopalliance-1.0.jar
asm-3.3.1.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
aspectjweaver.jar
cglib-2.2.2.jar
commons-dbcp-1.2.1.jar
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
commons-pool.jar
freemarker-2.3.19.jar
javassist-3.11.0.GA.jar
log4j-1.2.16.jar
mybatis-3.0.6.jar
mybatis-spring.jar
mysql-connector-java-5.1.22-bin.jar
ognl-3.0.5.jar
org.springframework.aop-3.0.6.RELEASE.jar
org.springframework.asm-3.0.6.RELEASE.jar org.springframework.aspects-3.0.6.RELEASE.jar org.springframework.beans-3.0.6.RELEASE.jar org.springframework.context-3.0.6.RELEASE.jar org.springframework.core-3.0.6.RELEASE.jar org.springframework.expression-3.0.6.RELEASE.jar org.springframework.jdbc-3.0.6.RELEASE.jar org.springframework.transaction-3.0.6.RELEASE.jar slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
struts2-core-2.3.4.1.jar
xwork-core-2.3.4.1.jar
struts2-spring-plugin-2.3.4.1.jar
org.springframework.web.struts-3.0.6.RELEASE.jar
org.springframework.web-3.0.6.RELEASE.jar
commons-beanutils-1.8.0.jar
commons-collections-3.2.1.jar
ezmorph-1.0.6.jar
json-lib-2.4-jdk15.jar
struts2-json-plugin-2.3.4.1.jar
其中包含了Mybatis3.0.6、Spring3.0.6和Struts2.3.4单独工作或者相互整合所依赖的jar 包,本文需要关注的是struts2的json插件struts2-json-plugin-2.3.4.1.jar,还有json-lib 相关的jar:
json-lib-2.4-jdk15.jar
ezmorph-1.0.6.jar
commons-beanutils-1.8.0.jar
commons-collections-3.2.1.jar
如果没有加入这些包,初始化action时很可能会报:
ERROR 11-22 17:16:35 Unable to find parent packages json-default
或者类似的错误
我们来看看工程的整体构建情况,下图是工程在eclipse中的目录结构:
我们逐一来看看这些目录或者包中都有些什么。
config目录下,applicationContext.xml是spring的配置文件,log4j.xml是log4j的配置文件,struts.xml是struts的配置文件,遵从分模块配置的规则,我把本demo用到的struts 配置放到了struts-login.xml中。
com.ribbonchen.action包中定义了两个action,BaseAction继承于struts2的ActionSupport,为了获取request、response、session对象,它还实现了ServletRequestAware,ServletResponseAware,SessionAware接口,工程中其他的action都将继承于BaseAction;UserAction里定义了用户登录和注册要用到的相关方法。
下面说的都是数据持久层里面的东西,具体代码MySQL的建表sql这里我就不贴了,请参见我上一篇博文。
com.ribbonchen.dao里定义了数据访问层的相关接口和类和mybatis用到的映射文件。com.ribbonchen.service里定义了业务层的相关接口和类。
com.ribbonchen.entity里定义了用户实体类UserEntity。
ServiceFactory是没用到spring注入service到Action里时用到的工厂方法,请无视它,嘿嘿。
好了,我们来看代码,注释我都写在代码里面了。
首先来配置web工程初始化的入口,web.xml:
xmlns:xsi="https://www.doczj.com/doc/2c6114647.html,/2001/XMLSchema-instance" xsi:schemaLocation="https://www.doczj.com/doc/2c6114647.html,/xml/ns/j2ee https://www.doczj.com/doc/2c6114647.html,/xml/ns/j2ee/web-app_2_4.xsd">
Spring的配置文件applicationContext.xml:
xmlns:aop="https://www.doczj.com/doc/2c6114647.html,/schema/aop"
xmlns:tx="https://www.doczj.com/doc/2c6114647.html,/schema/tx"
xsi:schemaLocation="https://www.doczj.com/doc/2c6114647.html,/schema/beans
https://www.doczj.com/doc/2c6114647.html,/schema/beans/spring-beans-3.0.xsd
https://www.doczj.com/doc/2c6114647.html,/schema/context
https://www.doczj.com/doc/2c6114647.html,/schema/context/spring-context-3.0.xsd
https://www.doczj.com/doc/2c6114647.html,/schema/tx
https://www.doczj.com/doc/2c6114647.html,/schema/tx/spring-tx-3.0.xsd
https://www.doczj.com/doc/2c6114647.html,/schema/aop
https://www.doczj.com/doc/2c6114647.html,/schema/aop/spring-aop-3.0.xsd">
class="https://www.doczj.com/doc/2c6114647.html,mons.dbcp.BasicDataSource"> value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8"/>
=================================================
-->
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.Exception" no-rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.RuntimeException"/> rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.RuntimeException"/> rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.Exception"/> rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.RuntimeException"/> rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.Exception" no-rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.RuntimeException"/> rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.Exception" no-rollback-for="https://www.doczj.com/doc/2c6114647.html,ng.RuntimeException"/> expression="execution(public * com.ribbonchen.service.*.*(..))"/> Log4j.xml参见我上一遍博文,是一样的,呵呵。 Struts配置文件struts.xml: "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "https://www.doczj.com/doc/2c6114647.html,/dtds/struts-2.3.dtd"> Struts配置文件struts-login.xml,这个是重点,请参看里面的注释: method="doLogin"> userService method="register"> userService com.ribbonchen.action.BaseAction: public HttpServletRequest request; public HttpServletResponse response; public Map session; /* * action初始化时将调用setter方法自动初始化上面三个属性 */ public void setServletRequest(HttpServletRequest request) { this.request = request; } public void setServletResponse(HttpServletResponse response) { this.response = response; } public void setSession(Map map) { this.session = map; } } https://www.doczj.com/doc/2c6114647.html,erAction: * 如果你没有实现数据持久层,那请你在这里设个断点并把下面的if语句删除, * debug到这里时看一下userEntity是不是已经被初始化了,我们主要看json有没有自动帮我们初始化了action中的属性 * * */ if (userService.login(userEntity)) { setMessage(SUCCESS); } } catch (Exception e) { e.printStackTrace(); setMessage(e.getMessage()); } return"logined"; } public String goIndex()throws Exception{ return SUCCESS; } public String register()throws Exception{ try { //IUserService service = (IUserService)ServiceFactory.getService(IUserService.class); userService.register(userEntity); setMessage(SUCCESS); } catch (Exception e) { e.printStackTrace(); setMessage(e.getMessage()); } return"registered"; } public IUserService getUserService() { return userService; } public void setUserService(IUserService userService) { https://www.doczj.com/doc/2c6114647.html,erService = userService; } public UserEntity getUserEntity() { return userEntity; } public void setUserEntity(UserEntity userEntity) { https://www.doczj.com/doc/2c6114647.html,erEntity = userEntity; } public String getMessage() { return message; 登陆页面login.jsp: <%@page language="java"contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> "https://www.doczj.com/doc/2c6114647.html,/TR/html4/loose.dtd"> //初始加载页面时 $(document).ready(function(){ //向服务器发送表单数据 $("#loginBt").click(function(){ //alert("in!!!"); if($("#name").val()==""){ alert("用户名不能为空!"); return; } if($("#password").val()==""){ alert("密码不能为空!"); return; } //把表单的数据进行序列化 var params = $("form").serialize(); //使用jQuery中的$.ajax({});Ajax方法 $.ajax({ url:"login/doLogin", type:"POST", data:params, dataType:"json", success:function(data){ //清空显示层中的数据 $("#message").html(""); //为显示层添加获取到的数据 //获取action是否成功消息用data.message,获取用户实体对象的属性值用https://www.doczj.com/doc/2c6114647.html,erEntity.属性名称 if(data.message!="success"){ alert("用户登陆失败,错误信息:"+data.message); return; } //alert("用户登陆成功"); $("#message").append(" "+https://www.doczj.com/doc/2c6114647.html,+" $("#name").val(""); $("#password").val(""); } }); }); }); 姓名: 密码: 注册页面register.jsp: <%@page language="java"contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> "https://www.doczj.com/doc/2c6114647.html,/TR/html4/loose.dtd">
$(document).ready(function(){
//向服务器发送表单数据
$("#regBt").click(function(){
if($("#name").val()==""){
alert("用户名不能为空!");
return;
}
if($("#password").val()==""){
alert("密码不能为空!");
return;
}
if($("#password").val()!=$("#conf").val()){
alert("前后密码不一致!");
return;
}
//把表单的数据进行序列化
//alert($("#id").val());
//return;
var params = $("form").serialize();
//使用jQuery中的$.ajax({});Ajax方法
$.ajax({
url:"login/register",
type:"POST",
data:params,
dataType:"json",
success:function(data){
//清空显示层中的数据
$("#message").html("");
//为显示层添加获取到的数据
//获取对象的数据用https://www.doczj.com/doc/2c6114647.html,erInfo.属性
if(data.message!="success"){
alert("用户注册失败,错误信息:"+data.message);
$("#name").val("");
$("#password").val("");
$("#conf").val("");
return;
}
//alert("用户注册成功");
$("#message").append("
"+$("#name").val()+"
.append("
.append("点击这里返回登录页面");
$("#name").val("");
$("#password").val("");
$("#conf").val("");
}
});
});
});