項目中我們經常遇到這樣的需求——頁面部分刷新,例如:添加用戶,轉到添加用戶頁面時,頁面自動加載了所有部門。
完整流程:選擇所屬部門,填寫用戶名和密碼,點擊“註冊”
填寫用戶名後,需要立即檢查數據庫是否存在此用戶名,如何在不刷新頁面的情況下實現此效果?
但看上面提出的問題並不難,情況很常見,都知道使用ajax實現,但是如何在struts中自定義結果集來實現ajax——這是這篇博客的重點。
(注:servlet要麼轉發要麼重定向,struts2可以自定義結果集)
轉發、重定向、action2action都會使頁面刷新,滿足不了頁面無刷新的需求,因此,可以自己定義一個結果集來解決(通過此結果集把服務器端(action)的數據回調到客戶端)。
工具:MyEclipse8.5、tomcat6.0.39
一,步驟:
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的核芯過濾器)
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xmlversion="1.0" encoding="UTF-8"?>
<web-appversion="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 配置Struts2的核心的過濾器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app></span>
----User.java:用戶實體類
<span style="font-family:KaiTi_GB2312;font-size:18px;">importjava.io.Serializable;
public class Userimplements Serializable{
private Long uid;//用戶id
private String username;//用戶名
private String password;//密碼
//*********get/set方法*********************************************
publicLong getUid() {
returnuid;
}
publicvoid setUid(Long uid) {
this.uid= uid;
}
publicString getUsername() {
returnusername;
}
publicvoid setUsername(String username) {
this.username= username;
}
publicString getPassword() {
returnpassword;
}
publicvoid setPassword(String password) {
this.password= password;
}
}</span>
----BaseAction.java:抽象Action類,封裝公共內容
<span style="font-family:KaiTi_GB2312;font-size:18px;">importjava.lang.reflect.ParameterizedType;
importcom.opensymphony.xwork2.ActionSupport;
importcom.opensymphony.xwork2.ModelDriven;
/**
* 這裏封裝一些共用的內容
* @author Administrator
*
*/
public classBaseAction<T> extends ActionSupport implements ModelDriven<T>{
privateClass classt;
privateT t;
publicstatic final String ADDUI = "addUI";
publicString addUI = ADDUI;
publicBaseAction(){
try{
ParameterizedTypetype = (ParameterizedType)this.getClass().getGenericSuperclass();
this.classt= (Class)type.getActualTypeArguments()[0];
this.t= (T)this.classt.newInstance();
}catch(Exceptione){
e.printStackTrace();
}
}
publicT getModel() {
//TODO Auto-generated method stub
returnthis.t;
}
}</span>
----UserAction.java:用戶模塊處理 Action
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="color:#333333;">importcn.itcast.oa0909.domain.User;
importcn.itcast.oa0909.struts2.action.base.BaseAction;
importcom.opensymphony.xwork2.ActionContext;
publicclass UserAction extendsBaseAction<User>{
/**
* 跳轉到添加用戶頁面
* @return
*/
publicString addUI(){
returnaddUI;
}
/**
* 校驗用戶名是否存在
* @return
*/
publicString checkUserName(){
if("學敏".equals(this.getModel().getUsername())){//如果輸入的用戶名爲"學敏"
ActionContext.getContext().getValueStack().push("該用戶名已經存在");//把數據壓入棧頂
}else{//如果輸入的用戶名就不是“學敏”
ActionContext.getContext().getValueStack().push("該用戶名可以使用");//把數據壓入棧頂
}
returnSUCCESS;
}
}</span></span>
----AjaxResult.java:自定義結果集(注:通過此結果集把服務器端(action)的數據回調到客戶端)
<span style="font-family:KaiTi_GB2312;font-size:18px;">importjavax.servlet.http.HttpServletResponse;
importorg.apache.struts2.ServletActionContext;
importcom.opensymphony.xwork2.ActionContext;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.Result;
public classAjaxResult implements Result{
publicvoid execute(ActionInvocation invocation) throws Exception {
HttpServletResponseresponse = ServletActionContext.getResponse();
response.setCharacterEncoding("utf-8");//處理中文亂碼問題
String message =ActionContext.getContext().getValueStack().peek().toString();//得到棧頂元素
response.getWriter().print(message);//將得到的棧頂元素返回到客戶端
}
}</span>
----struts.xml:Struts配置文件
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xmlversion="1.0" encoding="UTF-8"?>
<!DOCTYPE strutsPUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<!-- 配置文件改了以後不用重新啓動 -->
<constant name="struts.devMode"value="true"/>
<constantname="struts.ui.theme" value="simple"/>
<includefile="struts/struts-user.xml"></include>
<!-- 配置自定義結果集-->
<packagename="ajax-default" extends="struts-default">
<result-types>
<result-typename="ajax"class="cn.itcast.oa0909.result.AjaxResult"></result-type>
</result-types>
</package>
</struts>
</span>
----struts-user.xml
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xmlversion="1.0" encoding="UTF-8"?>
<!DOCTYPE strutsPUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<!--繼承Struts-default結果集 -->
<package name="user"namespace="/" extends="struts-default">
<actionname="userAction_*" method="{1}"class="cn.itcast.oa0909.struts2.action.UserAction">
<resultname="addUI">WEB-INF/jsp/user/add.jsp</result>
</action>
</package>
<!-- 繼承自定義結果集——ajax-default(在struts.xml文件中已配置) -->
<package name="userjson"namespace="/" extends="ajax-default">
<actionname="userJSONAction_*" method="{1}"class="cn.itcast.oa0909.struts2.action.UserAction">
<resulttype="ajax"></result>
</action>
</package>
</struts> </span>
----add.jsp:添加用戶頁面
<span style="font-family:KaiTi_GB2312;font-size:18px;"><%@ pagelanguage="java" import="java.util.*"pageEncoding="UTF-8"%>
<scriptlanguage="javascript"src="${pageContext.request.contextPath}/js/jquery-1.4.2.js"></script>
<scriptlanguage="javascript"src="${pageContext.request.contextPath}/js/user_add.js"></script>
<html>
<head>
<title>用戶信息</title>
<metahttp-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<form action="userAction_add.action">
<table>
<tr><tdwidth="100">所屬部門</td>
<td><selectname="departmentId" class="SelectStyle">
<optionvalue="0" selected="selected">請選擇部門</option>
<optionvalue="7">總經理室</option>
<optionvalue="1">市場部</option>
<optionvalue="2">諮詢部</option>
<optionvalue="3">招生部</option>
<optionvalue="4">教學部</option>
<optionvalue="5">後勤部</option>
</select>
</td>
</tr>
<tr>
<td>用戶名:</td>
<td><input type="text"name="username"/><labelid="message"></label></td>
</tr>
<tr>
<td>密碼:</td>
<td><input type="password"name="password"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit"value="註冊"/></td>
</tr>
</table>
</form>
</body>
</html></span>
(注:假設這裏的所屬部門中的數據是頁面加載時從數據庫中讀取的,而不是如上所示寫死的)
頁面效果:
所屬部門下拉框展開,如下所示:
-----user_add.js:添加用戶頁面所需js
<span style="font-family:KaiTi_GB2312;font-size:18px;">var user = {
//初始化事件
inintEvent: function(){
$("input[name='username']").unbind("blur");
$("input[name='username']").bind("blur",function(){//name值爲"username"的文本框失去焦點觸發的函數
user.checkUser($(this).val());//調用檢查用戶函數(校驗用戶名是否存在)
});
},
/**
* 校驗用戶名是否存在
*/
checkUser:function(username){
var a ="a";
var parameter = {//參數:用戶名
username:username
};
/**
*userJSONAction_checkUserName.action:請求地址
* parameter:參數
*function(data){}:回調函數
*/
$.post("userJSONAction_checkUserName.action",parameter,function(data){
$("#message").text(data);//將服務器返回的值賦給id="message"的label提示框,並顯示
if(data=="該用戶名可以使用"){
$("#message").css("color","blue");//設置提示文字的顏色
}else{
$("#message").css("color","red");//設置提示文字的顏色
}
});
}
};
//頁面加載時運行
$().ready(function(){
user.inintEvent();//頁面加載時,調用初始化事件
</span>
二,運行
輸入地址: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如何做到複用,能不能做到複用,這是個問題。
基於以上問題,下篇博客介紹——json類型的結果集——JSON插件是Struts2的Ajax插件,通過利用JSON插件,允許開發者以非常靈活的方式開發AJAX應用。