转自:http://blog.csdn.net/hanxuemin12345/article/details/38763057
项目中我们经常遇到这样的需求——页面部分刷新,例如:添加用户,转到添加用户页面时,页面自动加载了所有部门。
完整流程:选择所属部门,填写用户名和密码,点击“注册”,填写用户名后,需要立即检查数据库是否存在此用户名,如何在不刷新页面的情况下实现此效果?
但看上面提出的问题并不难,情况很常见,都知道使用ajax实现,但是如何在struts中自定义结果集来实现ajax——这是这篇博客的重点。
(注:转发、重定向、action2action都会使页面刷新,满足不了页面无刷新的需求,因此,可以自己定义一个结果集来解决(通过此结果集把服务器端(action)的数据回调到客户端)。
1,创建一个名称为Struts+AjaxResult的Web项目
2,导入Struts相关包
3,配置web.xml文件
4,创建PoJo类——User.java
5,创建Action基类和子Action类——BaseAction、UserAction.java
6,创建自定义结果集——AjaxResult.java
7,配置Struts.xml文件
8,创建页面——add.jsp
9,创建js文件——user_add.js
(注:还需引入jquery.js文件)
----web.xml:配置文件(注:配置Struts2的核芯过滤器)
1 <span style="font-family:KaiTi_GB2312;font-size:18px;"><?xmlversionxmlversion="1.0" encoding="UTF-8"?> 2 <web-appversionweb-appversion="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 8 <!-- 配置Struts2的核心的过滤器 --> 9 <filter> 10 <filter-name>struts2</filter-name> 11 <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 12 </filter> 13 <filter-mapping> 14 <filter-name>struts2</filter-name> 15 <url-pattern>/*</url-pattern> 16 </filter-mapping> 17 18 19 <welcome-file-list> 20 <welcome-file>index.jsp</welcome-file> 21 </welcome-file-list> 22 </web-app></span>
---User.java:用户实体类
1 <span style="font-family:KaiTi_GB2312;font-size:18px;">importjava.io.Serializable; 2 public class Userimplements Serializable{ 3 private Long uid;//用户id 4 private String username;//用户名 5 private String password;//密码 6 7 //*********get/set方法********************************************* 8 publicLong getUid() { 9 returnuid; 10 } 11 12 publicvoid setUid(Long uid) { 13 this.uid= uid; 14 } 15 16 publicString getUsername() { 17 returnusername; 18 } 19 20 publicvoid setUsername(String username) { 21 this.username= username; 22 } 23 24 publicString getPassword() { 25 returnpassword; 26 } 27 28 publicvoid setPassword(String password) { 29 this.password= password; 30 } 31 32 }</span>
----BaseAction.java:抽象Action类,封装公共内容
1 <span style="font-family:KaiTi_GB2312;font-size:18px;">importjava.lang.reflect.ParameterizedType; 2 3 importcom.opensymphony.xwork2.ActionSupport; 4 importcom.opensymphony.xwork2.ModelDriven; 5 6 /** 7 * 这里封装一些共用的内容 8 * @author Administrator 9 * 10 */ 11 public classBaseAction<T> extends ActionSupport implements ModelDriven<T>{ 12 privateClass classt; 13 privateT t; 14 15 publicstatic final String ADDUI = "addUI"; 16 publicString addUI = ADDUI; 17 18 publicBaseAction(){ 19 try{ 20 ParameterizedTypetype = (ParameterizedType)this.getClass().getGenericSuperclass(); 21 this.classt= (Class)type.getActualTypeArguments()[0]; 22 this.t= (T)this.classt.newInstance(); 23 }catch(Exceptione){ 24 e.printStackTrace(); 25 } 26 } 27 28 publicT getModel() { 29 //TODO Auto-generated method stub 30 returnthis.t; 31 } 32 }</span>
----UserAction.java:用户模块处理 Action
1 importcn.itcast.oa0909.domain.User; 2 importcn.itcast.oa0909.struts2.action.base.BaseAction; 3 importcom.opensymphony.xwork2.ActionContext; 4 5 publicclass UserAction extendsBaseAction<User>{ 6 7 /** 8 * 跳转到添加用户页面 9 * @return 10 */ 11 publicString addUI(){ 12 returnaddUI; 13 } 14 /** 15 * 校验用户名是否存在 16 * @return 17 */ 18 publicString checkUserName(){ 19 20 if("学敏".equals(this.getModel().getUsername())){//如果输入的用户名为"学敏" 21 ActionContext.getContext().getValueStack().push("该用户名已经存在");//把数据压入栈顶 22 }else{//如果输入的用户名就不是“学敏” 23 ActionContext.getContext().getValueStack().push("该用户名可以使用");//把数据压入栈顶 24 } 25 26 returnSUCCESS; 27 }
----AjaxResult.java:自定义结果集(注:通过此结果集把服务器端(action)的数据回调到客户端)
1 importjavax.servlet.http.HttpServletResponse; 2 3 importorg.apache.struts2.ServletActionContext; 4 5 importcom.opensymphony.xwork2.ActionContext; 6 importcom.opensymphony.xwork2.ActionInvocation; 7 importcom.opensymphony.xwork2.Result; 8 9 public classAjaxResult implements Result{ 10 publicvoid execute(ActionInvocation invocation) throws Exception { 11 HttpServletResponseresponse = ServletActionContext.getResponse(); 12 response.setCharacterEncoding("utf-8");//处理中文乱码问题 13 String message =ActionContext.getContext().getValueStack().peek().toString();//得到栈顶元素 14 response.getWriter().print(message);//将得到的栈顶元素返回到客户端 15 } 16 }
----struts.xml:Struts配置文件
1 <?xmlversionxmlversion="1.0" encoding="UTF-8"?> 2 <!DOCTYPE strutsPUBLIC 3 "-//ApacheSoftware Foundation//DTD Struts Configuration 2.1.7//EN" 4 "http://struts.apache.org/dtds/struts-2.1.7.dtd"> 5 <struts> 6 <!-- 配置文件改了以后不用重新启动 --> 7 <constant name="struts.devMode"value="true"/> 8 <constantnameconstantname="struts.ui.theme" value="simple"/> 9 10 <includefileincludefile="struts/struts-user.xml"></include> 11 12 <!-- 配置自定义结果集--> 13 <packagenamepackagename="ajax-default" extends="struts-default"> 14 <result-types> 15 <result-typenameresult-typename="ajax"class="cn.itcast.oa0909.result.AjaxResult"></result-type> 16 </result-types> 17 </package> 18 </struts>
----struts-user.xml
1 <?xmlversionxmlversion="1.0" encoding="UTF-8"?> 2 <!DOCTYPE strutsPUBLIC 3 "-//ApacheSoftware Foundation//DTD Struts Configuration 2.1.7//EN" 4 "http://struts.apache.org/dtds/struts-2.1.7.dtd"> 5 <struts> 6 7 <!--继承Struts-default结果集 --> 8 <package name="user"namespace="/" extends="struts-default"> 9 <actionnameactionname="userAction_*" method="{1}"class="cn.itcast.oa0909.struts2.action.UserAction"> 10 <resultnameresultname="addUI">WEB-INF/jsp/user/add.jsp</result> 11 </action> 12 </package> 13 14 <!-- 继承自定义结果集——ajax-default(在struts.xml文件中已配置) --> 15 <package name="userjson"namespace="/" extends="ajax-default"> 16 <actionnameactionname="userJSONAction_*" method="{1}"class="cn.itcast.oa0909.struts2.action.UserAction"> 17 <resulttyperesulttype="ajax"></result> 18 </action> 19 </package> 20 21 </struts>
---add.jsp:添加用户页面
1 <%@ pagelanguage="java" import="java.util.*"pageEncoding="UTF-8"%> 2 <scriptlanguagescriptlanguage="javascript"src="${pageContext.request.contextPath}/js/jquery-1.4.2.js"></script> 3 <scriptlanguagescriptlanguage="javascript"src="${pageContext.request.contextPath}/js/user_add.js"></script> 4 <html> 5 <head> 6 <title>用户信息</title> 7 <metahttp-equivmetahttp-equiv="Content-Type" content="text/html;charset=utf-8" /> 8 </head> 9 <body> 10 <form action="userAction_add.action"> 11 <table> 12 <tr><tdwidthtdwidth="100">所属部门</td> 13 <td><selectnameselectname="departmentId" class="SelectStyle"> 14 <optionvalueoptionvalue="0" selected="selected">请选择部门</option> 15 <optionvalueoptionvalue="7">总经理室</option> 16 <optionvalueoptionvalue="1">市场部</option> 17 <optionvalueoptionvalue="2">咨询部</option> 18 <optionvalueoptionvalue="3">招生部</option> 19 <optionvalueoptionvalue="4">教学部</option> 20 <optionvalueoptionvalue="5">后勤部</option> 21 </select> 22 </td> 23 </tr> 24 <tr> 25 <td>用户名:</td> 26 <td><input type="text"name="username"/><labelidlabelid="message"></label></td> 27 </tr> 28 <tr> 29 <td>密码:</td> 30 <td><input type="password"name="password"/></td> 31 </tr> 32 <tr> 33 <td colspan="2"><input type="submit"value="注册"/></td> 34 </tr> 35 36 </table> 37 </form> 38 </body> 39 40 </html>
(注:假设这里的所属部门中的数据是页面加载时从数据库中读取的,而不是如上所示写死的)
页面效果:
所属部门下拉框展开,如下所示:
-----user_add.js:添加用户页面所需js
1 var user = { 2 //初始化事件 3 inintEvent: function(){ 4 $("input[name='username']").unbind("blur"); 5 $("input[name='username']").bind("blur",function(){//name值为"username"的文本框失去焦点触发的函数 6 user.checkUser($(this).val());//调用检查用户函数(校验用户名是否存在) 7 }); 8 }, 9 /** 10 * 校验用户名是否存在 11 */ 12 checkUser:function(username){ 13 var a ="a"; 14 var parameter = {//参数:用户名 15 username:username 16 }; 17 18 /** 19 *userJSONAction_checkUserName.action:请求地址 20 * parameter:参数 21 *function(data){}:回调函数 22 */ 23 $.post("userJSONAction_checkUserName.action",parameter,function(data){ 24 $("#message").text(data);//将服务器返回的值赋给id="message"的label提示框,并显示 25 if(data=="该用户名可以使用"){ 26 $("#message").css("color","blue");//设置提示文字的颜色 27 }else{ 28 $("#message").css("color","red");//设置提示文字的颜色 29 } 30 }); 31 32 } 33 }; 34 //页面加载时运行 35 $().ready(function(){ 36 user.inintEvent();//页面加载时,调用初始化事件
二,运行
输入地址:http://localhost:8080/Struts2+AjaxResult/userAction_addUI.action,显示如下页面
用户名输入“学敏”,数据库中已经存在了此用户名,则当鼠标离开用户名文本框(即,用户名文本框失去焦点)时(注:此处为ajax请求,它的处理过程,和应用的技术点为本博客讲解的重点),就会提示“该用户已经存在”;用户名输入“张三那”,数据库中不存在,则提示“该用户名可以使用”
三,总结
自定义结果集的缺点:这样自定义的结果集,写死了,不能做到客户端需要什么数据就传什么数据;如,UserAction中的代码:
ActionContext.getContext().getValueStack().push("该用户名已经存在");//把数据压入栈顶
——把客户端需要的数据都要压入栈顶
AjaxResult中的代码:
String message =ActionContext.getContext().getValueStack().peek().toString();//得到栈顶元素
response.getWriter().print(message);//将得到的栈顶元素返回到客户端
——获取栈顶的元素,再通过 response.getWriter().print()语句将的到的栈顶元素返回到客户端;
那么问题来了,如果我需要的数据增加了,怎么办?毋庸置疑,在UserAction 中将增加的数据压入栈顶,还要在AjaxResult中依次获取数据,再通过 response.getWriter().print()依次返回,也就是会说此AjaxResult与UserAction要一一对应,必须写死在程序里,不灵活,不能做到客户端需要什么数据就传什么数据;
另外还有一个问题,如果其他业务,比如“部门管理”模块的一个功能也需要从服务器端返回数据到客户端,那是不是还要再写一个自定义结果集,AjaxResult如何做到复用,能不能做到复用,这是个问题。