10.3 Struts 2整合Ajax开发
图10.8 登录失败
由于Ajax技术的广泛应用,从而发展起来了许多的Ajax框架,基于这些框架能够更轻松和方便地开发出Ajax应用。其中DWR框架是其中比较流行的一个Ajax框架,而它最大的优势就是可以像使用本地的JavaScript函数一样,调用服务器上的Java方法。
10.3.1 基于DWR开发Ajax应用
首先从DWR的官方网站http://getahead.ltd.uk/dwr下载DWR框架,这里选择1.1.4版本下载。安装DWR非常简单,只需将下载的“dwr.jar”复制到Web应用的WEB-INF\lib目录下即可。
为了让DWR的核心Servlet起作用,所以还必须在“web.xml”文件中配置该核心Servlet,代码如下所示。
<servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class> uk.ltd.getahead.dwr.DWRServlet </servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping>
新建业务逻辑组件RegistCheck,该类提供isRegist方法来判断用户名是否被占用,如果被占用则返回“用户名已被占用,请重新输入”字符串;如果没有被占用则返回“该用户名可以使用”字符串,代码如下所示。
package net.hncu.service; import java.util.HashSet; import java.util.Set; public class RegistCheck { public String isRegist(String username){ Set<String> users = new HashSet<String>(); users.add("xiaoqiang"); if(users.contains(username)) { return "用户名已被占用,请重新输入"; }else { return "该用户名可以使用"; } } }
为了使得JavaScript能够调用该业务逻辑组件中的isRegist方法,需要在WEB-INF目录下添加“dwr.xml”配置文件,并在该配置文件中配置被暴露的Java方法,代码如下所示。
<? xml version="1.0" encoding="UTF-8"? > <! DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd"> <dwr> <allow> <create creator="new" javascript="checkUser"> <param name="class" value="net.hncu.service.RegistCheck" /> </create> </allow> </dwr>
新建注册页面,该页面包含一个注册表单。通过单击“用户名是否占用”按钮能触发JavaScript中的check()函数,通过该函数调用服务器端的isRegist方法,并通过DIV标签显示该方法的返回值信息,代码如下所示。
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>用户注册</title> <script type=' text/javascript' src=' dwr/interface/checkUser.js' ></script> <script type=' text/javascript' src=' dwr/engine.js' ></script> <script type=' text/javascript' src=' dwr/util.js' ></script> <script type="text/javascript"> function check() { var username = document.getElementById(' username' ).value; checkUser.isRegist(username, callback); } function callback(msg) { DWRUtil.setValue(' result' , msg); } </script> </head> <body> <! -- 显示用户名是否占用信息 --> <div id="result" style="color: red"></div> <! -- 注册表单 --> <form action="aa" method="post""> <table> <tr> <td>用户名:</td> <td><input id="username" type="text" name="username"></td> <td><input type="button" value="用户名是否占用" onclick=' check(); ' /></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password"></td> </tr> <tr> <td>确认密码:</td> <td> <input type="password" name="repassword"></td> </tr> <tr> <td>年龄: </td> <td><input type="text" name="age"></td> </tr> <tr> <td>出生日期: </td> <td><input type="text" name="birth"></td> </tr> <tr> <td>邮箱地址:</td> <td><input type="text" name="email"></td> </tr> <tr> <td></td> <td><input type="submit" value="提交"> <input type="reset" value="重置"> </td> </tr> </table> </form> </body> </html>
运行注册页面,随意输入一个用户名,单击“用户名是否占用”按钮,页面提示该用户名可以使用的提示信息,如图10.9所示。
输入用户名“xiaoqiang”,因为该用户已经存在,单击“用户名是否占用”按钮,所以页面提示用户名已被占用,请重新输入的提示信息,如图10.10所示。
图10.9 用户注册页(1)
图10.10 用户注册页(2)
10.3.2 在Struts 2中实现Ajax表单校验
Struts 2的Ajax表单校验是基于DWR和Dojo两个框架之上的,其中DWR负责实现在JavaScript代码中调用Java方法,而Dojo负责实现页面显示效果。Struts 2对于这两个框架的封装非常好了,因此只需通过少量的配置就能实现Ajax表单校验。
首先同前面介绍的一样,需要在Web应用中加入“dwr.jar”文件。然后在“web.xml”文件中配置DWR的核心Servlet。
配置完核心Servlet后,需要新增“dwr.xml”配置文件,并在该配置文件中添加配置代码,使得DWRValidator中的方法暴露为Javascript可以调用的远程接口。这份代码是非常固定的,基本上无需修改,代码如下所示。
<? xml version="1.0" encoding="UTF-8"? > <! -- START SNIPPET: dwr --> <! DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd"> <dwr> <allow> <create creator="new" javascript="validator"> <param name="class" value="org.apache.struts2.validators.DWRValidator"/> </create> <convert converter="bean" match="com.opensymphony.xwork2.ValidationAwareSupport"/> </allow> <signatures> <! [CDATA[ import java.util.Map; import org.apache.struts2.validators.DWRValidator; DWRValidator.doPost(String, String, Map<String, String>); ]]> </signatures> </dwr>
新建注册页面,该注册页面仅仅包含一个注册表单。设置该表单的主题为Ajax主题,并设置validate属性值为true,代码如下所示。
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> <%@ taglib prefix="s" uri="/struts-tags" %> <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>注册页面</title> <s:head theme="ajax"/> </head> <body> <! -- 注册表单 --> <center> <h2>注册页面</h2> <s:form action="register" validate="true" theme="ajax"> <s:textfield name="username" label="用户名"></s:textfield> <s:password name="password" label="密码"></s:password> <s:password name="repassword" label="确认密码"></s:password> <s:submit value="注册"></s:submit> </s:form> </center> </body> </html>
接下来新建业务控制器RegisterAction,设置同注册表单相对应的属性,并添加其setter和getter方法,代码如下所示。
package net.hncu.action;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Pattern;
import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction extends ActionSupport{
private String username;
private String password;
private String repassword;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRepassword() {
return repassword;
}
public void setRepassword(String repassword) {
this.repassword = repassword;
}
public String execute() throws Exception {
return SUCCESS;
}
}
在“struts.xml”文件中配置该业务控制器RegisterAction,并定义处理结果与视图资源之间的关系,代码如下所示。
<? xml version="1.0" encoding="UTF-8" ? > <! DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <! -- struts为配置文件根元素--> <struts> <package name="struts2" extends="struts-default"> <! -- 定义register的Action,其实现类为net.hncu.action.RegisterAction--> <action name="register" class="net.hncu.action.RegisterAction"> <! -- 定义处理结果与视图资源之间的关系--> <result name="success">/result.jsp</result> <result name="input">/register.jsp</result> </action> </package> </struts>
添加校验规则文件,这里使用非字段校验器风格来配置校验规则,当然也可以使用字段风格来配置,代码如下所示。
<? xml version="1.0" encoding="UTF-8"? > <! DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <validator type="requiredstring"> <param name="fieldName">username</param> <param name="trim">true</param> <message>必须输入用户名</message> </validator> <validator type="regex"> <param name="fieldName">username</param> <param name="expression"><! [CDATA[(\w{6,20})]]></param> <message>用户名长度必须为6至20之间</message> </validator> <validator type="requiredstring"> <param name="fieldName">password</param> <param name="trim">true</param> <message>必须输入密码</message> </validator> <validator type="regex"> <param name="fieldName">password</param> <param name="expression"><! [CDATA[(\w{6,20})]]></param> <message>密码长度必须为6至20之间</message> </validator> <validator type="requiredstring"> <param name="fieldName">repassword</param> <param name="trim">true</param> <message>必须输入确认密码</message> </validator> <validator type="regex"> <param name="fieldName">repassword</param> <param name="expression"><! [CDATA[(\w{6,20})]]></param> <message>确认密码长度必须为6至20之间</message> </validator> <validator type="fieldexpression"> <param name="fieldName">repassword</param> <param name="expression"><! [CDATA[(repassword==password)]]></param> <message>密码和确认密码必须一致</message> </validator> </validators>
运行注册页面,当不输入任何用户信息,直接单击“注册”按钮进行注册时,页面将提示错误信息,如图10.11所示。
这和客户端校验有什么区别吗?下面重点观察错误提示信息的输出。首先输入不符合长度的用户名信息,当将光标移出该文本框时,可以看出错误提示立即出现了,如图10.12所示。
图10.11 用户提示错误信息(1)
图10.12 用户提示错误信息(2)
Struts 2的Ajax表单校验,是采用异步的方式提交表单请求。和传统的Web应用不同的是,当前页面不会提交,提交的只是部分数据。用户可能根本就感觉不到这种提交,在提交的过程中依然可以进行其他的操作,而当服务器返回信息时,Struts 2会自动加载这些信息并显示给用户。