1. 程式人生 > >框架 day30 Struts2練習專案-人員管理(增刪改查)

框架 day30 Struts2練習專案-人員管理(增刪改查)

Struts2練習專案人員管理

1案例名稱:
人員管理系統:user manager system (ums)



2案例功能:

*使用者登入 -- xml校驗、登入攔截器
*查詢所有使用者(條件查詢)
*新增(上傳簡歷)-- token
*編輯(下載) -- 標籤回顯
*查詢
*刪除(略)

3技術分析



4環境搭建

4.1jar包

*struts
*dbutils
*c3p0
*mysql


4.2配置檔案

4.2.1struts.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<!-- 常量 -->
	<constant name="struts.devMode" value="true"></constant>
	<constant name="struts.ui.theme" value="simple"></constant>


	<package name="strutsDemo" namespace="/" extends="struts-default">
	
	</package>
</struts>


4.2.2web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	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_3_0.xsd">
 	<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>
</web-app>



4.2.3c3p0-config.xml

位置:src
<c3p0-config>


	<!-- 命名的配置 -->
	<named-config name="strutsExerciseDBXml">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/strutsExerciseDB</property>
		<property name="user">root</property>
		<property name="password">1234</property>
    	<!-- 如果池中資料連線不夠時一次增長多少個 -->
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">20</property>
		<property name="minPoolSize">10</property>
		<property name="maxPoolSize">40</property>
		<property name="maxStatements">0</property>
		<property name="maxStatementsPerConnection">5</property>
	</named-config>
</c3p0-config> 




4.2.4log4j.properties  , 

日誌配置檔案,存在src下
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=info, stdout



4.3包結構



4.4工具類

public class JdbcUtils {
	
	//建立一個連線池--c3p0 ,名稱來自 c3p0-config.xml配置
	private static ComboPooledDataSource dataSource = new ComboPooledDataSource("strutsExerciseDBXml");
	
	/**
	 * 獲得資料來源(連線池)
	 * @return
	 */
	public static DataSource getDataSource(){
		return dataSource;
	}


}


4.5資料庫和表

create database strutsExerciseDB character set utf8;
use strutsExerciseDB;


CREATE TABLE S_User(
	userID INT NOT NULL AUTO_INCREMENT, #主鍵ID
	userName VARCHAR(50)   NULL,  #使用者姓名
	loginName VARCHAR(50)   NULL, #登入名
	loginPwd VARCHAR(50)  NULL,   #密碼#
	sex VARCHAR(10)  NULL,        #性別(例如:男,女)
	birthday VARCHAR(50) NULL,    #出生日期
	education VARCHAR(20)  NULL,  #學歷(例如:研究生、本科、專科、高中)
	telephone VARCHAR(50)  NULL,  #電話 
	interest VARCHAR(20)  NULL,   #興趣愛好(例如:體育、旅遊、逛街)
	path VARCHAR(500)  NULL,      #上傳路徑(path路徑)
	filename VARCHAR(100)  NULL,  #上傳檔名稱(檔名)
	remark VARCHAR(500)  NULL,    #備註
	PRIMARY KEY (userID)
) ;


insert into s_user(userName,loginName,loginPwd,sex) values('龍哥','jack','1234','男');
insert into s_user(userName,loginName,loginPwd,sex,filename) values('鳳姐','rose','1234','女','簡歷.doc');



5編寫javabean

	private int userID;
	private String userName;
	private String loginName;
	
	private String loginPwd;
	private String sex;
	private String birthday;
	
	private String education;
	private String telephone;
	private String interest;
	
	private String path;
	private String filename;
	private String remark;
	
	private String isUpload;		//用於判斷檔案是否上傳。上傳檔名是否存在 filename


6使用者登入

6.1步驟

*jsp登入,提供表單,將html表單修改s標籤
*編寫action類,同時配置struts.xml
*action類呼叫service進行登入處理
*service呼叫dao進行查詢
*資料校驗
*攔截器

6.2修改login.jsp

*將html表單修改成struts標籤


6.3編寫action類

*繼承ActionSupport 

*實現ModelDriven

	//#1 封裝資料:查詢條件、新增普通欄位、編輯id、
	private User user = new User();


*提供login處理方法, 和 登入首頁,需要使用service

	/**
	 * 登入
	 * @return
	 */
	@InputConfig(resultName="loginInput") 	//登入校驗返回位置
	public String login(){
		
		User loginUser = userService.login(user);
		if(loginUser != null){
			//登入成功 -- session
			ActionContext.getContext().getSession().put("loginUser", loginUser);
			return "loginSuccess";
		} else {
			//賬號密碼不正確
			this.addFieldError("loginName", "使用者名稱和密碼不匹配");
			return "login";
		}
		
	}
	
	/**
	 * 登入成功首頁
	 * @return
	 */
	public String home(){
		return "home";
	}


6.4struts.xml

	<package name="strutsDemo" namespace="/" extends="struts-default">
		<!-- 使用者action -->
		<action name="userAction_*" class="cn.itcast.ums.web.action.UserAction" method="{1}">
			<!-- 1 登入成功 ,重定向-->
			<result name="loginSuccess" type="redirectAction">
				<param name="namespace">/</param>
				<param name="actionName">userAction_home</param>
			</result>
			<!-- 2 登入首頁 -->
			<result name="home">/login/home.jsp</result>
			<!-- 3 需要登入 -->
			<result name="login">/login/login.jsp</result>
			
		</action>
	</package>




6.5service 編寫

public class UserServiceImpl implements UserService {


	private UserDao userDao = new UserDaoImpl();
	@Override
	public User login(User user) {
		return userDao.find(user.getLoginName(),user.getLoginPwd());
	}


}




6.6dao編寫

public class UserDaoImpl implements UserDao {
	
	// 1 提供DBUtils 核心類 -- 必須提供資料來源,DBUtils底層自己維護Connection
	private QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());


	@Override
	public User find(String loginName, String loginPwd) {
		try {
			// 2 準備sql語句
			String sql = "select * from s_user where loginName = ? and loginPwd = ?";
			// 3 準備實際引數
			Object[] params = {loginName,loginPwd};
			// 4 執行
			return runner.query(sql, new BeanHandler<User>(User.class), params);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


}




6.7xml資料校驗

*檔名稱:
單個方法:action類名-action名稱-validation.xml 【】
所有方法:action類名-validation.xml


6.7.1xml檔案

<!DOCTYPE validators PUBLIC
  		"-//Apache Struts//XWork Validator 1.0.3//EN"
  		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
	<!-- 1 使用者名稱 -->
	<field name="loginName">
		<!-- 必填 -->
		<field-validator type="requiredstring">
			<message><![CDATA[使用者名稱不能為空]]></message>
		</field-validator>
		<!-- 長度 -->
		<field-validator type="stringlength">
			<param name="minLength">2</param>
			<param name="maxLength">16</param>
			<message><![CDATA[使用者名稱長度必須${minLength}-${maxLength}字元之間]]></message>
		</field-validator>
	</field>
	<!-- 2 密碼 -->
	<field name="loginPwd">
		<field-validator type="requiredstring">
			<!-- key從國際化資原始檔獲得提示資訊 -->
			<message key="loginPwd.message"></message>
		</field-validator>
	</field>
</validators>



6.7.2properties檔案

loginPwd.message = \u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A




6.8攔截器

*登入攔截器目的:除了登入功能之外,其他的功能都需要先登入,在訪問。
*介面:Interceptor
*實現類:MethodFilterInterceptor  指定不需要攔截方法名,也可以指定必須進行攔截方法。
*預設情況自定義攔截器無效,必須註冊、然後使用。

6.8.1實現類

public class LoginInterceptor extends MethodFilterInterceptor {


	@Override
	public String doIntercept(ActionInvocation ai) throws Exception {
		//確定使用者必須登入,如果是登入方法進行放行(配置檔案明確)
		Object loginUser = ActionContext.getContext().getSession().get("loginUser");
		if(loginUser == null){
			
			/** 友好提示資訊start*/
			// 1 獲得當前action例項
			Object actionObject = ai.getAction();
			// 2 判斷當前action類是否繼承ActionSupport
			if(actionObject instanceof ActionSupport){
				ActionSupport actionSupport = (ActionSupport) actionObject;
				actionSupport.addFieldError("loginName", "請登入");
			}
			/** 友好提示資訊end*/
			
			// 沒有登入--必須登入
			return "login";
		}
		//放行
		return ai.invoke();
	}


}


6.8.2配置struts.xml 



		<!-- 1 配置攔截器 -->
		<interceptors>
			<!-- 1.1 註冊 -->
			<interceptor name="loginInterceptor" class="cn.itcast.ums.web.interceptor.LoginInterceptor"></interceptor>
			
			<!-- 1.2 宣告自定義攔截器棧(多個攔截器的組合) -->
			<interceptor-stack name="loginStack">
				<!-- 1.2.1 預設棧  -->
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<!-- 1.2.2 其他攔截器 -->
				<!-- 1.2.3 自定義攔截器 -->
				<interceptor-ref name="loginInterceptor">
					<!-- * 設定哪些方法不需要攔截,多個方法之間使用逗號分隔 -->
					<param name="excludeMethods">login</param>
				</interceptor-ref>
			</interceptor-stack>			
		</interceptors>
	
		<!-- 2 將自定義棧,宣告預設棧 -->
		<default-interceptor-ref name="loginStack"></default-interceptor-ref>



7查詢所有



7.1修改left.jsp


				<!-- 查詢所有,檔案顯示位置:/user/list.jsp -->
				<s:a namespace="/" action="userAction_findAll" target="mainFrame">使用者管理</s:a>


7.2編寫action

	/**
	 * 查詢所有
	 * @return
	 */
	public String findAll(){
		
		//通知service 查詢
		List<User> allUser = userService.findAll(user);
		// 將查詢結果存放值棧 , jsp通過key直接獲得
		ActionContext.getContext().getValueStack().set("allUser", allUser);
		
		return "findAll";
	}



7.3struts.xml

			<!-- 3.5 查詢所有 -->
			<result name="findAll">/user/list.jsp</result>

7.4list.jsp展示



8條件查詢

8.1修改list.jsp

*提供表單
<%--條件查詢 start --%>
<s:form namespace="/" action="userAction_findAll" id="Form1" name="Form1" >
	<table cellpadding="0" cellspacing="0" border="0" width="100%">
		<tr>
			<td height="22" align="center" bgColor="#f5fafe" class="ta_01">
				使用者姓名
			</td>
			<td class="ta_01" bgColor="#ffffff">
				<s:textfield name="userName" cssClass="bg" size="15"></s:textfield>
			</td>
			<td height="22" align="center" bgColor="#f5fafe" class="ta_01">
				性別:
			</td>
			<td class="ta_01" bgColor="#ffffff">
				<s:select list="{'男','女'}" headerKey="" headerValue="--選擇性別--" name="sex" id="sex"></s:select>
			</td>
		</tr>
		<tr>
			<td height="22" align="center" bgColor="#f5fafe" class="ta_01">
				學歷:
			</td>
			<td class="ta_01" bgColor="#ffffff">
				<s:select list="{'博士','碩士','本科','專科','高中'}" headerKey="" headerValue="--選擇學歷--" name="education" id="education"></s:select>
			</td>
			<td height="22" align="center" bgColor="#f5fafe" class="ta_01">
				是否上傳簡歷
			</td>
			<td class="ta_01" bgColor="#ffffff">
				<s:select list="#{'1':'有','2':'無'}" headerKey="" headerValue="--請選擇--" name="isUpload" id="isUpload"></s:select>
			</td>
		</tr>
		<tr>
			<td width="100" height="22" align="center" bgColor="#f5fafe"
				class="ta_01">
			</td>
			<td class="ta_01" bgColor="#ffffff">
				<font face="宋體" color="red">  </font>
			</td>
			<td align="right" bgColor="#ffffff" class="ta_01"><br><br></td>
			<td align="right" bgColor="#ffffff" class="ta_01">
				<s:submit id="search" value="查詢" cssClass="button_view"></s:submit>
				     
				<s:reset id="reset" value="重置" cssClass="button_view"></s:reset>
			</td>
		</tr>
	</table>
</s:form>
<%--條件查詢 end --%>


8.2編寫dao拼寫sql

@Override
	public List<User> findAll(User user) {
		try {
			//#1 條件, 拼寫sql,拼寫實際引數
			// #1.1 拼寫sql
			StringBuffer sqlBuffer = new StringBuffer("select * from s_user where 1=1 ");
			// #1.2 拼寫實際引數 (順序,重複)
			List<Object> paramsList = new ArrayList<Object>();
			
			// #1.3 拼寫條件
			// * 使用者名稱
			//if(user.getUserName() != null && !"".equals(user.getUserName())){
			if(StringUtils.isNotBlank(user.getUserName())){
				sqlBuffer.append(" and userName like ? ");
				paramsList.add("%"+user.getUserName()+"%");
			}
			// * 性別
			if(StringUtils.isNotBlank(user.getSex())){
				sqlBuffer.append(" and sex = ? ");
				paramsList.add(user.getSex());
			}
			
			// * 學歷
			if(StringUtils.isNotBlank(user.getEducation())){
				sqlBuffer.append(" and education = ? ");
				paramsList.add(user.getEducation());
			}
			
			// * 是否上傳 -- 依賴:檔名是否為空
			if("1".equals(user.getIsUpload())){
				//上傳--不為空
				sqlBuffer.append(" and filename is not null");
			}else if("2".equals(user.getIsUpload())){
				//沒有上傳 -- 為空
				sqlBuffer.append(" and filename is null");
			}
			
			//條件end
			
			//2 準備sql
			String sql = sqlBuffer.toString();
			//3準備實際引數
			Object [] params = paramsList.toArray();
			//4執行
			return runner.query(sql, new BeanListHandler<User>(User.class), params);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

9使用者新增

*檔案上傳

9.1分析





9.2修改add.jsp

*位置:/strutsExercise/WebRoot/user/add.jsp

9.3action類提供add方法

*提供addUI,顯示jsp頁面
*提供add進行新增處理

/**
	 * 新增jsp頁面顯示
	 * @return
	 */
	public String addUI(){
		return "addUI";
	}
	/**
	 * 新增功能
	 * @return
	 */
	public String add(){
		try {
			// 1 處理上傳檔案,將資料封裝到javabean -- 允許沒有上傳內容
			if (upload != null) {
				// * 有上傳檔案--簡歷 。 需要給javabean的路徑path和檔名filename賦值


				// 1.1 確定路徑 , 例如: /WEB-INF/upload/uuid (保持只是內容)
				String path = "/WEB-INF/upload/" + UUID.randomUUID().toString();
				// 1.2 確定在tomcat下實際路徑,並獲得檔案
				File file = new File(ServletActionContext.getServletContext()
						.getRealPath(path));
				// 1.3 儲存檔案--執行拷貝
				FileUtils.copyFile(upload, file);
				// 1.4 賦值
				user.setPath(path);
				user.setFilename(uploadFileName);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		//保持功能
		this.userService.addUser(user);
		return "add";
	}



9.4service


@Override
	public void addUser(User user) {
		userDao.save(user);
	}



9.5dao


	@Override
	public void save(User user) {
		try {
			// 2 sql
			String sql = "insert into s_user(userName,loginName, loginPwd,sex,birthday, education,telephone,interest, path,filename,remark) values(?,?, ?,?,?, ?,?,?, ?,?,?)";
			// 3 引數
			Object [] params = {user.getUserName(),user.getLoginName(),
								user.getLoginPwd(),user.getSex(),user.getBirthday(),
								user.getEducation(),user.getTelephone(),user.getInterest(),
								user.getPath(),user.getFilename(),user.getRemark()};
			// 4 執行
			runner.update(sql, params);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


9.6struts.xml

*需要配置jsp顯示,新增成功之後處理
<!-- 3.6 新增jsp頁面顯示 -->
<result name="addUI">/user/add.jsp</result>
<!-- 3.7 新增成功,重定向到查詢所有 -->
<result name="add" type="redirectAction">userAction_findAll</result>



10編輯使用者

*標籤回顯
*檔案下載

10.1分析



10.2action類提供 preEdit方法

*通過id查詢


/** 
	 * 編輯前操作 , 通過id查詢使用者
	 * @return
	 */
	
	public String preEdit(){
		// 通過id查詢
		User tempUser = this.userService.findById(user.getUserID());
		// 存放到值棧root
		ActionContext.getContext().getValueStack().push(tempUser);
		return "preEdit";
	}




10.3修改edit.jsp

*位置:/strutsExercise/WebRoot/user/edit.jsp
*提供隱藏欄位給伺服器傳遞資料
 <%--編輯表單start --%>
		<s:form name="Form1" namespace="/" action="userAction_edit" enctype="multipart/form-data">
			 
			<table cellSpacing="1" cellPadding="5" width="100%" align="center" bgColor="#eeeeee" style="border: 1px solid #8ba7e3" border="0">
				<tr>
					<td class="ta_01" align="center" bgColor="#afd1f3" colSpan="4"
						height="26">
						<strong><STRONG>編輯使用者</STRONG>
						<%--提供隱藏欄位,使用者id  %{必須解析}  %{'字串'}--%>
						<s:hidden name="userID" value="%{userID}"></s:hidden>
						<%--上傳路徑和名稱 --%>
						<s:hidden name="path" value="%{path}"></s:hidden>
						<s:hidden name="filename" value="%{filename}"></s:hidden>
						</strong>
					</td>
				</tr>

				<tr>
					<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
						登入名:............



10.4編寫action類 edit方法

*按照一定的邏輯處理檔案上傳

public String edit() throws IOException{
		/*
		 * 處理檔案上傳:邏輯處理--自己規定
		 * 	之前有檔案:
		 * 		編輯沒有上傳,使用之前的
		 * 		編輯上傳,將之前覆蓋的
		 *  之前沒有
		 *  	編輯有
		 */
		
		// 編輯上傳
		if(upload != null){
			//上一次是否上傳
			if(StringUtils.isNotBlank(user.getPath()) && StringUtils.isNotBlank(user.getFilename())){
				//覆蓋
				// 1.1 檔案內容覆蓋
				File file = new File(ServletActionContext.getServletContext()
						.getRealPath(user.getPath()));
				// 1.3 儲存檔案--執行拷貝
				FileUtils.copyFile(upload, file);
				// 1.2 檔名稱覆蓋
				user.setFilename(uploadFileName);
			} else {
				//新上傳
				
				// 1.1 確定路徑 , 例如: /WEB-INF/upload/uuid (保持只是內容)
				String path = "/WEB-INF/upload/" + UUID.randomUUID().toString();
				// 1.2 確定在tomcat下實際路徑,並獲得檔案
				File file = new File(ServletActionContext.getServletContext()
						.getRealPath(path));
				// 1.3 儲存檔案--執行拷貝
				FileUtils.copyFile(upload, file);
				// 1.4 賦值
				user.setPath(path);
				user.setFilename(uploadFileName);
			}
		}
		
		
		//TODO 編輯操作完成
		return "edit";
	}



10.5struts.xml

<!-- 3.8 編輯前操作,查詢使用者,在jsp頁面顯示 -->
<result name="preEdit">/user/edit.jsp</result>
<!-- 3.9 編輯成功,重定向首頁 -->
<result name="edit" type="redirectAction">userAction_findAll</result>



11下載

11.1action類

// * 下載的資源,target是struts.xml配置的
	private InputStream target;
	public InputStream getTarget() {
		return target;
	}
	// * 確定下載的檔名稱:處理中文亂碼問題
	private String downloadFileName;
	public String getDownloadFileName() throws UnsupportedEncodingException {
		if(downloadFileName != null){
			return new String(downloadFileName.getBytes(),"ISO-8859-1");
		} 
		// 給<s:debug> 提供
		return null;
	}
	
	//下載
	public String download(){
		// 給下載資源賦值
		// 1 通過id查詢 使用者名稱 和 路徑
		User tempUser = this.userService.findById(user.getUserID());
		if(tempUser == null){
			// 有人改路徑,使用者存在
			this.addFieldError("download", "下載資源不存在");
			return "error";
		}
		
		// 2 獲得下載資源
		this.target = ServletActionContext.getServletContext().getResourceAsStream(tempUser.getPath());
		if(target == null){
			// 下載資源不存在
			this.addFieldError("download", "下載資源已經被刪除");
			return "error";
		}
		
		// 3 賦值檔名稱
		this.downloadFileName = tempUser.getFilename();
		
		return "download";
	}



11.2struts.xml

<!-- 3.10 下載配置 
				* action提供給struts下載內容
				* struts設定下載頭,確定下載名稱檔案
			-->
			<result name="download" type="stream">
				<!-- 3.10.1 確定檔案內容,使用action類的指定的getter方法屬性:target -->
				<param name="inputName">target</param>
				<!-- 3.10.2 確定下載響應頭 -->
				<param name="contentDisposition">attachment;filename=${downloadFileName}</param>
			</result>




12使用者名稱是否存在(ajax)

*ajax


12.1使用struts json

*打入jar包


*使用父包
	<package name="strutsDemo" namespace="/" extends="json-default">
PS:因為父包也繼承了預設struts-default


*結果使用 json型別,讓struts生成json資料
			<result name="checkName" type="json">
				<!-- 3.11.1 設定從值棧獲得那個資料 
					* root 確定值棧的資料名稱,如果沒有設定,預設從棧頂獲取。
				-->
				<param name="root">msgMapKey</param>
			</result>


12.2jsp傳送ajax

		<%--匯入工具包,自定義jQuery --%>
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/jQuery.js"></script>
		<script type="text/javascript">
			function checkLoginNameFn(obj){
				// 請求路徑
				var url = "${pageContext.request.contextPath}/userAction_checkLoginName";
				// 請求引數
				var params = {"loginName":obj.value};
				
				//傳送ajax請求
				jQuery.post(url,params,function(data){
					//參考案例:/day23/WebRoot/e_ajax_json.jsp
					if(data.isHasUser){
						//可用
					} else {
						//不可用
					}
					//將提示顯示登入名稱之後
					document.getElementById("loginNameSpan").innerHTML = data.msg;
				});
			}
		</script>


12.3action編寫方法

*將提示資訊存放Map,方法struts生成json資料
	public String checkLoginName(){
		
		//1 通過登入名稱查詢使用者是否存在
		User tempUser = this.userService.findByName(user.getLoginName());
		//2 拼寫提示資訊
		Map<String,String> msgMap = new HashMap<String, String>();
		if(tempUser != null){
			//存在
			msgMap.put("msg", "使用者名稱已經存在");
			msgMap.put("isHasUser", "false");		//是否可以使用:不能使用
		} else {
			//不存在
			msgMap.put("msg", "使用者名稱可以使用");
			msgMap.put("isHasUser", "true");		//是否可以使用:能使用
		}
		
		//將生成資料壓入棧頂
		ActionContext.getContext().getValueStack().set("msgMapKey", msgMap);
		return "checkName";
	}


*如果使用set方法,在struts.xml 必須配置 結果集型別json的root屬性
*如果使用push方法,壓入到棧頂,直接使用。struts json 預設從棧頂獲得資料。


12.4struts.xml配置


<!-- 3.11 ajax -->
			<result name="checkName" type="json">
				<!-- 3.11.1 設定從值棧獲得那個資料 
					* root 確定值棧的資料名稱,如果沒有設定,預設從棧頂獲取。
				-->
				<param name="root">msgMapKey</param>
			</result>



12.5jsp 響應之後處理

	//傳送ajax請求
				jQuery.post(url,params,function(data){
					//參考案例:/day23/WebRoot/e_ajax_json.jsp
					if(data.isHasUser){
						//可用
					} else {
						//不可用
					}
					//將提示顯示登入名稱之後
					document.getElementById("loginNameSpan").innerHTML = data.msg;
				});




13js時間

13.1匯入js類庫

<%--匯入時間類庫 --%>
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/Calendar.js"></script>


13.2使用

<%--
	struts標籤:readonly="true"
	html標籤:readonly="readonly"
	--%>
<s:textfield readonly="true" onclick="c.showMoreDay=true;c.show(this);">