搭建Struts2開發環境步驟
1、建立web工程2、導包3、創建XXXXXAction類文件* 注意:繼承ActionSupport,如果不繼承,就不能使用struts進行開發public class HelloWorldAction extends ActionSupport /*implements Action*/ {public HelloWorldAction(){System.out.println("這是HelloWorldAction的構造方法");}public String execute() throws Exception {//System.out.println(this.getUsername());System.out.println("歡迎您訪問HelloWorldAction!");return SUCCESS;}}4、struts.xml配置文件* 引入規範:struts2-core-2.1.8.1包下struts-2.1.7.dtd* 引入加載的文件屬性:struts2-core-2.1.8.1包下org.apache.struts2.default.properties (用於constent引入)<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN""http://struts.apache.org/dtds/struts-2.1.7.dtd"><struts><!-- 改變訪問的action的後綴,改成.do --><!-- <constant name="struts.action.extension" value="action"></constant>--><!-- 處理國際化加載的資源文件(.properties),默認是false:當修改國際化資源文件,不自動加載ture:自動加載資源文件 --><!-- <constant name="struts.i18n.reload" value="true"></constant>--><!-- 處理struts2的配置文件(.xml)默認是false:當修改struts的配置文件,不自動加載ture:當修改完struts.xml文件時,自動加載--><!--<constant name="struts.configuration.xml.reload" value="true"></constant>--><!-- struts的開發模式默認是false:生產模式true:開發模式struts.i18n.reload:自動加載struts.configuration.xml.reload:自動加載--><constant name="struts.devMode" value="true"></constant><!-- 加載其他配置文件 --><include file="cn/itcast/web/a_primer/struts_primer.xml"></include></struts>5、在web.xml文件中,添加過濾器(加載所有的struts的配置文件)<!-- 這是struts2的核心過濾器,如果不使用該過濾器,不能使用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>6、導入相應jsp,測試
Struts2的四大作用域對象的獲取
1、在struts.xml文件中添加
<struts>
<package name="context" namespace="/context" extends="struts-default">
<action name="contextAction_test" class="cn.itcast.web.b_context.ContextAction">
<result name="success">/context/success.jsp</result>
</action>
<action name="contextAction02_test" class="cn.itcast.web.b_context.Context02Action">
<result name="attr">/context/attr.jsp</result>
</action>
</package>
</struts>2、在XXXXXAction(類)中
方法一(ContextAction)
* 使用ServletActionContext獲取
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("username", "username_request");
HttpServletResponse response = ServletActionContext.getResponse();
Map<String, Object> mapSession = ServletActionContext.getContext().getSession();
mapSession.put("username", "username_session");
ServletContext sc = ServletActionContext.getServletContext();
sc.setAttribute("username", "username_application");方法二(Context02Action) (開發中常用)
* 需要實現 implements ServletRequestAware,SessionAware,ServletContextAware (實現三個接口)
private HttpServletRequest request = null;
private Map<String, Object> session = null;
private ServletContext context = null;
//獲取request
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
//獲取session
public void setSession(Map<String, Object> session) {
this.session = session;
}
//獲取application
public void setServletContext(ServletContext context) {
this.context = context;
}
struts.xml中的三個作用域
在配置文件struts.xml文件中的3個作用域(指定type參數)
* 轉發,默認是dispatcher
<result name="success" type="dispatcher">
/resulttype/success.jsp
</result>
* 重定向,redirect(指定同一資源下,重定向到某一文件)
<result name="success" type="redirect">
/resulttype/success.jsp
</result>
* 不同資源下的重定向,redirectAction
有2個參數需要指定
<result name="success" type="redirectAction">
<!-- name="actionName":需要訪問的action的路徑
name="namespace":指向另一個Action資源的命名空間
如果使用重定向,request作用域將無效-->
<param name="actionName">helloWorldAction</param>
<param name="namespace">/primer</param>
</result>
Struts2中的通配符
1、操作struts.xml文件
(1)* 通過method指定類中的方法
<action name="bookAction" class="cn.itcast.web.d_pattern.BookAction" method="add">
<result name="add">
/pattern/BookAction.jsp
</result>
</action>
(2)* 通配符實例一
<action name="*_add" class="cn.itcast.web.d_pattern.BookAction" method="add">
<result name="add">
/pattern/BookAction.jsp
</result>
</action>
* 通配符實例二
<action name="*_add" class="cn.itcast.web.d_pattern.{1}" method="add">
<result name="add">
/pattern/{1}.jsp
</result>
</action>
* 通配符實例三
<action name="*_*" class="cn.itcast.web.d_pattern.{1}" method="{2}">
<result name="{2}">
/pattern/{1}.jsp
</result>
<result name="delete">
/pattern/success.jsp
</result>
</action>
(3)* 動態方法調用(作爲了解)
<!-- 是否調用action中的動態方法:true(默認):允許調用(在action中可以!號)
false:不允許調用調用動態方法 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>、
<!-- 動態方法調用
<a href="${pageContext.request.contextPath}/pattern/BookAction!add.action">圖書添加</a><br>
<a href="${pageContext.request.contextPath}/pattern/BookAction!delete.action">圖書刪除</a><br>
-->
<!-- <action name="BookAction" class="cn.itcast.web.d_pattern.BookAction">
<result name="add">/pattern/BookAction.jsp</result>
<result name="delete">/pattern/success.jsp</result>
</action>-->
(4)使用通配符(必須掌握) 開發中最常用
<action name="BookAction_*" class="cn.itcast.web.d_pattern.BookAction" method="{1}">
<result name="add">/pattern/BookAction.jsp</result>
<result name="delete">/pattern/success.jsp</result>
</action>
(5)在package中定義全局的轉發
<global-results>
<result name="delete">
/pattern/successGlobal.jsp
</result>
</global-results>
Struts2類型轉換
1、類型轉換
(1)定義表單:
編號:<input type="text" name="id" value="1"><br>
姓名:<input type="text" name="userName" value=""><br>
(1)在UserAction中
使用javabean獲取表單中的值,而且支持各種數據類型,如果數據類型不匹配,則拋異常
(如果,不想拋異常,需要在struts.xml文件指定錯誤頁面)
<result name="input">/converter/error.jsp</result>
在頁面訪問進入Action之前,先執行jvavbean的set()方法將屬性值獲取到javabean中
(2)定義表單:
創建日期:<input type="text" name="createTime" value="">格式yyyyMMdd<br>
(2)使用struts2默認的日期類型格式(XXXX-XX-XX),如果想實現(XXXXXXXX)
需要自定義類型轉換器
局部:ActionClassName-conversion.properties,放置到類路徑下格式:需要轉換的屬性名=轉換器
本例中在cn.itcast.web.e_converter建立UserAction-conversion.properties文件
對應的是UserAction的屬性,配置如下:
createTime=cn.itcast.web.e_converter.DateConverter
全局:放置到src目錄,命名爲xwork-conversion.properties格式:需要轉換的數據類型=轉換器
在本例中,對應所有Action中Date類型都有效
java.util.Date=cn.itcast.web.e_converter.DateConverter
類型轉換器:
public class DateConverter extends DefaultTypeConverter {
/**
* context:OGNL上下文對象(下節課講)
* Object value:表單中<input type="text" name="createTime" value="">中name的屬性值,也是需要轉換的值
* Class toType:對應轉換的類型
* * 自定義類型轉換器
* 局部配置:在當前目錄e_converter中建立ActionClassName-conversion.properties
* 針對於本例UserAction-conversion.properties
* return :轉換後的結果
* */
public Object convertValue(Map context, Object value, Class toType) {
System.out.println("Object value="+value);
System.out.println("Class toType="+toType);
if(value==null){
return null;
}
if(toType==null){
return null;
}
if(toType!=java.util.Date.class){
return null;
}
//需要轉換yyyyMMdd
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
if (value instanceof String[]) {
String[] date = (String[]) value;
if(date[0]!=null && !"".equals(date[0].trim())){
try {
return format.parse(date[0].trim());
} catch (ParseException e) {
return null;
}
}
}
return null;
}
}
(3) 學歷id:<input type="text" name="edu.eduid" value=""><br>
學歷名稱:<input type="text" name="edu.eduname" value=""><br>
(3)創建類文件Edu,放置eduid和eduname並生成set和get方法
在UserAction中,聲明屬性命名爲edu,並生成set和get方法
(4) 員工姓名:<input type="text" name="emps[0].name" value=""><br>
薪水:<input type="text" name="emps[0].salary" value=""><br>
員工姓名:<input type="text" name="emps[1].name" value=""><br>
薪水:<input type="text" name="emps[1].salary" value=""><br>
(4)
創建類文件Emp,放置name和salary並生成set和get方法
在UserAction中,聲明屬性命名爲emps的一個集合(Collection、List),並生成set和get方法
(3)(4)做爲了解,不常用
struts文件上傳
1、單文件上傳
(1)表單要求:
<form action="${pageContext.request.contextPath}/upload/uploadAction_saveFile.action"
name="form1" method="post" enctype="multipart/form-data" >
上傳文件名稱:<input type="file" name="uploadImage">
<input type="submit" value="上傳">
</form>
(2)在UploadAction中添加
//上傳文件名稱:<input type="file" name="uploadImage">
//對應表單中的屬性,文件以流的形式傳遞,獲取文件
private File uploadImage;
//獲取上傳文件的類型,格式表單中屬性的名稱+ContentType,本例uploadImage+ContentType
private String uploadImageContentType;
//獲取上傳文件的名稱,格式表單中屬性的名稱+FileName,本例uploadImage+FileName
private String uploadImageFileName;
(3)實現
public String saveFiles(){
System.out.println("歡迎進入UploadAction...");
//處理文件上傳
//需求:將文件上傳到WebRoot下upload文件,首先找到upload的目錄
ServletContext sc = ServletActionContext.getServletContext();
String path = sc.getRealPath("/file");
File file = new File(path,uploadImageFileName);
//將一個文件拷貝到另一個文件中
try {
FileUtils.copyFile(uploadImage, file);
} catch (IOException e) {
throw new RuntimeException(e);
}
return "success";
}
(4)控制上傳文件的大小、類型、擴展名
在struts.xml文件中添加:
全局:設置全局攔截器,放置在<package></package>中,對所有action有效
<interceptor-stack name="defaultStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
將fileUpload放置到默認棧的後面,當默認棧執行完畢後,再執行
<interceptor-ref name="fileUpload">
<param name="maximumSize">5229339</param>
<param name="allowedTypes">application/pdf,application/vnd.ms-excel</param>
<param name="allowedExtensions">.pdf,.txt</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
局部:放置<action></action>中,指定當前action有效
<interceptor-ref name="defaultStack">
<!-- 定義文件的大小,默認是2M -->
<param name="fileUpload.maximumSize">1229339</param>
<!-- 定義允許上傳的文件類型,如果文件類型定義多個,需要用逗號分開 -->
<param name="fileUpload.allowedTypes">application/pdf,application/vnd.ms-excel,application/vnd.ms-powerpoint</param>
<!-- 定義文件的擴展名,如果存在多個擴展名,用逗號分開 -->
<param name="fileUpload.allowedExtensions">.pdf,.ppt</param>
</interceptor-ref>
限制上傳文件大小,默認2M:
<constant name="struts.multipart.maxSize" value="5229339"></constant>
(5)實現國際化
* 在struts.xml文件添加,默認不加載struts.custom.i18n.resources屬性,fileupload表示src下的資源文件名稱
如果將資源文件放置到某個目錄下,需要在文件的添加相應的目錄
<constant name="struts.custom.i18n.resources" value="fileupload"></constant>
(6)在error.jsp中可以使用<s:fielderror></s:fielderror>,顯示對應的錯誤信息
在struts.xml文件中
<!--input: 如果該類中上傳文件失敗,可跳轉到/upload/error.jsp -->
<result name="input">/upload/error.jsp</result>
(7)常見的文件類型
文件類型:
excel:application/vnd.ms-excel
word:application/msword
ppt:application/vnd.ms-powerpoint
txt:text/plain
pdf:application/pdf
2、多文件上傳
1、上傳的文件用數組進行表示:
//上傳文件名稱:<input type="file" name="uploadImages">
//對應表單中的屬性,文件以流的形式傳遞,獲取文件
private File[] uploadImages;
//獲取上傳文件的類型,格式表單中屬性的名稱+ContentType,本例uploadImages+ContentType
private String [] uploadImagesContentType;
//獲取上傳文件的名稱,格式表單中屬性的名稱+FileName,本例uploadImages+FileName
private String [] uploadImagesFileName;
2、實現:
public String saveFiles(){
System.out.println("歡迎進入UploadAction...");
//處理文件上傳
//需求:將文件上傳到WebRoot下upload文件,首先找到file的目錄
ServletContext sc = ServletActionContext.getServletContext();
String path = sc.getRealPath("/file");
for(int i=0;uploadImagesContentType!=null && i<uploadImagesContentType.length;i++){
File file = new File(path,uploadImagesFileName[i]);
try {
//將一個文件拷貝到另一個文件中
FileUtils.copyFile(uploadImages[i], file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return "success";
}
自定義攔截器
1、攔截器:struts2的攔截器分2大類,一類是xwork包下,一類是struts2的包下,無論使用哪個攔截器,都必須實現Interceptor接口
struts2的攔截器屬於單實例
2、自定義攔截器(判斷用戶是否登錄,即從session中獲取相應的用戶信息)
實現ActionInvocation接口
package cn.itcast.web.g_aop;
import java.util.Map;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
@SuppressWarnings("serial")
public class PersonInterceptor implements Interceptor {
public PersonInterceptor(){
System.out.println("PersonInterceptor構造方法....");
}
public void init() {
System.out.println("PersonInterceptor的init方法....");
}
public String intercept(ActionInvocation invocation) throws Exception {//利用invocation可以得到很多數據
System.out.println("action="+invocation.getAction());
System.out.println("actionName="+invocation.getProxy().getActionName());
System.out.println("namespace="+invocation.getProxy().getNamespace());
System.out.println("method="+invocation.getProxy().getMethod());
//判斷session中是否存在用戶信息
//獲取session對象
Map<String, Object> mapSession = invocation.getInvocationContext().getSession();
String user = (String) mapSession.get("user");
if(user==null){
return "error";
}
// invocation.invoke():表示執行調用UserAction中save()方法,返回值String就表示save方法返回值
String result = invocation.invoke();
return result;
}
public void destroy() {
System.out.println("PersonInterceptor的destroy方法....");
}
}
3、需要在struts.xml文件添加和配置自定義攔截器在struts.xml或者相應的action的struts.xml配置中的package中添加配置自定義攔截器,對相應的action起作用
<!-- 自定義攔截器 -->
<interceptors>
<interceptor name="person" class="cn.itcast.web.g_aop.PersonInterceptor"></interceptor>
<interceptor-stack name="personStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<!-- 將自定義的攔截器放置到默認棧的後面 -->
<interceptor-ref name="person"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 默認執行的攔截器,即自定義的攔截器 -->
<default-interceptor-ref name="personStack"></default-interceptor-ref>
struts表單驗證
表單驗證:1、手工驗證
(1)要想實現對ValidateAction類中的方法進行校驗,必須要是繼承ActionSupport,因爲ActionSupport類中實現了Validateable接口
接口Validateable中有validate方法,用於對錶單進行驗證
/**
* 針對ValidateAction中的某一方法進行校驗,不希望所有的方法進行校驗
* 只需要將ValidateAction的中的方法名放置到validate方法的後面,並且方法的首字母要大寫
* 只對ValidateAction類中的login方法進行校驗
* */
public void validateLogin(){
System.out.println("進入登錄校驗的方法validate");
if(this.username==null || "".equals(username)){
this.addFieldError("username", "用戶名不能爲空");
}
if(this.psw==null || "".equals(psw)){
this.addFieldError("psw", "密碼不能爲空");
}
else{
//驗證密碼在6到12之間,定義正則表達式
String exg = "^[A-Za-z0-9]{6,12}$";
//編譯正則表達式
Pattern pattern = Pattern.compile(exg);
//與密碼進行匹配
Matcher matcher = pattern.matcher(this.psw);
//如果匹配不成功,說明密碼輸入有誤
if(!matcher.matches()){
this.addFieldError("psw", "輸入的密碼格式不正確(要求6到12之間)");
}
}
}
(2)在進行表單驗證的時候,如果出現異常,需要將錯誤的信息添加
this.addFieldError("username", "輸入的密碼格式不正確(要求6到12之間)");
最後struts會判斷錯誤集合中是否有值,如果有值,會通過struts.xml文件的配置
<result name="input">/validate/login.jsp</result>
指定到登錄頁面。
要想將錯誤信息顯示到登錄頁面,需要在登錄頁面添加<s:fielderror/>2、xml文件驗證
(1)在cn.itcast.web.h_validate中建立xml格式文件的配置文件
xml格式:
* ValidateAction中的所有方法
ActionClassName-validation.xml 其中ActionClassName指定的是Action類的名稱
本例:ValidateXmlAction-validation.xml
* ValidateAction中的指定方法
ActionClassName-ActionName-validation.xml,其中ActionClassName指定的是Action類的名稱
其中ActionName,提交表單的action的路徑的名稱
本例:ValidateXmlAction-validateXmlAction_login-validation.xml
創建xml的驗證文件時,需要添加規範
* 規範在xwork-core-2.1.6.jar中xwork-validator-1.0.3.dtd
* xml文件配置代碼:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.3//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<!-- 使用XML文件對指定Action類做校驗 -->
<validators>
<!-- 指定校驗的字段名稱,對應表單中name的屬性值 -->
<field name="username">
<!-- 針對某一字段的驗證規則
struts2將驗證規則存放到xwork-2.x.jar中
com.opensymphony.xwork2.validator.validators下的default.xml文件
-->
<!-- 用戶名不能爲空 -->
<field-validator type="requiredstring">
<!-- 指定驗證規則中屬性名稱指定相應值 -->
<param name="trim">true</param>
<!-- 填寫提示的錯誤信息 -->
<message>用戶名不能爲空</message>
</field-validator>
</field>
<field name="psw">
<!-- 密碼不能爲空 -->
<field-validator type="requiredstring">
<param name="trim">true</param>
<message><![CDATA[密碼不能爲空]]></message>
</field-validator>
<!-- 密碼長度在6到12之間 -->
<field-validator type="regex">
<param name="expression">^[A-Za-z0-9]{6,12}$</param>
<message><![CDATA[密碼的長度不匹配(需要輸入6到12之間)]]></message>
</field-validator>
</field>
<!-- 驗證年齡不能小於0 -->
<field name="age">
<field-validator type="agevalidator">
<message><![CDATA[年齡不能小於0]]></message>
</field-validator>
</field>
</validators>
在該文件中<field-validator type="requiredstring">,其中type爲字段指定校驗規則
struts2中的校驗規則xwork-core-2.1.6.jar中,com.opensymphony.xword2.validator.validators中的default.xml文件
(2)自定義校驗規則(驗證年齡不能小於0)
建立AgeValidator文件,定義校驗規則,必須實現Validator接口
或者繼承ValidatorSupport 和 FieldValidatorSupport
加載驗證規則
在src的目錄下創建validators.xml,配置如下
<validators>
<!-- name:爲自定義的校驗規則指定名稱,
與ValidateXmlAction-validateXmlAction_login-validation.xml文件中校驗規則type的值對應
class:校驗規則的類路徑
-->
<validator name="agevalidator" class="cn.itcast.web.h_validate.AgeValidator"></validator>
</validators>
如果不想在src目錄下創建validators.xml,就需要在struts2的校驗規則下進行修改
路徑如下:struts2中的校驗規則xwork-core-2.1.6.jar中,com.opensymphony.xword2.validator.validators中的default.xml文件
(3)一些校驗器例子
required 必填校驗器
<field-validatortype="required">
<message>性別不能爲空!</message>
</field-validator>
requiredstring 必填字符串校驗器
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用戶名不能爲空!</message>
</field-validator>
stringlength:字符串長度校驗器
<field-validator type="stringlength">
<paramname="maxLength">10</param>
<paramname="minLength">2</param>
<paramname="trim">true</param>
<message><![CDATA[產品名稱應在2-10個字符之間]]></message>
</field-validator>
int:整數校驗器
<field-validator type="int">
<paramname="min">1</param>
<paramname="max">150</param>
<message>年齡必須在1-150之間</message>
</field-validator>
字段OGNL表達式校驗器
<field name="imagefile">
<field-validatortype="fieldexpression">
<paramname="expression"><![CDATA[imagefile.length()<= 0]]></param>
<message>文件不能爲空</message>
</field-validator>
</field>
email:郵件地址校驗器
<field-validatortype="email">
<message>電子郵件地址無效</message>
</field-validator>
regex:正則表達式校驗器
<field-validatortype="regex">
<paramname="expression"><![CDATA[^13\d{9}$]]></param>
<message>手機號格式不正確!</message>
</field-validator>