Struts2
1. 搭建Struts2的開發環境:
1) 導入相應的jar包;6個
2) 編寫struts的配置文件;struts.xml
3) struts2在web中的啟動配置;web.xml
2. 第一個struts2應用
3. actin屬性的註入message是action中的變量
<paramname="message">註入參數的值</param>
4. 編寫自定義類型轉換器:建立自定義局部類型轉換器,處理日期類型,通過繼承DefaultTypeConverter,(推薦使用StrutsTypeConverter,它繼承瞭DefaultTypeConverter)實現自己的DateTypeConverter,並且在action所在的包下創建HelloWorldAction3-conversion.properties文件;在文件中編寫對應關系:birthday=com.lcq.type.converter.DateTypeConverter
將轉換的屬性和轉換器進行綁定。如果是全局,類型轉換器就要將properties文件放置在src的根目錄下,同時修改文件的名稱為:xwork-conversion.properties,修改裡邊的內容為:要轉換的變量的類型=轉換器的名稱,
轉換器的編寫:
[java]
/**
* 建立自定義類型轉換器,處理日期類型,通過繼承DefaultTypeConverter,實現自己的DateTypeConverter
* @author lcq
*
*/
public class DateTypeConverter extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Objectvalue,
Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
try {
if (toType == Date.class) {
String[] params = (String[]) value;
return dateFormat.parse(params[0]);
} else if (toType == String.class) {
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
return super.convertValue(context, value, toType);
}
}
例如定義的action為:
[java]
package com.lcq.action;
import java.util.Date;
public class HelloWorldAction3 {
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String addUI(){
return "success";
}
public String execute(){
return "success";
}
}
5. 訪問和添加request/session/application屬性,並在頁面進行打印輸出
//從struts2封裝的ActionContext中獲取request/session/application
[java]
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "application scope");
ctx.getSession().put("session", "sessionscope");
ctx.put("request", "request scope");
jsp中:
[java]
${applicationScope.app }<br>
${sessionScope.session }<br>
${requestScope.request }<br>
6. 得到request/session/application對象:
在action中利用ServletActionContext.getxxxx()方法得到
7. 文件上傳實現:
1)上傳頁面:upload.jsp
[java]
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/employee/upload.action" method="post">
file:<input type="file"name="image">
<input type="submit" value="upload">
</form>
2) xml中的配置
[html]
<action name="upload" class="com.lcq.action.FileUpLoadAction"
method="execute">
<result name="success">/WEB-INF/page/uploadMessage.jsp</result>
</action>
3)Action中的方法
[java]
public String execute() throws Exception{
//構建真實的存放路徑
String realPath = ServletActionContext.getServletContext().getRealPath("/image");
System.out.println(realPath);
if(image != null){
File savefile = new File(new File(realPath),imageFileName);
if(!savefile.getParentFile().exists()){
savefile.getParentFile().mkdirs();
}
FileUtils.copyFile(image, savefile);
ActionContext.getContext().put("message", "上傳成功");
}
return "success";
}
4)結果頁面輸出上傳信息
[html]
<body>
message }
</body>
8. 多文件上傳隻要修改為:同時在action中將相應的參數變為數組即可
[html]
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/employee/upload.action" method="post">
file1:<input type="file"name="image"><br>
file2:<input type="file"name="image"><br>
file3:<input type="file"name="image"><br>
<input type="submit" value="upload">
action中
[java]
private File[] image;// 定義上傳文件的文件屬性
private String[] imageFileName;// 得到文件的名稱
……..
……..
……..
public String execute() throws Exception {
// 構建真實的存放路徑
StringrealPath = ServletActionContext.getServletContext().getRealPath(
"/image");
System.out.println(realPath);
if (image != null) {
for (int i = 0; i < image.length; i++) {
Filesavefile = new File(new File(realPath), imageFileName[i]);
if(!savefile.getParentFile().exists()) {
savefile.getParentFile().mkdirs();
}
FileUtils.copyFile(image[i], savefile);
}
ActionContext.getContext().put("message", "上傳成功");
}
return "success";
}
9. 編寫自定義攔截器:
1) 繼承自Interceptor接口來實現。
[java]
public class PermissionInterceptor implements Interceptor {
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
Object user = ActionContext.getContext().getSession().get("user");
if(user!=null) return invocation.invoke(); //如果user不為null,代表用戶已經登錄,允許執行action中的方法
ActionContext.getContext().put("message", "你沒有權限執行該操作");
return "success";
}
}
2) 在xml中的配置為:
[html]
<interceptors>
<interceptor name="permission"
class="com.lcq.Interceptor.PermissionInterceptor" />
<interceptor-stack name="permissionStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="permission" />
</interceptor-stack>
</interceptors>
<global-results>
<result name="success">/WEB-INF/page/message.jsp</result>
</global-results>
<action name="userAction" class="com.lcq.action.UserAction"
method="execute">
<interceptor-ref name="permissionStack" />
</action>
10. 對action的所有方法進行輸入校驗
1) 要進行驗證的內容:
[html]
<body>
<s:fielderror/>
<form action="${pageContext.request.contextPath}//person/manage_save" method="post">
用戶名:<input type="text"name="username">用戶名不能為空<br>
手機號:<input type="text"name="mobile">不能為空,並且要符合手機號的格式1,3/5/8,後面是9個數字<br>
<input type="submit" value="提 交">
</form>
</body>
2) 在action中繼承ActionSupport重寫validate()方法:
[java]
@Override
public void validate() {//對action的所有方法進行校驗
if(this.username == null || "".equals(this.username.trim())){
this.addFieldError("username", "用戶名不能為空");
}
if(this.mobile == null || "".equals(this.mobile.trim())){
this.addFieldError("mobile", "手機號不能為空");
}else{
if(!Pattern.compile("^1[358]\\d{9}{1}quot;).matcher(this.mobile).matches()){
this.addFieldError("mobile", "手機號格式不對");
}
}
}
3) 在validate方法中將錯誤信息放在錯誤集合中,轉到input頁面,所以在xml中的配置是:
[html]
<struts>
<package name="person" namespace="/person" extends="struts-default">
<action name="manage_*" class="com.lcq.action.PersonAction"
method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/WEB-INF/page/message.jsp</result>
</action>
</package>
</struts>
4) 如果隻是對個別的方法進行校驗則隻要改正validate方法為validateXxxx()就行,其中Xxxx是要校驗的方法的名稱。
[java]
public void validateUpdate() {//對action的update()方法進行校驗
if(this.username == null || "".equals(this.username.trim())){
this.addFieldError("username", "用戶名不能為空");
}
if(this.mobile == null || "".equals(this.mobile.trim())){
this.addFieldError("mobile", "手機號不能為空");
}else{
if(!Pattern.compile("^1[358]\\d{9}{1}quot;).matcher(this.mobile).matches()){
this.addFieldError("mobile", "手機號格式不對");
}
}
}
11. 基於xml的輸入校驗
1) 隻要在要校驗的action所在包下建立相應的action的xml驗證文件即可,在xml中編寫:
2) 如果隻是對action中的指定方法進行校驗則隻要修改xml的文件名即可,修改為PersonAction-person-manage_update-validation.xml則該文件隻對action中的update方法進行校驗
[html]
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用戶名不能為空!</message>
</field-validator>
</field>
<field name="mobile">
<field-validator type="requiredstring">
<message>手機號不能為空!</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手機號格式不正確!</message>
</field-validator>
</field>
</validators>
12. struts2對異常的處理機制,要編寫自己的異常處理類,在struts.xml中進行配置。
13. OGNL表達式語言。www.aiwalls.com
14. EL表達式:${username}可以訪問值棧(action。。。)對象中的所有屬性,是因為struts2對HttpServletRequest對象進行瞭封裝,但是不能訪問:request、application、session、parameters、attr等對象。如果要訪問這些對象,要使用#語法進行訪問,比如:#application.username或者#application[‘username’],特別註意在EL表達式中隻能使用值棧中屬性。
15. ognl表達式進行迭代和投影。並且能夠使用集合。
16. 可以不用ognl表達式,直接用jstl和el結合來代替使用。
17. 利用token標簽防止表單的重復提交問題
1)在jsp頁面的表單中添加<s:token></s:token>;
2)在對應的action中添加攔截器和不跳轉對應的頁面:
<interceptor-ref name="defaultStack" />
<interceptor-ref name="token" />
<result name="invalid.token">/updatePerson.jsp</result>
摘自 liuchangqing123