1.struts.xml文件中的<constantname="struts.devMode">中的value改為true,那么以后修改了struts.xml文件的話,它會自動地更新加載,不需要每次修改完都去重啟服務器。
2.strurs2的核心控制器是一個Filter,而不是一個servlet,那么在web,xml文件中就需要配置FilterDispather,如
<filter>
<!–配置STRUTS2核心Filter的名字–>
<filter-name>struts</filter-name>
<!–配置STRUTS2核心Filter的名字–>
<filter-class>org.apache.struts2.dispatcher.FilterDispacher</filter-class>
</filter>
<!–置該Filter攔截URL–>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.struts2的運行原理:當在客戶端瀏覽器中輸入url地址的話,它的請求通過http協議發送到服務器端(tomcat),tomcat接受到請求之后,判斷是哪一個應用程序並找到對應的應用程序,接着會讀取相應的web.xml文件中的配置,根據url的輸入找到相應類型的<url-pattern>並被它所對應的<filter-class>接受,通過dofilter來看你所輸入的namespace(也就是你所訪問的路徑),它會從struts2.xml文件中查找所對應的namespace,查找之后,再去看是否有對應的同名的action,如有,再去找次action所對應的result,內部是通過forward方式到result所對應的頁面的。
4.namespace和我們所訪問的路徑一一對應,struts2的作用將請求和視圖相互分開,更加靈活,
struts.xml文件中的package是用來解決action重名的情況,在action中的result的默認name是success,可以不寫,只要在java類中包含返回值為string類型的excute方法,就可以被struts2當作一個action解決,默認情況下action執行的是excute方法。
5.自定義action有3種方式:
1.返回類型為string的excute方法,當讀到action是一個帶有class時,會去找class對應的對象(每次訪問都會new一個新的action),並調用此對應的excute方法,根據excute方法的返回值結果找到對應的jsp頁面
默認action是沒有class的,它底層默認執行的是ActionSuport對象中的excute方法,並默認返回success
2.實現Action接口,並重寫excute方法
3.繼承ActionSupprt,並重寫excute方法
在實際開發中,會使用第三種方法,因為ActionSupport本身就已經封裝了很多方法,可以直接調用此那些方法。
6.struts2和struts1的區別
struts1在訪問時,都只有一個action,這樣做會有線程安全問題,struts2在每次訪問一個action時,會new一個新的action對象(那樣就沒有線程安全問題)
7.在action中指定method方法,就可以調用該類所對應的方法了,只要這個方法是string類型的,默認是調用excute方法,也可以使用動態調用的方式DMI,如:在struts.xml文件中的action<action name="use" class="..."><result>/used.jsp</result>,而在url中是:http://localhost:8080/myweb/user/use!add。它表示調用名為use的action中所對應class中的add方法
說明:action執行的時,並不一定要執行excute方法,可以在配置文件中的action 中的method來指定要執行的哪個方法,也可以在url地址中用!方式來動態的指定,之所以不推薦使用method方式,因為會產生很多的action
8.在action中指定的method方法就可以調用該類對應的方法了,只要這個方法是string類型的,默認是調用excute方法(這種方式不推薦使用)
可以使用動態方法調用(DMI)如在struts.xml文件中的action中<action name="use" class=".."><result>/user.jsp</result></action>而在url中是:http://localhost:8080/myweb/user/use!add它表示的就是調用名為uszxce的action中所對應的class中的add方法
說明:action執行的時並不一定要執行excute方法,可以在配置文件中的action是用method=來指定需要調用的方法(不推薦),也可以在url地址中用!來動態指定(DMI),之所以不推薦使用method的方式,因為會產生太多的action。
9.通配符,使用通配符將配置降到最低,不過一定要遵守‘約定大約配置’如:struts.xml文件中<action name='student*' class="..." method="{1}"><result>/studet{1}_success.jsp</result> .
在地址欄中url:http://localhost:8080/myweb/actions/studetadd。
說明:method="{1}"表示的是前面所有通配符中的第一個*,name=“stydent”根據請求的url得到* 對應的是add,所以method={1}表示的是調用所對應的class中所對應的add方法,同理<result>/student{1}_success.jsp</result>就會調用studentadd_success.jsp文件* 是對應你所依賴的url進行配對的。
在一個含有通配符(*)的action中,當一個請求到來,它先找到與之完全匹配的action中的name,如沒有就找到最精確匹配的而且誰在前找誰。
10.struts2中接受參數的幾種方式
(1)通過action屬性獲得,當url中有參數傳遞時如http://localhost:8080/myweb/use!add?name=2&age=2,怎么樣獲取這些參數呢?
自定義action,在成員變量里設置對應的參數如name,age,並設置相應的set,get方法,那么struts2會自動地將url中的參數值傳遞到對應的成員變量中去 (底層struts2會自動地將url中的參數值傳遞到對應的成員方法上,會通過set方式)
(2)通過DomainModel預對象模型進行獲得,自定義一個action在成員里面設置一個user的對象,里面有name,age屬性和所對應的set,get方法,當在地址上輸入ul:http://localhost:8080/localhost/user/use!add?user.name=1&user.age=2,struts2會先通過setuser,再通過setName和setAge進行設值,這樣的話就會獲得user對象的值了。
11.struts2在進行中文設置的時候,需要在struts.xml文件中constant的name='struts.i18n.encoding value=gbk'就可以了。
12.簡單數據交驗,使用addFieldError方法和s:fieldError標簽可以進行簡單數據效驗如:在一個form中定義一個文本框,名為name(這個是在jsp頁面中),而在所對應處理請求的action中定義一個一樣的屬性name,如if (name=null || name.equals ""){this.addFieldError("name" ,"name is error"); return ERROR;},而在另外一個jsp文件里取得是通過<s:fielderror fieldName="name"/>這樣會在頁面上顯示name is error文字信息,也可以通過<s:property value="error.name[0]"/>也可以同樣顯示這樣的信息,可以在jsp頁面中用<s:debug></s:debug>標簽將所有的actionContext的值和所有的value stack context可以直接通過<s:property>的name取得,說明:s為struts2的標簽,需要在jsp文件中引入標簽庫才可以使用。
13.取得request,session,application的方式有2種,總體是取得map類型的request,session,application,真實類型的HttpServletRequest,HttpSession,servletContext的引用。
(1)依賴於容器,在表單提交的時候,到了后台的action中並定義了map類型的request,session,application即:Map request,session,application=(Map) ActionContext.getContext.get("request");然后再通過方法對這三個屬性進行設置(即設置他們的map類型的值)在前台jsp中可以通過request.getAttribute("key")取得相應的值,或是通過<s:property>取值
(2)是IOC(控制反轉)它要實現RequestAware,SessionAware,ApplicationAware接口,並重寫setRequest,setsession,setApplication的方法,而此時定義的request等仍為反形即 Map<String,Object>request 等而在jsp頁面中取得的方式同上面一樣(這種方式最常用)
14.模塊包含,在struts.xml文件中使用include可以把另外一個xml文件包含近來,相當於復制,好處就是將模塊進行分離,相互獨立。
默認action<default-action-ref>當別人訪問這個namespace時,若找不到對應的action,那么就會默認的用<default-action-ref name="abc">中指定的action的name去訪問(這里就會去訪問name所對應的action)
15.result類型,包含:dispachter,redirect,chain,redireAction,freemaker,httpheader,stream,velority,xslt,plaintext,toles,其中stream用於下載。
(1)result的type的默認類型是type="dispatcher"這個相當於用於jsp中的forward,用於服務器的跳轉到結果頁面去(不能挑磚到action中去)用dispather地址欄中顯示的是action的name。
(2)redirect是從客戶端重定向的跳轉,這相當於jsp中的redirect,地址欄中顯示的是要訪問的那個jsp頁面(不可以挑磚到另外一個action中去)
(3)chain可以調轉到另外一個action中去,這種是服務器的方式,
redirectAction是用於客戶端跳轉到另外一個action中去,httpHeader就是一個發送http頭消息的。
16.global-results的全局結果機指的是在struts.xml文件中package里面可以共享的結果集如:<global-results><reslut name="mainpage">/main.jsp</result></global-results>表示的是當返回的值就mainpage時,就會挑磚到這個頁面
(2)一個包若想使用另外一個package中的內容,要使用<package>中的extends來繼承另外一個包,這樣就可以使用另外一個包的global了,如<package name="user"><globa-reslut></result name="asd">,若另外一個包象使用這個包的中的global-result可以通過<package name="abv" extends ="user">這樣就可以使用那個package了。
17.一次請求只有一個值棧,所以服務器的forward過程中幾個action共同使用同一個value stack的值,可以直接訪問,當通過redirect或兩次請求之間傳遞參數的時候,可以通過帶參數的結果基進行訪問,因為redirect或兩次請求不是共同用同一個value stack,但是可以從ActionContext中獲取值,從其獲取的值的時候前面要加上#,如:<s:property value="#parameters">.
18.ognl表達式 :obgect graph naivgation language。指的是操作標簽中value里面的表達式,在domain中可以自己new一個對象這個前提是有對應的set/get方法,這樣的話就可以使用OGNL表達式了。
(1).訪問value stack中的action的普通屬性<s:property value="name" />
(2).訪問值占中對象的普通屬性 <s: property value="use.age" />這個需要有對應的set/get方法
(3).訪問值占中的普通方法<... value="password.length()">,<s:property value="use.method()">
(4)訪問值占中action的普通方法<... value="Hello()">
(5).訪問值占中的靜態方法<s:property value="@com.wt.work@add">表示的是要訪問work類中的add方法
(6).訪問靜態屬性 <s:property value="@com.wt.work@STR">表示要訪問work中的STR屬性
(7).訪問Math類中的靜態方法<s:property value="@@MAX(1,5)">
(8)訪問普通類的構造函數<s:property value="new com.wt.work.user(99)">表示要訪問user類中帶參數的構造函數
(9).訪問list,map,set等集合都可以
(10).投影(過濾)只有3個:?#,^#,$#如 :<s:property value="user.{?#this.name=1}.{age}">表示name=1時候的那個對象的age。
(11).<s:property value="user.{^#this.age>1}.{age}">表示age>1對象中的前一個。
(12).<s:property value="user.{$#this.age>1}.{age}">表示age>1對象中的后一個。
(13).[]:<s:property value="{0}">表示從ognl的 value stack中從上往下第0個位置開始一直到站底的集合。
19.<s:bean>標簽在沒有設置var時,對象被放置到value stack的占頂中,當bean標簽結束時,就從占頂取走。<s:bean>標簽如果 設置了var時,對象就會放到ActionContext中去。
20.struts2通用標簽:property,set,bean,include,param,debug.其中set標簽默認為action訪問,會將值放入到request和ActionContext中,它的范圍是:page,request,session,application.控制標簽:if ,elseif,else,iterator,subset.
21.在數據庫中一般建議使用preparedStatement而不直接使用statement是因為preparedStatement的效率高,在一次編譯之后就可以直接從緩沖中獲取了,第二是因為可以防止sql注入,安全性好。
22.struts2的聲明式異常,(1)當將異常定義在具體某個action時,那么可以在<action>里面定義<exception-mapping result="error" exception="java.sql.exception">那么當在servlet層出現sql異常它就會拋給對應的action,然后再由action查到struts.xml文件中,找到對應的action,再調用對應的頁面顯示。
(2)對於大多數異常的處理方式:<global-results>和<global-exception-mapping>如:<global-results><result name="error">/error.jsp</result></global-results><global-exception-mapping><exception-mapping result="error" exception="java.lang.Exception"></global-exception-mapping>
注意,<global-exception-mapping>要在<global-results>之后。
在action中進行異常隱射時就想上面的1,在package中進行全局異常映射如上面的2,使用繼承同用異常映射。
22.I18N(國際化)的原理:通過一個ResourceBundle類的getBundle方法中,指定你的資源名的前綴如:app同時指定需要加載的資源文件,如有兩個資源文件:app_zh_CN.properties和app_en_us.properties,那么再ResourceBundle中 ResourceBundle res=ResoueceBundle.getBundle("app",Locale.US),那么它會自動的加載app_en_us.properties文件,當加載zh_cn的時會出現亂碼,那么可以通過native2aseii在dos下將中文轉為ascii就可以實現了。
23.i18n有3個級別:Action,package,application
(1)在Action中,哪個資源文件的前綴名要與Action中的類名一樣,它表示的應用范圍就是這個Action,要和Action放在一個目錄下面
(2)在package時,哪個資源文件的前綴名要與package名要一致,表示應用范圍在這個包中所有的文件
(3)在Application整個應用程序中,必須將資源文件放在src目錄下面,這個前綴名沒有要求,在struts.xml文件中 constant 中name="struts.constant.i18n.resources" value="是你的前綴名"
24.i18n要傳遞參數時,先在properties文件中用{0}占位符。如welecome=w{0},然后在前端頁面中用<s:text name="welecome"><s:param name="1個ognl'表達式">這里是字符串</s:param></s:text>.
動態語言切換i18n,如果轉換為英語就是在URL地址欄中加上?resquest_locale=en_us即可,中文也是一樣。
25.攔截器:一個請求到來時,先在filter中操作一個action,它先操作攔截器,然后再讓攔截器去操作action,再返回給攔截器,然后攔截器再返回給filter,再請求中默認都進行了一系列的攔截操作。
自定義攔截器:實現iterceptor接口,並重寫itercept方法,同時在struts.xml文件中定義<interceptor><interceptor name="my" class="..."></...>在action中用<interceptor-ref name="my">同時還要用默認的<interceptor-ref name="defaultStack">
26.token攔截器防止重復提交,在要提交的form表單頁面中,定義<s:token>標簽,同時在struts.xml文件中定義action可以防止在對應的action中進行重復提交如:<interceptor-ref name="defaultStack"></interceptor-ref><interceptor-ref name="token" /><reslut name="invalid.token">/error.jsp</reslut>
那么在重復提交會到error.jsp文件。
27.token為什么可以防止重復提交。當訪問頁面時,首先在服務器端session里面生成一個隨機數,然后再將這個隨機數寫入到form里面,當再次提交的時,隨機數就會帶到服務器中與之前的session中的值是否一樣,當提交之后服務器就會將session中的那個隨機數清除,當再提交的時候服務器發現session中沒有那個值,就不容許 重復提交了。
28.自定義類型轉換器。當你想在前台或url通過輸入參數在后台可以接受到的話,當不是基本數據類型時,可以自定義一個類繼承DefaultTypeCoverter並重寫convertvalue方法,同時還要通過注冊的方式來告訴struts2去用你自定義的類型轉換器,有兩種注冊方式
(1)局部的是要操作的action在一個目錄下且名字必須要與Action名一樣:XXXAction-Conversion.properties
(2)全局注冊,是放入 src目錄下面,且名字為XXwork-Conversion.properties,且在properties文件中寫如:p=com.wt.myTypeConveter.
也可用自定義一個類繼承strutsTypeConverter進行類型轉換。