輕量級JavaEE企業應用實戰(九)

Struts2介紹

1.下載Struts2
2.將Struts2的lib下的 common-fileupload.jar 、commons-io.jar、freemarker.jar、javassist.ga.jar、ognl.jar、struts2-core.jar和xwork-core.jar加入到應用的WEB-INF\lib路徑下(上述jar包省略版本)
3.編輯WEB應用的web.xml文件,配置Struts2的核心Filter

//定義Struts2的核心Filter
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>
        org.apache.struts2.dispatcher.FilterDispatcher
    </filter-class>
</filter>
//讓Struts2的核心Filter攔截所有請求
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Struts2的常量配置

除了使用struts.xml管理配置之外,還可以使用struts.properties文件來管理常量,該文件定義了Struts2的大量常量,可以通過改變這些常量來滿足應用的需求
常用常量配置:

struts.configuration //指定配置文件的配置管理器,默認的是org.apache.struts2.config.DefaultConfiguration
struts.locale //web應用默認的Locale,默認是en_US
struts.i18n.encoding //指定web應用的默認編碼集,該常量對處理中文請求參數十分有效,對於使用中文參數,應設置爲GBK禍GB2312
...

Struts2回默認加載類加載路徑下的
struts.xml //開發者定義的默認配置文件
struts-default.xml //Struts 2框架自帶的配置文件
struts-plugin.xml //Struts 2插件默認配置文件
所以,在這幾種配置文件中都可以進行常量的配置

此外,還可以通過web應用的web.xml來加載Struts2常量

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>
        org.apache.struts2.dispatcher.FilterDispatcher
    </filter-class>
    <init-param>
        <param-name>struts.custom.i18n.resources</param-name>
        <param-value>mess</param-value>
    </init-param>
</filter>

通常Struts2按如下順序加載Struts常量:
struts-default.xml //在struts2-core-2.1.2.jar中
struts-plugin.xml //在struts2-Xxx-2.1.2.jar等Struts2插件jar中
struts.xml //web應用默認struts配置文件
struts.properties //struts2默認配置文件
web.xml //web應用配置文件

包含其他配置文件

<include file="struts-xxx.xml" /> //模塊化方式管理配置文件

Action實現

爲了用戶開發Action更加規範,Struts2提供了一個藉口Action,黎明定義了一些結果字符串以及execute,ActionSupport繼承了這個藉口,這就是execute方法爲何是Action中默認處理用戶請求的方法的原因

public interface Action {
    public static final String ERROR = "error";
    ...
    public String execute() throws Exception;
}

public class ActionSupport implements Action, Validateable,ValidationAware,TextProvider,LocaleProvider,Serializable {
    ...
}

Action訪問Servlet API

Struts2提供了一個ActionContext類來訪問,Servlet API
原因:
該類中引入了servlet中的ServletContext、PageContext、HttpServletRequest、HttpServletResponse作爲方法中的參數
最終實現在ServletActionContext中

儘管可以通過ActionContext訪問Servlet,畢竟不是直接獲取Servlet API,所以Struts2又提供了幾個接口直接訪問Servlet API:
ServletContextAware //直接訪問web應用的ServletContext實例
ServletRequestAware //直接訪問用戶請求的HttpServletRequest實例
ServletResponseAware //直接訪問服務器相應的HttpServletResponse實例
注:
上述幾個接口都需要用戶的Action中對其方法進行重寫,其參數爲servletContext、request、response,相當於對servlet進行了封裝

servletActionContext訪問Servlet API

方法:
static PageContext getPageContext();
static HttpServletRequest getRequest();
static HttpServletResponse getResponse();
static ServletContext getServletContext();

servletActionContextActionContext的實質,實際上都是一樣的,下邊來看內部實現:

servletActionContext中的幾個方法,以pageContext爲例
public static PageContext getPageContext() {
    return (PageContext)ActionContext.getContext().get(PAGE_CONTEXT);
}

接下來看ActionContext

static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();

public static getContext() {
    return actionContext.get();
}

解析:
ActionContextThreadLocal是實現ThreadLocal的一個內部類.ThreadLocal可以命名爲”線程局部變量”,它爲每一個使用該變量的線程都提供一個變量值的副本,使每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本衝突.這樣,我們ActionContext裏的屬性只會在對應的當前請求線程中可見,從而保證它是線程安全的.

servletContext和ActionContext聯繫
兩者中有着一些重複的功能,在我們的Action中,該如何去抉擇呢?
我們遵循的原則是:如果ActionContext能夠實現我們的功能,那最好就不要使用ServletActionContext,讓我們的Action儘量不要直接去訪問Servlet的相關對象

注意:在使用ActionContext時有一點要注意: 不要在Action的構造函數裏使用ActionContext.getContext(),因爲這個時候ActionContext裏的一些值也許沒有設置,這時通過ActionContext取得的值也許是null;同樣,HttpServletRequest req = ServletActionContext.getRequest()也不要放在構造函數中,也不要直接將req作爲類變量給其賦值。至於原因,我想是因爲前面講到的static ThreadLocal actionContext = new ActionContextThreadLocal(),從這裏我們可以看出ActionContext是線程安全的,而ServletActionContext繼承自ActionContext,所以ServletActionContext也線程安全,線程安全要求每個線程都獨立進行,所以req的創建也要求獨立進行,所以ServletActionContext.getRequest()這句話不要放在構造函數中,也不要直接放在類中,而應該放在每個具體的方法體中(eg:login()、queryAll()、insert()等),這樣才能保證每次產生對象時獨立的建立了一個req

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章