2008年10月22日 星期三

Struts2 -10/22 學習進度 Chapter 3 part2

Request and Form data


在針對取值的處理部份,action也許會需要透過request String 來取值
就像是在form data 中取得一樣。
Struts2採用了javaBeans的方式,透過getter/setter存取,以下例來看:
"/home.action?framework=struts&version=2"
如果要存取這樣的url,則action必須能提供setters for framework & version。
然而並不是所有的setter都需要設定為String type ,在struts2中具有自動轉型的功能,但只針對
primitive tpye / basic object types / can be configured for customized class。
另外Struts2也可以有自動針對object的method call自動進行追蹤!
eX: 有一個 form裡面的其中一個元素名稱叫做: person.address.home.postcode
則Struts2會自動呼叫 getPerson().getAddress().getHome.setPostcode(2).




Accessing Business Services


為了降低耦合度,Struts2使用了DI(Dependency Injection)或者IOC(Inversion of Control)。
DI的實作部份可以透過Constructor Injection、Interface Injection、Setter Injection。
不過在struts2上,是採用了setter Injection,也就是說當你如果要讓action去存取某個object,就一定要針對該obj提供setter。使用di的最佳選擇是Spring Framework,以plugin方式達成,當然也可以選其它的像是 Plexus,或者是自己實作。

*****不過要特別注意一下,在這裡使用到的是Spring Core , not Spring MVC !!*****

也有一些objects 是不在spring framework上管理的,像是HttpServletRequest,這是透過setter injection與interface injection組合來管理的。

***** 小故事 *****
最早在WebWork中使用的DI是自己開發的,但是在webwork 2.2版之後就被拿掉,改用spring framework,最大的原因是原先的di 是透過 interface injection,這樣麻煩的是需要將每個component都要進行實作,而使用setter injection的好處則是純pojo,只要透過setter處理就可以讓spring framework作 DI。
除此之外,在原先的方式,每個component都有一個Aware介面,那是為了提供setter給該元件使用的,如果interface是 UserDao,則這個 aware interface就會是 UserDaoAware (自動轉譯),並且會提供一個method void setUserDao(UserDao dao);
***** /小故事 *****

Accessing Data from the Action
比較常見的方式是存取 HttpServletRequest or HttpSession,不過這些已經可以被包進 Aware interface (letting the di to do its work),然後就直接設定objs去存取所需要的required name。
如果需要透過tag libs orJSTL去存取data是比較輕鬆的,而這些都可以直接在action中透過Value Stack來做。

Interceptors
在Struts2中,多數的功能都有實作interceptors,像是例外處理、檔案上傳,lifecycle callbacks以及 validation。
Interceptors就像是Servlet filters 或 JDKs的 Proxy class,主要是提供了 pre-processing以及 post-processing around the action。
以下是三種使用到的interceptors
1. SpringFramework - ActionAutowiringInterceptor interceptor.
2. Request String and Form Values - ParametersInteceptor.
3. Servlet-Based objects - ServletConfigInterceptor.
上述的前兩個interceptor是獨立運作的,不跟其他的東西有所關聯,但第三個則會與以下的interface一起運作。
3.1 Sessionaware - to provide access to all the session attributes via a Map
3.2 ServletRequestAware - to provide access to all the request attributes via a Map
3.3 RequestAware – to provide access to all the request attributes via a Map
3.4 ApplicationAware – to provide access to all the application attributes via a Map
3.5 ServletResponseAware – to provide access to the HttpServletResponse object
3.6 ParameterAware – to provide access to all the request string and form
values attributes via a Map
3.7 PrincipalAware -to provide access to the PrincipleProxy object;
this object implements the principle and role methods of the
HttpServletRequest object in implementation, but by providing a proxy,
allows for implementation independence in the action
3.8 ServletContextAware – to provide access to the ServletContext object
使用interceptor的xml範例
<interceptors>

<interceptor name="autowiring"
class="interceptor.ActionAutowiringInterceptor"/>
</interceptors>
接著把所要使用的action作設定-要放在package tag底下
<action name="my" class="com.fdar.infoq.MyAction" >
<result>view.jsp</result>
<interceptor-ref name="autowiring"/>
</action>
另外也提供了 interceptor stacks的管理方式,設定是在struts-default.xml
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
This configuration node is placed under the
node. Each tag references either an
interceptor or an interceptor stack that has been configured
before the current interceptor stack.
使用了stack的話,在action的修改設定如下
<action name="my" class="com.fdar.infoq.MyAction">
<result>view.jsp</result>
<interceptor-ref name="basicStack" />
.......


Implementing Interceptors
透過自訂的interceptor可以相當優雅的(elegant)切開你的ap,專注於buz上的code就好
實作方式很簡單,相關的實際運作則交給背後的XWork Framework。
public interface Interceptor extends Serializable{
void destory();
void init();
String intercept(ActionInvocation invocation)throws Exception;
}

事實上,Struts2也提供了一個AbstractInterceptor class讓你繼承。
ActionInvocation obj 是提供存取 runtime environment的關鍵元件!
It allows access to the action itself;
the context (which for a web application includes the request parameters,
session parameters, the users locale, etc.);
the result of the actions execution; and methods to invoke the action and
determine whether the action has already been invoked.

Value Stack / OGNL
==================
OGNL : Object Graph Navigational Language
The value stack consists of the following objects in the provided order:
1. Temporary Objects – during execution temporary objects are created
and placed onto the value stack; an example of this would be the
current iteration value for a collection being looped over in a JSP tag
2. The Model Object – if model objects are being used, the current model object
is placed before the action on the value stack
3. The Action Object – the action being executed
4. Named Objects – these objects include #application,
#session, #request, #attr and #parameters and refer
to the corresponding servlet scopes
---> Page 38

沒有留言: