Struts2框架_result結(jié)果集&Servlet的API獲取&參數(shù)封裝

一女器、 rusult標(biāo)簽結(jié)果集配置

全局結(jié)果

<!-- 全局result設(shè)置-->
<global-results>
    <!-- 不寫name屬性,默認(rèn)success -->
    <result>/a_result/result.jsp</result>
</global-results> 

作用是為package中配置的所有action提供全局的返回結(jié)果頁面

局部結(jié)果

<action name="result_*" class="com.itdream.struts2.test.Struts2_Result" method="{1}">
    <!-- 默認(rèn)是SUCESS -->
    <result>/a_result/result.jsp</result>       
</action>

寫在action標(biāo)簽內(nèi),作用是為當(dāng)前action配置結(jié)果頁面

結(jié)果類型【掌握前四種】

1. dispatcher 轉(zhuǎn)發(fā)頁面
dispathcer轉(zhuǎn)發(fā)到頁面促王。不寫type默認(rèn)值就是dispatcher轉(zhuǎn)發(fā)

<result name="resultTypejsp" type="dispatcher">/b_resultType/resultType.jsp</result>
2. chain 轉(zhuǎn)發(fā)Action
chain是轉(zhuǎn)發(fā)到Action動(dòng)作類,result標(biāo)簽內(nèi)填寫要轉(zhuǎn)發(fā)到的action的name屬性,不能加.action的后綴

可以這樣理解,轉(zhuǎn)發(fā)相當(dāng)于在當(dāng)前struts.xml中找action的name,所以不需要加.action后綴

<result name="resultTypejsp" type="chain">resultType2</result>
3. redirect 重定向到頁面
重定向到頁面褐望。

<result name="resultTypejsp" type="redirect">/b_resultType/resultType.jsp</result>
4. redirectAction 轉(zhuǎn)發(fā)Action
重定向到Action動(dòng)作類中的action的內(nèi)容可以加.ation后綴名也可以不加

<result name="resultTypejsp" type="redirectAction">resultType2.action</result>

5. stream: 結(jié)果為文件流验庙。文件下載
<result name="success" type="stream">
    <param name="contentType">image/jpeg</param>
    <param name="inputName">imageStream</param>
    <param name="contentDisposition">attachment;filename="document.pdf"</param>
    <param name="bufferSize">1024</param>
</result>   

contentType:下載文件類型

inputName:對(duì)應(yīng)要輸出到客戶端流聲明的名稱

contentDisposition:下載到客戶端時(shí)熙兔,客戶端文件名稱

bufferSize:讀文件的緩存大小
6. json:轉(zhuǎn)發(fā)颁股。
<package name="xxx" namespace="/xxx" extends="json-default">
    <action name="json" method="xxx"
        class="org.itheima.struts.action.JsonAction">
        <result name="success" type="json">
            <param name="encoding">utf-8</param>
            <param name="root">jsonObject</param>
        </result>
    </action>   
</package>

由action轉(zhuǎn)發(fā)到j(luò)son結(jié)果

encoding:配置編碼格式

root:配置對(duì)象嫁审。action類中必須提供一個(gè)和root值相同的屬性名稱,且需要提供getter方法克锣。
7. jsonActionRedirect:重定向
<action name="xxx" method="xxx"
        class="org.itheima.struts.action.JsonAction">
        <result name="success" type="jsonActionRedirect">
            xxx.action
        </result>
</action>

由action重定向到j(luò)son結(jié)果。
8. 小結(jié)
dispatcher與chain屬于轉(zhuǎn)發(fā),redirect與redirectAction是重定向

這里的轉(zhuǎn)發(fā)和重定向的理解與Servlet中一樣腔长。
填寫的內(nèi)容.action也與Servlet中的理解差不多袭祟。

重定向相當(dāng)于頁面重新發(fā)送請(qǐng)求,因此后綴有.action(也可以沒有)
轉(zhuǎn)發(fā)不能有后綴.action

二、 Struts與Servlet交互對(duì)接的三種方式

客戶端與服務(wù)端交互時(shí)捞附,通常會(huì)帶參數(shù)過來巾乳,服務(wù)器也會(huì)回寫數(shù)據(jù)給客戶端您没。在此過程中,參與著請(qǐng)求胆绊,和響應(yīng)氨鹏,以及會(huì)話。servlet在此過程中提供了HttpServletRequest作為獲取請(qǐng)求數(shù)據(jù)的方案压状,HttpServletResponse作為響應(yīng)的方案仆抵,HttpSession負(fù)責(zé)了會(huì)話方案。Struts其實(shí)是基于servlet實(shí)現(xiàn)的web框架种冬,他需要遵循規(guī)則提供請(qǐng)求镣丑,響應(yīng)和會(huì)話的API供開發(fā)人員使用,因此Struts針對(duì)這一問題提供了自己的一套API封裝娱两,提供了多種方式的訪問莺匠。

1. 使用ActionContext對(duì)象間接使用Servlet的API

1.1 ActionContext對(duì)象實(shí)例獲取
ActionContext context = ActionContext.getContext();

ActionContext是綁定在當(dāng)前線程中的∈ぃ框架在請(qǐng)求線程開啟時(shí)趣竣,
將ActionContext實(shí)例對(duì)象就綁定上來了,因此我們可以通過靜態(tài)方法直接獲取旱物。
1.2 請(qǐng)求參數(shù)的獲得
Map<String, Object> parameters = context.getParamters();
相當(dāng)于Servlet中的request.getParamters()方法
1.3 存儲(chǔ)數(shù)據(jù)到域中
context.put(key, value)遥缕; 相當(dāng)于存儲(chǔ)數(shù)據(jù)到request域中
context.getSession().put(key,value); 相當(dāng)于存儲(chǔ)數(shù)據(jù)到Session域中
context.getApplication().put(key, value); 相當(dāng)于存儲(chǔ)數(shù)據(jù)到ServletContext作用域
1.4 表單提交測(cè)試
表單form.jsp :

    <form action="${pageContext.request.contextPath }/servlet1.action" method="post">
        用戶名<input type="text" name="username" /><br/>
        密碼<input type="password" name="password" /><br/>
        <input type="submit" value="提交" /><br/>
    </form>

----------------------------------------------------------------------------

struts.xml中action的配置 :

<action name="servlet1" class="com.itdream.struts2.test.Struts2_Servlet" method="servlet1">
    <result>/c_servlet/result.jsp</result>
</action>

----------------------------------------------------------------------------    

Action動(dòng)作類:

ActionContext context = ActionContext.getContext();
//獲取到傳遞過來的所有參數(shù)
Map<String, Object> parameters = context.getParameters();

for(String key : parameters.keySet()) {
    //通過獲取的key獲取到每一個(gè)對(duì)應(yīng)的String[]的值
    String[] values = (String[]) parameters.get(key);
    
    //存入request作用域
    context.put(key, values[0]);
}

//轉(zhuǎn)發(fā)到頁面顯示
return SUCCESS;

---------------------------------------------------------------------------

回顯頁面 : 

用戶名:${username }<br/>
密碼:${password }

2. 實(shí)現(xiàn)Struts2提供的相應(yīng)接口獲取相應(yīng)的實(shí)例

實(shí)現(xiàn)以下接口 ,提供聲明以及setter方法:
    ServletContextAware
    ServletRequestAware
    ServletResponseAware
    ParameterAware
    SessionAware
    ApplicationAware
    PrincipalAware  

例如:下面例子實(shí)現(xiàn)ServletRequestAware接口,成員位置聲明request,并提供setter方法异袄。

public class Struts2_Servlet2 extends ActionSupport implements ServletRequestAware {
    //聲明request引用
    private HttpServletRequest request;

    @Override
    //提供setter方法,Struts2框架檢測(cè)到我們實(shí)現(xiàn)了ServletRequestAware接口,會(huì)將與request對(duì)象作為參數(shù)傳遞進(jìn)來
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }
    
    // 間接方式使用Servlet的API
    public String servlet2() {
        //獲取參數(shù)
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println(username);
        System.out.println(password);
        //存入作用域
        request.setAttribute("username", username);
        request.setAttribute("password", password);
        //頁面跳轉(zhuǎn)
        return SUCCESS;
    }
}

3. 使用ServletActionContext直接獲取實(shí)例

Struts2還提供了ServletActionContext類提供了多個(gè)靜態(tài)方法通砍。

1. 獲得請(qǐng)求
    HttpServletRequest request = ServletActionContext.getRequest();

2. 獲得響應(yīng)
    HttpServletResponse response = ServletActionContext.getResponse();

-----------------------------------------------------------------------------

3. 獲得ServletContext對(duì)象
    ServletContext servletContext = ServletActionContext.getServletContext();

4. 獲得PageContext對(duì)象
    PageContext pageContext = ServletActionContext.getPageContext();

============================================================================

例如:

public String servlet2() {
    // 獲得request對(duì)象
    HttpServletRequest request = ServletActionContext.getRequest();

    // 獲取參數(shù)
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    // 存入作用域
    request.setAttribute("username", username);
    request.setAttribute("password", password);
    // 頁面跳轉(zhuǎn)
    return SUCCESS;
}

三、 Struts封裝參數(shù)的三種方式

1. 屬性驅(qū)動(dòng)(有兩種)

1.1 將Action作為javaBean類,提供屬性的setter方法
將Action動(dòng)作類作為一個(gè)JavaBean的類,提供與表單name屬性對(duì)應(yīng)的成員變量的聲明,Struts2在執(zhí)行到
param攔截器時(shí),會(huì)根據(jù)提供的setter方法將獲取到的參數(shù)一一封裝到對(duì)應(yīng)的字段中去烤蜕。

-----------------------------------------------------------------------------

例子:

form.jsp :

<form action="${pageContext.request.contextPath }/model1.action" method="post">
    用戶名<input type="text" name="username" /><br/>
    密碼<input type="password" name="password" /><br/>
    年齡<input type="text" name="age" /><br/>
    生日<input type="text" name="birthday" /><br/>
    <input type="submit" value="提交" /><br/>
</form>

struts.xml : 

    <action name="model1" class="com.itdream.model.test.Model1"></action>

Action動(dòng)作類:

/**
 * 屬性驅(qū)動(dòng):將Action動(dòng)作類作為一個(gè)javaBean類,提供屬性的setter方法,Struts2使用setter來封裝參數(shù)
 */
public class Model1 extends ActionSupport {

    private String username;
    private String password;
    private int age;
    private Date birthday;

    public void setAge(int age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String execute() throws Exception {

        // 我們提供了與參數(shù)name屬性相同的字段,Struts2在調(diào)用攔截器時(shí)就幫我們對(duì)數(shù)據(jù)進(jìn)行了封裝,但是必須提供setter方法
        // 因此我們直接使用封裝好了的參數(shù)了
        System.out.println(username);
        System.out.println(password);
        System.out.println(age);
        System.out.println(birthday);

        return NONE;
    }
}


這種驅(qū)動(dòng)方式的缺陷是如果傳入的數(shù)據(jù)很多的話,那么Action動(dòng)作類中需要定義的字段也會(huì)很多,同樣setter方法也會(huì)變的很多封孙。
這使得Action中的代碼變得很臃腫。

1.2 屬性驅(qū)動(dòng) : 對(duì)象驅(qū)動(dòng)
  • 在Action類中聲明一個(gè)JavaBean的實(shí)例對(duì)象,通過這個(gè)實(shí)例對(duì)象封裝傳遞過來的參數(shù)
  • 這種對(duì)象驅(qū)動(dòng)的前提是:創(chuàng)建這樣一個(gè)JavaBean并提供setter/getter方法
  • 在頁面?zhèn)髦档臅r(shí)候使用ognl表達(dá)式,即對(duì)象名.字段名

    例子:

    form.jsp : 表單提交的參數(shù)的name屬性必須使用 對(duì)象名.字段名的方式

    <form action="${pageContext.request.contextPath }/model2.action" method="post">
        用戶名<input type="text" name="user.username" /><br/>
        密碼<input type="password" name="user.password" /><br/>
        年齡<input type="text" name="user.age" /><br/>
        生日<input type="text" name="user.birthday" /><br/>
        <input type="submit" value="提交" /><br/>
    </form> 


    struts.xml :
    <action name="model2" class="com.itdream.model.test.Model2Action"></action>

    Action動(dòng)作類 : 

    public class Model2Action extends ActionSupport {
    
        //聲明JavaBean對(duì)象用于封裝
        private User user;
        
        //必須提供對(duì)象的getter方法,Struts2框架通過getter方法獲取到這個(gè)javaBean對(duì)象,
        //這個(gè)對(duì)象如果為null,Struts2會(huì)new一個(gè)對(duì)象通過setter方法放進(jìn)來,以便下一次參數(shù)的封裝
        public User getUser() {
            return user;
        }
        
        public void setUser(User user) {
            this.user = user;
        }
        
        
        @Override
        public String execute() throws Exception {
            
            System.out.println(user);
            
            return NONE;
        }
    }


    這種 屬性驅(qū)動(dòng)_對(duì)象驅(qū)動(dòng) 必須提供getter方法,如果沒有提供getter方法,Struts2框架底層就無法獲得該對(duì)象進(jìn)行封裝讽营。


2. 模型驅(qū)動(dòng)

Struts2中封裝參數(shù)還有一種方式:模型驅(qū)動(dòng)虎忌。

  • 實(shí)現(xiàn)ModelDriven接口封裝參數(shù)
  • 提供一個(gè)JavaBean的類,用于封裝
  • 必須在成員位置創(chuàng)建要封裝成的JavaBean的對(duì)象
  • 必須實(shí)現(xiàn)getModel方法,Struts2底層獲得該對(duì)象
    
    接收到請(qǐng)求,Struts2發(fā)現(xiàn)要跳轉(zhuǎn)的Action實(shí)現(xiàn)了ModelDriven接口,就會(huì)在modelDriven攔截器時(shí)執(zhí)行,
    在這個(gè)攔截器會(huì)獲取到提供的Model對(duì)象,進(jìn)行參數(shù)的封裝。這里要注意,我們必須手動(dòng)創(chuàng)建對(duì)象,Struts2
    的底層不會(huì)幫我們創(chuàng)建對(duì)象橱鹏。

    另外,如果modelDriven攔截器封裝了的參數(shù),在該攔截器后的params攔截器就不會(huì)再進(jìn)行封裝了,它只會(huì)
    封裝modelDriven未進(jìn)行封裝的參數(shù)膜蠢。
    因此,模型驅(qū)動(dòng)優(yōu)先于屬性驅(qū)動(dòng)莉兰。

    ----------------------------------------------------------------------------------
    
    例子:

    form.jsp :
 
    <form action="${pageContext.request.contextPath }/model3.action" method="post">
        用戶名<input type="text" name="username" /><br/>
        密碼<input type="password" name="password" /><br/>
        年齡<input type="text" name="age" /><br/>
        生日<input type="text" name="birthday" /><br/>
        <input type="submit" value="提交" /><br/>
    </form>

    -------------------------------------------------------------------------------

    struts.xml : 

    <action name="model3" class="com.itdream.model.test.Model3Action"></action>

    -------------------------------------------------------------------------------
    Action動(dòng)作類:
    

    /**
     * 模型驅(qū)動(dòng) : 前提: 提供一個(gè)JavaBean的模型類,以供封裝
     */
    public class Model3Action extends ActionSupport implements ModelDriven<User> {
    
        // 模型驅(qū)動(dòng):手動(dòng)構(gòu)建對(duì)象
        private User user = new User();
    
        @Override
        // Struts2獲取到這個(gè)對(duì)象模型,用于封裝
        public User getModel() {
            return user;
        }
        
        @Override
        public String execute() throws Exception {
            
            System.out.println(user);
            return NONE;
        }
    
    }

模型封裝,對(duì)于封裝單個(gè)對(duì)象是非常方便的,但是如果要封裝多個(gè)對(duì)象,還是需要使用屬性驅(qū)動(dòng)中的對(duì)象驅(qū)動(dòng)


3. 屬性驅(qū)動(dòng)-對(duì)象驅(qū)動(dòng)封裝對(duì)象到List集合中

與上面屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)一樣挑围。

1. 必須提供JavaBean的實(shí)體類用于封裝對(duì)象。
2. 頁面jsp傳參到Action動(dòng)作類使用OGNL表達(dá)式糖荒。
3. Action動(dòng)作類中聲明該對(duì)象,和模型驅(qū)動(dòng)不同,屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)可以不創(chuàng)建對(duì)象,框架會(huì)幫我們創(chuàng)建對(duì)象杉辙。
4. 必須提供get和set方法,以便Struts2的底層進(jìn)行封裝

form.jsp頁面OGNL表達(dá)式傳參:

<form action="${pageContext.request.contextPath }/model4.action" method="post">
    用戶名<input type="text" name="list[0].username" /><br/>
    密碼<input type="password" name="list[0].password" /><br/>
    年齡<input type="text" name="list[0].age" /><br/>
    生日<input type="text" name="list[0].birthday" /><br/>
    
    用戶名<input type="text" name="list[1].username" /><br/>
    密碼<input type="password" name="list[1].password" /><br/>
    年齡<input type="text" name="list[1].age" /><br/>
    生日<input type="text" name="list[1].birthday" /><br/>
    
    用戶名<input type="text" name="list[2].username" /><br/>
    密碼<input type="password" name="list[2].password" /><br/>
    年齡<input type="text" name="list[2].age" /><br/>
    生日<input type="text" name="list[2].birthday" /><br/>
    
    <input type="submit" value="提交" /><br/>
</form>


這里name屬性使用,list[0]...代表放入List集合中的某一個(gè)對(duì)象,用list[n].字段名 代表傳遞單個(gè)對(duì)象的單個(gè)字段的參數(shù)。

struts.xml : 請(qǐng)求對(duì)應(yīng)Action配置

<action name="model4" class="com.itdream.model.test.Model4Action"></action>

Action動(dòng)作類

/**
 * 封裝多個(gè)對(duì)象到List集合中 前提: 提供JavaBean類用于封裝每一個(gè)對(duì)象,頁面使用OGNL表達(dá)式
 */
public class Model4Action extends ActionSupport {

    // 提供List集合的聲明,用于封裝對(duì)象
    private List<User> list = new ArrayList<>();

    //必須提供List集合的get方法,讓Struts2框架能夠拿到該對(duì)象
    public List<User> getList() {
        return list;
    }

    //如果拿到的對(duì)象為空,Struts2會(huì)利用set方法聲明的引用設(shè)置一個(gè)新的對(duì)象捶朵。即框架底層會(huì)幫我new一個(gè)對(duì)象,并傳遞進(jìn)來,以便進(jìn)行封裝
    public void setList(List<User> list) {
        this.list = list;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(list);
        return NONE;
    }
}

4. 屬性驅(qū)動(dòng)-對(duì)象驅(qū)動(dòng)封裝對(duì)象到Map集合中

與上面屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)一樣蜘矢。

1. 必須提供JavaBean的實(shí)體類用于封裝對(duì)象狂男。
2. 頁面jsp傳參到Action動(dòng)作類使用OGNL表達(dá)式。
3. Action動(dòng)作類中聲明該對(duì)象,和模型驅(qū)動(dòng)不同,屬性驅(qū)動(dòng)的對(duì)象驅(qū)動(dòng)可以不創(chuàng)建對(duì)象,框架會(huì)幫我們創(chuàng)建對(duì)象品腹。
4. 必須提供get和set方法,以便Struts2的底層進(jìn)行封裝

form.jsp頁面OGNL表達(dá)式傳參:

<form action="${pageContext.request.contextPath }/model5.action" method="post">
    用戶名<input type="text" name="map['one'].username" /><br/>
    密碼<input type="password" name="map['one'].password" /><br/>
    年齡<input type="text" name="map['one'].age" /><br/>
    生日<input type="text" name="map['one'].birthday" /><br/>
    
    用戶名<input type="text" name="map['two'].username" /><br/>
    密碼<input type="password" name="map['two'].password" /><br/>
    年齡<input type="text" name="map['two'].age" /><br/>
    生日<input type="text" name="map['two'].birthday" /><br/>
    
    用戶名<input type="text" name="map['three'].username" /><br/>
    密碼<input type="password" name="map['three'].password" /><br/>
    年齡<input type="text" name="map['three'].age" /><br/>
    生日<input type="text" name="map['three'].birthday" /><br/>
    
    <input type="submit" value="提交" /><br/>
</form>

    
這里name屬性使用,map['one']...來代表放入map集合的第幾個(gè)對(duì)象,傳遞的單個(gè)對(duì)象的字段的參數(shù),使用map['one'].字段名來表示

struts.xml : 請(qǐng)求對(duì)應(yīng)Action配置

<action name="model5" class="com.itdream.model.test.Model5Action"></action>

Action動(dòng)作類

/**
 * 屬性驅(qū)動(dòng): 對(duì)象驅(qū)動(dòng)封裝多個(gè)對(duì)象的參數(shù) 前提: 有一個(gè)JavaBean的實(shí)體類用于封裝每個(gè)對(duì)象 jsp頁面使用OGNL表達(dá)式表示每一個(gè)字段屬性進(jìn)行傳參
 * 提供get和set方法
 */
public class Model5Action extends ActionSupport {

    // 聲明/創(chuàng)建一個(gè)Map集合用于封裝參數(shù)
    private Map<String, User> map = new HashMap<>();

    //提供get方法,Struts2框架可以獲得該map集合用于封裝
    public Map<String, User> getMap() {
        return map;
    }

    //提供set方法,Struts2如果獲得的map集合為null,會(huì)自動(dòng)創(chuàng)建一個(gè)然后傳遞Map集合的引用到當(dāng)前聲明
    public void setMap(Map<String, User> map) {
        this.map = map;
    }
    
    
    @Override
    public String execute() throws Exception {
        
        for(String key : map.keySet()) { //遍歷獲取每一個(gè)key
            System.out.println(key+">>>"+map.get(key));
            System.out.println("==============================");
        }
        return NONE;
    }
}

四岖食、 Struts2的參數(shù)類型轉(zhuǎn)換器【了解】

解決的問題:

客戶端傳輸過程中傳輸特定類型的字符串時(shí),到action類中需要轉(zhuǎn)換為對(duì)應(yīng)的對(duì)象時(shí)舞吭,中間的轉(zhuǎn)換的問題泡垃。
主要解決的是對(duì)象類型的轉(zhuǎn)換。

一般來說,Struts2提供的類型轉(zhuǎn)換器已經(jīng)很強(qiáng)大了镣典,一般不需要再自己自定義類型轉(zhuǎn)換器了兔毙。

-----------------------------------------------------------------------------
如果類型轉(zhuǎn)換錯(cuò)誤,會(huì)提示需要跳轉(zhuǎn)到result標(biāo)簽name為input對(duì)應(yīng)的頁面去 :

解決方案 : 配置input結(jié)果集視圖,跳轉(zhuǎn)回輸入頁面: 
    <result name="input">/error.jsp</result>

又發(fā)現(xiàn)如果只是這么處理讓其跳回輸入頁面沒有友好提示 :
解決方案:
    頁面需要回顯錯(cuò)誤提示兄春。使用<s:fielderror/>自動(dòng)回顯錯(cuò)誤信息澎剥。
    要使用該標(biāo)簽,必須先引入標(biāo)簽庫:
    <%@ taglib prefix="s" uri="/struts-tags" %> 
    <s:fielderror>填寫錯(cuò)誤</s:fielderror>

-----------------------------------------------------------------------------

為什么參數(shù)轉(zhuǎn)換錯(cuò)誤會(huì)跳轉(zhuǎn)到input邏輯視圖頁面赶舆?

1. 在接收請(qǐng)求參數(shù)時(shí)哑姚, 必然要進(jìn)行類型轉(zhuǎn)換。如果Struts2的類型轉(zhuǎn)換器執(zhí)行類型轉(zhuǎn)換時(shí)出現(xiàn)錯(cuò)誤芜茵,那么叙量,Struts2 內(nèi)部提供了一個(gè)名為conversionError的攔截器來處理錯(cuò)誤,該攔截器將負(fù)責(zé)將對(duì)應(yīng)錯(cuò)誤封裝成表單域錯(cuò)誤(FieldError)九串,并將這些錯(cuò)誤信息放入ActionContext中的一個(gè)集合中绞佩;

2. 當(dāng)執(zhí)行到WorkFlow攔截器的時(shí)候,該攔截器會(huì)判斷ActionContext的集合中是否存在錯(cuò)誤信息猪钮,如果存在品山,則,自動(dòng)跳轉(zhuǎn)到input邏輯視圖烤低。(一般我們還配置到原來的頁面肘交,讓用戶更正輸入的數(shù)據(jù))。

自定義轉(zhuǎn)換器的配置方案

1. 新建一個(gè)類繼承StrutsTypeConverter扑馁,實(shí)現(xiàn)內(nèi)部方法

public class DateConversion extends StrutsTypeConverter {
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
        if (values != null && values.length > 0) {
            String dateString = values[0];
            try {
                return sdf.parse(dateString);
            } catch (ParseException e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }

    @Override
    public String convertToString(Map context, Object o) {
        if (o != null && o instanceof Date) {
            return sdf.format(o);
        }
        return null;
    }
}   


2. 在項(xiàng)目的src下新建xwork-conversion.properties,在其中配置要轉(zhuǎn)換的類型(注冊(cè)全局轉(zhuǎn)換器)
    java.util.Date=org.itdream.struts.action.DateConversion

五涯呻、 異常Exception捕獲

解決的問題:當(dāng)action代碼執(zhí)行中出現(xiàn)異常時(shí),錯(cuò)誤信息會(huì)反饋到客戶頁面腻要,用戶體驗(yàn)不好

局部異常捕獲:

在action標(biāo)簽中配置exception-mapping標(biāo)簽:

<result name="xxx" type="redirect">/xxx.jsp</result>
<exception-mapping result="xxx" exception="java.lang.Throwable" />

* exception-mapping標(biāo)簽中的result屬性指向捕獲異常后出錯(cuò)的頁面結(jié)果复罐。
* exception-mapping標(biāo)簽中的exception屬性指的是要捕獲那種異常。

全局異常捕獲:

在package標(biāo)簽中配置global-exception-mapping標(biāo)簽 :

<global-results>
<result name="xxx">xxx.jsp</result>
</global-results>
<global-exception-mappings>
    <exception-mapping result="xxx"
            exception="java.lang.Throwable">
    </exception-mapping>
</global-exception-mappings>

* global-exception-mapping標(biāo)簽中的result屬性指向捕獲異常后出錯(cuò)的頁面結(jié)果雄家。
* global-exception-mapping標(biāo)簽中的exception屬性指的是要捕獲那種異常市栗。

異常顯示 :

異常捕獲的作用是為了提示用戶界面的顯示結(jié)果,但如果出錯(cuò)了,開發(fā)人員是要知道錯(cuò)誤日志的填帽。

如果要開啟錯(cuò)誤日志,在action標(biāo)簽中配置如下:

<interceptor-ref name="defaultStack">
    <param name="exception.logEnabled">true</param>
    <param name="exception.logLevel">error</param>
</interceptor-ref>

六咙好、 CRM案例:使用Hibernate與Struts2添加客戶

1. 分析

  1. 創(chuàng)建Web工程,Struts環(huán)境搭建
    • 導(dǎo)入Struts2的jar包(與Hibernate的jar包不沖突)
    • web.xml配置Struts2的前端控制器
    • 配置struts.xml,確定請(qǐng)求與Action動(dòng)作類,以及響應(yīng)與result頁面的對(duì)應(yīng)關(guān)系
    • Struts2搭建完成
  2. Hibernate環(huán)境搭建
    • 導(dǎo)入Hibernate所需的jar包:required,c3p0,log4j
    • 創(chuàng)建Hibernate所需的ORM關(guān)系
      • R : 關(guān)系型數(shù)據(jù)庫篡腌,創(chuàng)建所需數(shù)據(jù)庫的表sys_customer
      • O : 持久化類,編寫持久化類,Customer
      • M : 配置文件勾效,配置文件間的映射關(guān)系,Customer.hbm.xml
    • Hibernate的核心配置文件hibernate.cfg.xml
      • 連接數(shù)據(jù)庫的基本配置
      • 配置與線程綁定的Session
      • 普通配置
        • Hibernate的方言配置,實(shí)現(xiàn)了跨數(shù)據(jù)庫
        • 顯示sql語句
        • 格式化sql語句
        • Hibernate的自動(dòng)建表hbm2ddl
        • Hibernate的事務(wù)隔離級(jí)別配置
        • c3p0連接池配置
      • 加載映射文件
    • 編寫Hibernate工具類HibernateUtils
    • 測(cè)試Hibernate是否搭建成功
  3. 實(shí)現(xiàn)客戶添加功能
    • 這里我為了使用以下result標(biāo)簽的redirectAction的功能,修改menu.jsp點(diǎn)擊添加客戶時(shí)跳轉(zhuǎn)到CustomerAction嘹悼,最后跳轉(zhuǎn)到add.jsp
    • add.jsp填寫完成點(diǎn)擊提交,將數(shù)據(jù)提交到CustomerAction動(dòng)作類中,在Action動(dòng)作類實(shí)現(xiàn)將客戶保存到數(shù)據(jù)庫中
    • 添加完成訪問CustomerAction的查詢所有客戶的list方法
    • 功能完成

2. 環(huán)境搭建【省略】

3. 代碼體現(xiàn)

3.1 修改menu.jsp
點(diǎn)擊添加客戶跳轉(zhuǎn)到Action
<TD class=menuSmall><A class=style2 href="${pageContext.request.contextPath}/customer_add.action" target="main">- 新增客戶</A></TD>
3.2 struts.xml配置根據(jù)訪問路徑跳轉(zhuǎn)對(duì)應(yīng)Action
為了方便,我直接將struts.xml中所有配置直接粘貼過來,看的時(shí)候根據(jù)邏輯看

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <!-- 開發(fā)者模式開啟 -->
    <constant name="struts.devMode" value="true" />
    
    <package name="default" namespace="/" extends="struts-default">
        <!-- 與customer有關(guān)的Action -->
        <action name="customer_*" class="com.itdream.struts2.crm.web.action.CutomerAction" method="{1}">
            <result name="addJsp">/jsp/customer/add.jsp</result>
            <result name="saveSucess" type="redirectAction">customer_list</result>
            <!-- 默認(rèn)轉(zhuǎn)發(fā) -->
            <result name="listCustomer">/jsp/customer/list.jsp</result>
        </action>
    </package>
</struts>
3.3 Action動(dòng)作類
/**
 * 處理有關(guān)Cutomer的Action動(dòng)作類
 */
public class CutomerAction extends ActionSupport implements ModelDriven<Customer>{
    
    //手動(dòng)創(chuàng)建model對(duì)象,如果不創(chuàng)建只是聲明的話,Struts2底層不會(huì)幫我們創(chuàng)建
    private Customer customer = new Customer();
    
    @Override
    //必須提供getModel方法,Struts2才能獲得我們創(chuàng)建的model對(duì)象,進(jìn)行封裝
    public Customer getModel() {
        return customer;
    }
    
    
    //用戶點(diǎn)擊添加客戶其實(shí)可以直接讓他跳轉(zhuǎn)add.jsp,這里為了實(shí)現(xiàn)以下result標(biāo)簽的redirect重定向跳轉(zhuǎn)
    public String add() {
        return "addJsp";
    }
    
    
    //用戶添加客戶
    public String save() {
        System.out.println("=======================");
        //獲取表單提交參數(shù),這里使用模型驅(qū)動(dòng)Struts2框架幫我們進(jìn)行封裝
        //實(shí)現(xiàn)ModelDriven的接口,泛型是Customer的實(shí)體類,成員變量創(chuàng)建Model對(duì)象,添加getModel方法讓Struts2能夠獲得聲明的對(duì)象
        //--------------------------------------
        //調(diào)用Service業(yè)務(wù)層保存客戶
        CustomerService service = new CustomerServiceImpl();
        service.saveCustomer(customer);
        
        return "saveSucess";
    }
    
    //查看所有客戶列表
    public String list() {
        //調(diào)用Service業(yè)務(wù)層
        CustomerService service = new CustomerServiceImpl();
        List<Customer> listCustomer = service.findAllCustomer();
        
        //存入request作用域
        ServletActionContext.getRequest().setAttribute("list", listCustomer);
        
        //跳轉(zhuǎn)頁面
        return "listCustomer";
    }
}
3.4 Service業(yè)務(wù)層
public class CustomerServiceImpl implements CustomerService {

    @Override
    // 添加客戶
    public void saveCustomer(Customer customer) {
        // 獲取Session對(duì)象
        Session session = HibernateUtils.getCurrentSession();
        // 開啟事務(wù)
        Transaction transaction = session.beginTransaction();

        try {
            // 調(diào)用dao層
            CustomerDAO dao = new CustomerDAOImpl();
            dao.saveCustomer(customer);
        } catch (Exception e) {
            // 異常回滾,Hibernate默認(rèn)異巢愎回滾
            // transaction.rollback();
            e.printStackTrace();
        } finally {
            // 提交事務(wù)
            transaction.commit();
        }
    }

    @Override
    //查看所有客戶
    public List<Customer> findAllCustomer() {
        //獲取與線程綁定的Session對(duì)象
        Session session = HibernateUtils.getCurrentSession();
        //開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        
        List<Customer> listCustomer = null;
        try {
            //調(diào)用dao層
            CustomerDAO dao = new CustomerDAOImpl();
            listCustomer = dao.findAllCustomer();
        } catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            //提交事務(wù)
            transaction.commit();
        }
        return listCustomer;
    }
}
3.5 dao持久層
public class CustomerDAOImpl implements CustomerDAO {

    @Override
    //添加客戶
    public void saveCustomer(Customer customer) {
        //獲取Session對(duì)象
        Session session = HibernateUtils.getCurrentSession();
        //保存對(duì)象到Session緩沖區(qū),事務(wù)提交自動(dòng)更新到數(shù)據(jù)庫
        session.save(customer);
    }

    @Override
    //查詢所有客戶
    public List<Customer> findAllCustomer() {
        //獲得Session
        Session session = HibernateUtils.getCurrentSession();
        return session.createCriteria(Customer.class).list();
    }

}
3.6 解析list.jsp
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杨伙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子萌腿,更是在濱河造成了極大的恐慌限匣,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毁菱,死亡現(xiàn)場離奇詭異米死,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贮庞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門峦筒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窗慎,你說我怎么就攤上這事物喷。” “怎么了遮斥?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵峦失,是天一觀的道長。 經(jīng)常有香客問我伏伐,道長宠进,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任藐翎,我火速辦了婚禮材蹬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吝镣。我一直安慰自己堤器,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布末贾。 她就那樣靜靜地躺著闸溃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辉川,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天表蝙,我揣著相機(jī)與錄音,去河邊找鬼乓旗。 笑死府蛇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屿愚。 我是一名探鬼主播汇跨,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼妆距!你這毒婦竟也來了穷遂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤娱据,失蹤者是張志新(化名)和其女友劉穎蚪黑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吸耿,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祠锣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咽安。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伴网。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妆棒,靈堂內(nèi)的尸體忽然破棺而出澡腾,到底是詐尸還是另有隱情,我是刑警寧澤糕珊,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布动分,位于F島的核電站,受9級(jí)特大地震影響红选,放射性物質(zhì)發(fā)生泄漏澜公。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一喇肋、第九天 我趴在偏房一處隱蔽的房頂上張望坟乾。 院中可真熱鬧,春花似錦蝶防、人聲如沸甚侣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殷费。三九已至印荔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間详羡,已是汗流浹背仍律。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留实柠,地道東北人染苛。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像主到,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子躯概,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容