一女器、 rusult標(biāo)簽結(jié)果集配置
全局結(jié)果
<!-- 全局result設(shè)置-->
<global-results>
<!-- 不寫name屬性,默認(rèn)success -->
<result>/a_result/result.jsp</result>
</global-results>
作用是為package中配置的所有action提供全局的返回結(jié)果頁面
局部結(jié)果
<action name="result_*" class="com.itdream.struts2.test.Struts2_Result" method="{1}">
<!-- 默認(rèn)是SUCESS -->
<result>/a_result/result.jsp</result>
</action>
寫在action標(biāo)簽內(nèi),作用是為當(dāng)前action配置結(jié)果頁面
結(jié)果類型【掌握前四種】
1. dispatcher 轉(zhuǎn)發(fā)頁面
dispathcer轉(zhuǎn)發(fā)到頁面促王。不寫type默認(rèn)值就是dispatcher轉(zhuǎn)發(fā)
<result name="resultTypejsp" type="dispatcher">/b_resultType/resultType.jsp</result>
2. chain 轉(zhuǎn)發(fā)Action
chain是轉(zhuǎn)發(fā)到Action動(dòng)作類,result標(biāo)簽內(nèi)填寫要轉(zhuǎn)發(fā)到的action的name屬性,不能加.action的后綴
可以這樣理解,轉(zhuǎn)發(fā)相當(dāng)于在當(dāng)前struts.xml中找action的name,所以不需要加.action后綴
<result name="resultTypejsp" type="chain">resultType2</result>
3. redirect 重定向到頁面
重定向到頁面褐望。
<result name="resultTypejsp" type="redirect">/b_resultType/resultType.jsp</result>
4. redirectAction 轉(zhuǎn)發(fā)Action
重定向到Action動(dòng)作類中的action的內(nèi)容可以加.ation后綴名也可以不加
<result name="resultTypejsp" type="redirectAction">resultType2.action</result>
5. stream: 結(jié)果為文件流验庙。文件下載
<result name="success" type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">imageStream</param>
<param name="contentDisposition">attachment;filename="document.pdf"</param>
<param name="bufferSize">1024</param>
</result>
contentType:下載文件類型
inputName:對(duì)應(yīng)要輸出到客戶端流聲明的名稱
contentDisposition:下載到客戶端時(shí)熙兔,客戶端文件名稱
bufferSize:讀文件的緩存大小
6. json:轉(zhuǎn)發(fā)颁股。
<package name="xxx" namespace="/xxx" extends="json-default">
<action name="json" method="xxx"
class="org.itheima.struts.action.JsonAction">
<result name="success" type="json">
<param name="encoding">utf-8</param>
<param name="root">jsonObject</param>
</result>
</action>
</package>
由action轉(zhuǎn)發(fā)到j(luò)son結(jié)果
encoding:配置編碼格式
root:配置對(duì)象嫁审。action類中必須提供一個(gè)和root值相同的屬性名稱,且需要提供getter方法克锣。
7. jsonActionRedirect:重定向
<action name="xxx" method="xxx"
class="org.itheima.struts.action.JsonAction">
<result name="success" type="jsonActionRedirect">
xxx.action
</result>
</action>
由action重定向到j(luò)son結(jié)果。
8. 小結(jié)
dispatcher與chain屬于轉(zhuǎn)發(fā),redirect與redirectAction是重定向
這里的轉(zhuǎn)發(fā)和重定向的理解與Servlet中一樣腔长。
填寫的內(nèi)容.action也與Servlet中的理解差不多袭祟。
重定向相當(dāng)于頁面重新發(fā)送請(qǐng)求,因此后綴有.action(也可以沒有)
轉(zhuǎn)發(fā)不能有后綴.action
二、 Struts與Servlet交互對(duì)接的三種方式
客戶端與服務(wù)端交互時(shí)捞附,通常會(huì)帶參數(shù)過來巾乳,服務(wù)器也會(huì)回寫數(shù)據(jù)給客戶端您没。在此過程中,參與著請(qǐng)求胆绊,和響應(yīng)氨鹏,以及會(huì)話。servlet在此過程中提供了HttpServletRequest作為獲取請(qǐng)求數(shù)據(jù)的方案压状,HttpServletResponse作為響應(yīng)的方案仆抵,HttpSession負(fù)責(zé)了會(huì)話方案。Struts其實(shí)是基于servlet實(shí)現(xiàn)的web框架种冬,他需要遵循規(guī)則提供請(qǐng)求镣丑,響應(yīng)和會(huì)話的API供開發(fā)人員使用,因此Struts針對(duì)這一問題提供了自己的一套API封裝娱两,提供了多種方式的訪問莺匠。
1. 使用ActionContext對(duì)象間接使用Servlet的API
1.1 ActionContext對(duì)象實(shí)例獲取
ActionContext context = ActionContext.getContext();
ActionContext是綁定在當(dāng)前線程中的∈ぃ框架在請(qǐng)求線程開啟時(shí)趣竣,
將ActionContext實(shí)例對(duì)象就綁定上來了,因此我們可以通過靜態(tài)方法直接獲取旱物。
1.2 請(qǐng)求參數(shù)的獲得
Map<String, Object> parameters = context.getParamters();
相當(dāng)于Servlet中的request.getParamters()方法
1.3 存儲(chǔ)數(shù)據(jù)到域中
context.put(key, value)遥缕; 相當(dāng)于存儲(chǔ)數(shù)據(jù)到request域中
context.getSession().put(key,value); 相當(dāng)于存儲(chǔ)數(shù)據(jù)到Session域中
context.getApplication().put(key, value); 相當(dāng)于存儲(chǔ)數(shù)據(jù)到ServletContext作用域
1.4 表單提交測(cè)試
表單form.jsp :
<form action="${pageContext.request.contextPath }/servlet1.action" method="post">
用戶名<input type="text" name="username" /><br/>
密碼<input type="password" name="password" /><br/>
<input type="submit" value="提交" /><br/>
</form>
----------------------------------------------------------------------------
struts.xml中action的配置 :
<action name="servlet1" class="com.itdream.struts2.test.Struts2_Servlet" method="servlet1">
<result>/c_servlet/result.jsp</result>
</action>
----------------------------------------------------------------------------
Action動(dòng)作類:
ActionContext context = ActionContext.getContext();
//獲取到傳遞過來的所有參數(shù)
Map<String, Object> parameters = context.getParameters();
for(String key : parameters.keySet()) {
//通過獲取的key獲取到每一個(gè)對(duì)應(yīng)的String[]的值
String[] values = (String[]) parameters.get(key);
//存入request作用域
context.put(key, values[0]);
}
//轉(zhuǎn)發(fā)到頁面顯示
return SUCCESS;
---------------------------------------------------------------------------
回顯頁面 :
用戶名:${username }<br/>
密碼:${password }
2. 實(shí)現(xiàn)Struts2提供的相應(yīng)接口獲取相應(yīng)的實(shí)例
實(shí)現(xiàn)以下接口 ,提供聲明以及setter方法:
ServletContextAware
ServletRequestAware
ServletResponseAware
ParameterAware
SessionAware
ApplicationAware
PrincipalAware
例如:下面例子實(shí)現(xiàn)ServletRequestAware接口,成員位置聲明request,并提供setter方法异袄。
public class Struts2_Servlet2 extends ActionSupport implements ServletRequestAware {
//聲明request引用
private HttpServletRequest request;
@Override
//提供setter方法,Struts2框架檢測(cè)到我們實(shí)現(xiàn)了ServletRequestAware接口,會(huì)將與request對(duì)象作為參數(shù)傳遞進(jìn)來
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
// 間接方式使用Servlet的API
public String servlet2() {
//獲取參數(shù)
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username);
System.out.println(password);
//存入作用域
request.setAttribute("username", username);
request.setAttribute("password", password);
//頁面跳轉(zhuǎn)
return SUCCESS;
}
}
3. 使用ServletActionContext直接獲取實(shí)例
Struts2
還提供了ServletActionContext
類提供了多個(gè)靜態(tài)方法通砍。
1. 獲得請(qǐng)求
HttpServletRequest request = ServletActionContext.getRequest();
2. 獲得響應(yīng)
HttpServletResponse response = ServletActionContext.getResponse();
-----------------------------------------------------------------------------
3. 獲得ServletContext對(duì)象
ServletContext servletContext = ServletActionContext.getServletContext();
4. 獲得PageContext對(duì)象
PageContext pageContext = ServletActionContext.getPageContext();
============================================================================
例如:
public String servlet2() {
// 獲得request對(duì)象
HttpServletRequest request = ServletActionContext.getRequest();
// 獲取參數(shù)
String username = request.getParameter("username");
String password = request.getParameter("password");
// 存入作用域
request.setAttribute("username", username);
request.setAttribute("password", password);
// 頁面跳轉(zhuǎn)
return SUCCESS;
}
三、 Struts封裝參數(shù)的三種方式
1. 屬性驅(qū)動(dòng)(有兩種)
1.1 將Action作為javaBean類,提供屬性的setter方法
將Action動(dòng)作類作為一個(gè)JavaBean的類,提供與表單name屬性對(duì)應(yīng)的成員變量的聲明,Struts2在執(zhí)行到
param攔截器時(shí),會(huì)根據(jù)提供的setter方法將獲取到的參數(shù)一一封裝到對(duì)應(yīng)的字段中去烤蜕。
-----------------------------------------------------------------------------
例子:
form.jsp :
<form action="${pageContext.request.contextPath }/model1.action" method="post">
用戶名<input type="text" name="username" /><br/>
密碼<input type="password" name="password" /><br/>
年齡<input type="text" name="age" /><br/>
生日<input type="text" name="birthday" /><br/>
<input type="submit" value="提交" /><br/>
</form>
struts.xml :
<action name="model1" class="com.itdream.model.test.Model1"></action>
Action動(dòng)作類:
/**
* 屬性驅(qū)動(dòng):將Action動(dòng)作類作為一個(gè)javaBean類,提供屬性的setter方法,Struts2使用setter來封裝參數(shù)
*/
public class Model1 extends ActionSupport {
private String username;
private String password;
private int age;
private Date birthday;
public void setAge(int age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String execute() throws Exception {
// 我們提供了與參數(shù)name屬性相同的字段,Struts2在調(diào)用攔截器時(shí)就幫我們對(duì)數(shù)據(jù)進(jìn)行了封裝,但是必須提供setter方法
// 因此我們直接使用封裝好了的參數(shù)了
System.out.println(username);
System.out.println(password);
System.out.println(age);
System.out.println(birthday);
return NONE;
}
}
這種驅(qū)動(dòng)方式的缺陷是如果傳入的數(shù)據(jù)很多的話,那么Action動(dòng)作類中需要定義的字段也會(huì)很多,同樣setter方法也會(huì)變的很多封孙。
這使得Action中的代碼變得很臃腫。
1.2 屬性驅(qū)動(dòng) : 對(duì)象驅(qū)動(dòng)
- 在Action類中聲明一個(gè)JavaBean的實(shí)例對(duì)象,通過這個(gè)實(shí)例對(duì)象封裝傳遞過來的參數(shù)
- 這種對(duì)象驅(qū)動(dòng)的前提是:創(chuàng)建這樣一個(gè)JavaBean并提供setter/getter方法
- 在頁面?zhèn)髦档臅r(shí)候使用ognl表達(dá)式,即
對(duì)象名.字段名
例子:
form.jsp : 表單提交的參數(shù)的name屬性必須使用 對(duì)象名.字段名的方式
<form action="${pageContext.request.contextPath }/model2.action" method="post">
用戶名<input type="text" name="user.username" /><br/>
密碼<input type="password" name="user.password" /><br/>
年齡<input type="text" name="user.age" /><br/>
生日<input type="text" name="user.birthday" /><br/>
<input type="submit" value="提交" /><br/>
</form>
struts.xml :
<action name="model2" class="com.itdream.model.test.Model2Action"></action>
Action動(dòng)作類 :
public class Model2Action extends ActionSupport {
//聲明JavaBean對(duì)象用于封裝
private User user;
//必須提供對(duì)象的getter方法,Struts2框架通過getter方法獲取到這個(gè)javaBean對(duì)象,
//這個(gè)對(duì)象如果為null,Struts2會(huì)new一個(gè)對(duì)象通過setter方法放進(jìn)來,以便下一次參數(shù)的封裝
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}
這種 屬性驅(qū)動(dòng)_對(duì)象驅(qū)動(dòng) 必須提供getter方法,如果沒有提供getter方法,Struts2框架底層就無法獲得該對(duì)象進(jìn)行封裝讽营。
2. 模型驅(qū)動(dòng)
Struts2
中封裝參數(shù)還有一種方式:模型驅(qū)動(dòng)虎忌。
- 實(shí)現(xiàn)
ModelDriven
接口封裝參數(shù) - 提供一個(gè)JavaBean的類,用于封裝
- 必須在成員位置創(chuàng)建要封裝成的JavaBean的對(duì)象
- 必須實(shí)現(xiàn)getModel方法,Struts2底層獲得該對(duì)象
接收到請(qǐng)求,Struts2發(fā)現(xiàn)要跳轉(zhuǎn)的Action實(shí)現(xiàn)了ModelDriven接口,就會(huì)在modelDriven攔截器時(shí)執(zhí)行,
在這個(gè)攔截器會(huì)獲取到提供的Model對(duì)象,進(jìn)行參數(shù)的封裝。這里要注意,我們必須手動(dòng)創(chuàng)建對(duì)象,Struts2
的底層不會(huì)幫我們創(chuàng)建對(duì)象橱鹏。
另外,如果modelDriven攔截器封裝了的參數(shù),在該攔截器后的params攔截器就不會(huì)再進(jìn)行封裝了,它只會(huì)
封裝modelDriven未進(jìn)行封裝的參數(shù)膜蠢。
因此,模型驅(qū)動(dòng)優(yōu)先于屬性驅(qū)動(dòng)莉兰。
----------------------------------------------------------------------------------
例子:
form.jsp :
<form action="${pageContext.request.contextPath }/model3.action" method="post">
用戶名<input type="text" name="username" /><br/>
密碼<input type="password" name="password" /><br/>
年齡<input type="text" name="age" /><br/>
生日<input type="text" name="birthday" /><br/>
<input type="submit" value="提交" /><br/>
</form>
-------------------------------------------------------------------------------
struts.xml :
<action name="model3" class="com.itdream.model.test.Model3Action"></action>
-------------------------------------------------------------------------------
Action動(dòng)作類:
/**
* 模型驅(qū)動(dòng) : 前提: 提供一個(gè)JavaBean的模型類,以供封裝
*/
public class Model3Action extends ActionSupport implements ModelDriven<User> {
// 模型驅(qū)動(dòng):手動(dòng)構(gòu)建對(duì)象
private User user = new User();
@Override
// Struts2獲取到這個(gè)對(duì)象模型,用于封裝
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}
模型封裝,對(duì)于封裝單個(gè)對(duì)象是非常方便的,但是如果要封裝多個(gè)對(duì)象,還是需要使用屬性驅(qū)動(dòng)中的對(duì)象驅(qū)動(dòng)
3. 屬性驅(qū)動(dòng)-對(duì)象驅(qū)動(dòng)封裝對(duì)象到List
集合中
與上面屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)一樣挑围。
1. 必須提供JavaBean的實(shí)體類用于封裝對(duì)象。
2. 頁面jsp傳參到Action動(dòng)作類使用OGNL表達(dá)式糖荒。
3. Action動(dòng)作類中聲明該對(duì)象,和模型驅(qū)動(dòng)不同,屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)可以不創(chuàng)建對(duì)象,框架會(huì)幫我們創(chuàng)建對(duì)象杉辙。
4. 必須提供get和set方法,以便Struts2的底層進(jìn)行封裝
form.jsp
頁面OGNL表達(dá)式傳參:
<form action="${pageContext.request.contextPath }/model4.action" method="post">
用戶名<input type="text" name="list[0].username" /><br/>
密碼<input type="password" name="list[0].password" /><br/>
年齡<input type="text" name="list[0].age" /><br/>
生日<input type="text" name="list[0].birthday" /><br/>
用戶名<input type="text" name="list[1].username" /><br/>
密碼<input type="password" name="list[1].password" /><br/>
年齡<input type="text" name="list[1].age" /><br/>
生日<input type="text" name="list[1].birthday" /><br/>
用戶名<input type="text" name="list[2].username" /><br/>
密碼<input type="password" name="list[2].password" /><br/>
年齡<input type="text" name="list[2].age" /><br/>
生日<input type="text" name="list[2].birthday" /><br/>
<input type="submit" value="提交" /><br/>
</form>
這里name屬性使用,list[0]...代表放入List集合中的某一個(gè)對(duì)象,用list[n].字段名 代表傳遞單個(gè)對(duì)象的單個(gè)字段的參數(shù)。
struts.xml : 請(qǐng)求對(duì)應(yīng)Action配置
<action name="model4" class="com.itdream.model.test.Model4Action"></action>
Action動(dòng)作類
/**
* 封裝多個(gè)對(duì)象到List集合中 前提: 提供JavaBean類用于封裝每一個(gè)對(duì)象,頁面使用OGNL表達(dá)式
*/
public class Model4Action extends ActionSupport {
// 提供List集合的聲明,用于封裝對(duì)象
private List<User> list = new ArrayList<>();
//必須提供List集合的get方法,讓Struts2框架能夠拿到該對(duì)象
public List<User> getList() {
return list;
}
//如果拿到的對(duì)象為空,Struts2會(huì)利用set方法聲明的引用設(shè)置一個(gè)新的對(duì)象捶朵。即框架底層會(huì)幫我new一個(gè)對(duì)象,并傳遞進(jìn)來,以便進(jìn)行封裝
public void setList(List<User> list) {
this.list = list;
}
@Override
public String execute() throws Exception {
System.out.println(list);
return NONE;
}
}
4. 屬性驅(qū)動(dòng)-對(duì)象驅(qū)動(dòng)封裝對(duì)象到Map
集合中
與上面屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)一樣蜘矢。
1. 必須提供JavaBean的實(shí)體類用于封裝對(duì)象狂男。
2. 頁面jsp傳參到Action動(dòng)作類使用OGNL表達(dá)式。
3. Action動(dòng)作類中聲明該對(duì)象,和模型驅(qū)動(dòng)不同,屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)可以不創(chuàng)建對(duì)象,框架會(huì)幫我們創(chuàng)建對(duì)象品腹。
4. 必須提供get和set方法,以便Struts2的底層進(jìn)行封裝
form.jsp
頁面OGNL表達(dá)式傳參:
<form action="${pageContext.request.contextPath }/model5.action" method="post">
用戶名<input type="text" name="map['one'].username" /><br/>
密碼<input type="password" name="map['one'].password" /><br/>
年齡<input type="text" name="map['one'].age" /><br/>
生日<input type="text" name="map['one'].birthday" /><br/>
用戶名<input type="text" name="map['two'].username" /><br/>
密碼<input type="password" name="map['two'].password" /><br/>
年齡<input type="text" name="map['two'].age" /><br/>
生日<input type="text" name="map['two'].birthday" /><br/>
用戶名<input type="text" name="map['three'].username" /><br/>
密碼<input type="password" name="map['three'].password" /><br/>
年齡<input type="text" name="map['three'].age" /><br/>
生日<input type="text" name="map['three'].birthday" /><br/>
<input type="submit" value="提交" /><br/>
</form>
這里name屬性使用,map['one']...來代表放入map集合的第幾個(gè)對(duì)象,傳遞的單個(gè)對(duì)象的字段的參數(shù),使用map['one'].字段名來表示
struts.xml : 請(qǐng)求對(duì)應(yīng)Action配置
<action name="model5" class="com.itdream.model.test.Model5Action"></action>
Action動(dòng)作類
/**
* 屬性驅(qū)動(dòng): 對(duì)象驅(qū)動(dòng)封裝多個(gè)對(duì)象的參數(shù) 前提: 有一個(gè)JavaBean的實(shí)體類用于封裝每個(gè)對(duì)象 jsp頁面使用OGNL表達(dá)式表示每一個(gè)字段屬性進(jìn)行傳參
* 提供get和set方法
*/
public class Model5Action extends ActionSupport {
// 聲明/創(chuàng)建一個(gè)Map集合用于封裝參數(shù)
private Map<String, User> map = new HashMap<>();
//提供get方法,Struts2框架可以獲得該map集合用于封裝
public Map<String, User> getMap() {
return map;
}
//提供set方法,Struts2如果獲得的map集合為null,會(huì)自動(dòng)創(chuàng)建一個(gè)然后傳遞Map集合的引用到當(dāng)前聲明
public void setMap(Map<String, User> map) {
this.map = map;
}
@Override
public String execute() throws Exception {
for(String key : map.keySet()) { //遍歷獲取每一個(gè)key
System.out.println(key+">>>"+map.get(key));
System.out.println("==============================");
}
return NONE;
}
}
四岖食、 Struts2的參數(shù)類型轉(zhuǎn)換器【了解】
解決的問題:
客戶端傳輸過程中傳輸特定類型的字符串時(shí),到action類中需要轉(zhuǎn)換為對(duì)應(yīng)的對(duì)象時(shí)舞吭,中間的轉(zhuǎn)換的問題泡垃。
主要解決的是對(duì)象類型的轉(zhuǎn)換。
一般來說,Struts2提供的類型轉(zhuǎn)換器已經(jīng)很強(qiáng)大了镣典,一般不需要再自己自定義類型轉(zhuǎn)換器了兔毙。
-----------------------------------------------------------------------------
如果類型轉(zhuǎn)換錯(cuò)誤,會(huì)提示需要跳轉(zhuǎn)到result標(biāo)簽name為input對(duì)應(yīng)的頁面去 :
解決方案 : 配置input結(jié)果集視圖,跳轉(zhuǎn)回輸入頁面:
<result name="input">/error.jsp</result>
又發(fā)現(xiàn)如果只是這么處理讓其跳回輸入頁面沒有友好提示 :
解決方案:
頁面需要回顯錯(cuò)誤提示兄春。使用<s:fielderror/>自動(dòng)回顯錯(cuò)誤信息澎剥。
要使用該標(biāo)簽,必須先引入標(biāo)簽庫:
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:fielderror>填寫錯(cuò)誤</s:fielderror>
-----------------------------------------------------------------------------
為什么參數(shù)轉(zhuǎn)換錯(cuò)誤會(huì)跳轉(zhuǎn)到input邏輯視圖頁面赶舆?
1. 在接收請(qǐng)求參數(shù)時(shí)哑姚, 必然要進(jìn)行類型轉(zhuǎn)換。如果Struts2的類型轉(zhuǎn)換器執(zhí)行類型轉(zhuǎn)換時(shí)出現(xiàn)錯(cuò)誤芜茵,那么叙量,Struts2 內(nèi)部提供了一個(gè)名為conversionError的攔截器來處理錯(cuò)誤,該攔截器將負(fù)責(zé)將對(duì)應(yīng)錯(cuò)誤封裝成表單域錯(cuò)誤(FieldError)九串,并將這些錯(cuò)誤信息放入ActionContext中的一個(gè)集合中绞佩;
2. 當(dāng)執(zhí)行到WorkFlow攔截器的時(shí)候,該攔截器會(huì)判斷ActionContext的集合中是否存在錯(cuò)誤信息猪钮,如果存在品山,則,自動(dòng)跳轉(zhuǎn)到input邏輯視圖烤低。(一般我們還配置到原來的頁面肘交,讓用戶更正輸入的數(shù)據(jù))。
自定義轉(zhuǎn)換器的配置方案
1. 新建一個(gè)類繼承StrutsTypeConverter扑馁,實(shí)現(xiàn)內(nèi)部方法
public class DateConversion extends StrutsTypeConverter {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
if (values != null && values.length > 0) {
String dateString = values[0];
try {
return sdf.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
return null;
}
@Override
public String convertToString(Map context, Object o) {
if (o != null && o instanceof Date) {
return sdf.format(o);
}
return null;
}
}
2. 在項(xiàng)目的src下新建xwork-conversion.properties,在其中配置要轉(zhuǎn)換的類型(注冊(cè)全局轉(zhuǎn)換器)
java.util.Date=org.itdream.struts.action.DateConversion
五涯呻、 異常Exception捕獲
解決的問題:當(dāng)action代碼執(zhí)行中出現(xiàn)異常時(shí),錯(cuò)誤信息會(huì)反饋到客戶頁面腻要,用戶體驗(yàn)不好
局部異常捕獲:
在action標(biāo)簽中配置exception-mapping標(biāo)簽:
<result name="xxx" type="redirect">/xxx.jsp</result>
<exception-mapping result="xxx" exception="java.lang.Throwable" />
* exception-mapping標(biāo)簽中的result屬性指向捕獲異常后出錯(cuò)的頁面結(jié)果复罐。
* exception-mapping標(biāo)簽中的exception屬性指的是要捕獲那種異常。
全局異常捕獲:
在package標(biāo)簽中配置global-exception-mapping標(biāo)簽 :
<global-results>
<result name="xxx">xxx.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="xxx"
exception="java.lang.Throwable">
</exception-mapping>
</global-exception-mappings>
* global-exception-mapping標(biāo)簽中的result屬性指向捕獲異常后出錯(cuò)的頁面結(jié)果雄家。
* global-exception-mapping標(biāo)簽中的exception屬性指的是要捕獲那種異常市栗。
異常顯示 :
異常捕獲的作用是為了提示用戶界面的顯示結(jié)果,但如果出錯(cuò)了,開發(fā)人員是要知道錯(cuò)誤日志的填帽。
如果要開啟錯(cuò)誤日志,在action標(biāo)簽中配置如下:
<interceptor-ref name="defaultStack">
<param name="exception.logEnabled">true</param>
<param name="exception.logLevel">error</param>
</interceptor-ref>
六咙好、 CRM案例:使用Hibernate與Struts2添加客戶
1. 分析
- 創(chuàng)建
Web
工程,Struts
環(huán)境搭建- 導(dǎo)入
Struts2
的jar包(與Hibernate的jar包不沖突) -
web.xml
配置Struts2的前端控制器 - 配置
struts.xml
,確定請(qǐng)求與Action動(dòng)作類,以及響應(yīng)與result頁面的對(duì)應(yīng)關(guān)系 - Struts2搭建完成
- 導(dǎo)入
-
Hibernate
環(huán)境搭建- 導(dǎo)入
Hibernate
所需的jar包:required,c3p0,log4j - 創(chuàng)建
Hibernate
所需的ORM關(guān)系- R : 關(guān)系型數(shù)據(jù)庫篡腌,創(chuàng)建所需數(shù)據(jù)庫的表
sys_customer
- O : 持久化類,編寫持久化類,
Customer
- M : 配置文件勾效,配置文件間的映射關(guān)系,
Customer.hbm.xml
- R : 關(guān)系型數(shù)據(jù)庫篡腌,創(chuàng)建所需數(shù)據(jù)庫的表
-
Hibernate
的核心配置文件hibernate.cfg.xml
- 連接數(shù)據(jù)庫的基本配置
- 配置與線程綁定的
Session
- 普通配置
Hibernate的方言配置,實(shí)現(xiàn)了跨數(shù)據(jù)庫
- 顯示sql語句
- 格式化sql語句
-
Hibernate
的自動(dòng)建表hbm2ddl
-
Hibernate
的事務(wù)隔離級(jí)別配置 -
c3p0
連接池配置
- 加載映射文件
- 編寫
Hibernate
工具類HibernateUtils
- 測(cè)試
Hibernate
是否搭建成功
- 導(dǎo)入
- 實(shí)現(xiàn)客戶添加功能
- 這里我為了使用以下
result標(biāo)簽的redirectAction
的功能,修改menu.jsp
點(diǎn)擊添加客戶時(shí)跳轉(zhuǎn)到CustomerAction
嘹悼,最后跳轉(zhuǎn)到add.jsp
-
add.jsp
填寫完成點(diǎn)擊提交,將數(shù)據(jù)提交到CustomerAction動(dòng)作類
中,在Action
動(dòng)作類實(shí)現(xiàn)將客戶保存到數(shù)據(jù)庫中 - 添加完成訪問
CustomerAction
的查詢所有客戶的list
方法 - 功能完成
- 這里我為了使用以下
2. 環(huán)境搭建【省略】
3. 代碼體現(xiàn)
3.1 修改menu.jsp
點(diǎn)擊添加客戶跳轉(zhuǎn)到Action
<TD class=menuSmall><A class=style2 href="${pageContext.request.contextPath}/customer_add.action" target="main">- 新增客戶</A></TD>
3.2 struts.xml配置根據(jù)訪問路徑跳轉(zhuǎn)對(duì)應(yīng)Action
為了方便,我直接將struts.xml中所有配置直接粘貼過來,看的時(shí)候根據(jù)邏輯看
<?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>
<!-- 開發(fā)者模式開啟 -->
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<!-- 與customer有關(guān)的Action -->
<action name="customer_*" class="com.itdream.struts2.crm.web.action.CutomerAction" method="{1}">
<result name="addJsp">/jsp/customer/add.jsp</result>
<result name="saveSucess" type="redirectAction">customer_list</result>
<!-- 默認(rèn)轉(zhuǎn)發(fā) -->
<result name="listCustomer">/jsp/customer/list.jsp</result>
</action>
</package>
</struts>
3.3 Action動(dòng)作類
/**
* 處理有關(guān)Cutomer的Action動(dòng)作類
*/
public class CutomerAction extends ActionSupport implements ModelDriven<Customer>{
//手動(dòng)創(chuàng)建model對(duì)象,如果不創(chuàng)建只是聲明的話,Struts2底層不會(huì)幫我們創(chuàng)建
private Customer customer = new Customer();
@Override
//必須提供getModel方法,Struts2才能獲得我們創(chuàng)建的model對(duì)象,進(jìn)行封裝
public Customer getModel() {
return customer;
}
//用戶點(diǎn)擊添加客戶其實(shí)可以直接讓他跳轉(zhuǎn)add.jsp,這里為了實(shí)現(xiàn)以下result標(biāo)簽的redirect重定向跳轉(zhuǎn)
public String add() {
return "addJsp";
}
//用戶添加客戶
public String save() {
System.out.println("=======================");
//獲取表單提交參數(shù),這里使用模型驅(qū)動(dòng)Struts2框架幫我們進(jìn)行封裝
//實(shí)現(xiàn)ModelDriven的接口,泛型是Customer的實(shí)體類,成員變量創(chuàng)建Model對(duì)象,添加getModel方法讓Struts2能夠獲得聲明的對(duì)象
//--------------------------------------
//調(diào)用Service業(yè)務(wù)層保存客戶
CustomerService service = new CustomerServiceImpl();
service.saveCustomer(customer);
return "saveSucess";
}
//查看所有客戶列表
public String list() {
//調(diào)用Service業(yè)務(wù)層
CustomerService service = new CustomerServiceImpl();
List<Customer> listCustomer = service.findAllCustomer();
//存入request作用域
ServletActionContext.getRequest().setAttribute("list", listCustomer);
//跳轉(zhuǎn)頁面
return "listCustomer";
}
}
3.4 Service業(yè)務(wù)層
public class CustomerServiceImpl implements CustomerService {
@Override
// 添加客戶
public void saveCustomer(Customer customer) {
// 獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
// 開啟事務(wù)
Transaction transaction = session.beginTransaction();
try {
// 調(diào)用dao層
CustomerDAO dao = new CustomerDAOImpl();
dao.saveCustomer(customer);
} catch (Exception e) {
// 異常回滾,Hibernate默認(rèn)異巢愎回滾
// transaction.rollback();
e.printStackTrace();
} finally {
// 提交事務(wù)
transaction.commit();
}
}
@Override
//查看所有客戶
public List<Customer> findAllCustomer() {
//獲取與線程綁定的Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
//開啟事務(wù)
Transaction transaction = session.beginTransaction();
List<Customer> listCustomer = null;
try {
//調(diào)用dao層
CustomerDAO dao = new CustomerDAOImpl();
listCustomer = dao.findAllCustomer();
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}finally {
//提交事務(wù)
transaction.commit();
}
return listCustomer;
}
}
3.5 dao持久層
public class CustomerDAOImpl implements CustomerDAO {
@Override
//添加客戶
public void saveCustomer(Customer customer) {
//獲取Session對(duì)象
Session session = HibernateUtils.getCurrentSession();
//保存對(duì)象到Session緩沖區(qū),事務(wù)提交自動(dòng)更新到數(shù)據(jù)庫
session.save(customer);
}
@Override
//查詢所有客戶
public List<Customer> findAllCustomer() {
//獲得Session
Session session = HibernateUtils.getCurrentSession();
return session.createCriteria(Customer.class).list();
}
}