1. 程式人生 > >struts2中的異常對映處理機制

struts2中的異常對映處理機制

首先在struts2中有兩種異常處理機制:區域性異常對映和全域性異常對映。

拿經典的使用者登入功能來說:

一:區域性異常:

1:首先我們的登入介面:表單交由exAction.action 處理。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  <s:form action="exAction" id="form" method="post">
   <s:textfield name="username" key="user"/>
   <s:textfield name="password" key="pass"/><br/>
    <s:submit key="login"/>
  </s:form>
</body>
</html>

2:我們先定義一個異常myException:申明message屬性並提供get,set方法,封裝提示資訊。該類繼承Exception

package com.mao;

public class myException extends Exception {
	private String message;
	public myException(String message) {
		super(message);
		this.message = message;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	
}

3:然後我們的邏輯控制器Action,實現類:ExceptionAction

package com.mao;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class ExceptionAction extends ActionSupport{
	private String username;
	private String password;
	private String tip;
	
	//省略所有屬性的set、get方法
	public String execute()throws Exception{
		ActionContext act=ActionContext.getContext();
		if(getUsername().equalsIgnoreCase("user")){
			throw new myException("自定義異常");
		}
		if(getUsername().equalsIgnoreCase("sql")){
			throw new java.sql.SQLException("使用者名稱不能為sql");
		}
		if(getUsername().equals("mao")&&getPassword().equals("3214")){
			setTip("伺服器提示:登陸成功");
			return SUCCESS;
		}else{
			return ERROR;
		}
	}
}

程式碼很明顯看出,如果使用者名稱為user丟擲自定義異常,如果為sql丟擲系統定義的SQLException異常,這裡順便說一下equalsIgnoreCase()方法與equals()區別,從字面上也看出來了equalsIgnoreCase()字面不拘小節嘛,所以它不區分大小寫,比如使用者名稱getUsername.equalsIgnoreCase("mao"),你輸mao和Mao都是可以可以的,而equals()嚴格區分位元組和長度,比較苛刻。

4:然後我們的配置檔案struts.xml

此處我只列舉出區域性異常的部分:

            <!-- 定義區域性異常和區域性結果集 -->
	    <action name="exAction" class="com.mao.ExceptionAction">
	      <exception-mapping result="my" exception="com.mao.myException"/>
	      <result name="my">/ecpt.jsp</result>
	      <result name="success">/welcom.jsp</result>
	      <result name="error">/error.jsp</result>
	    </action>
這裡注意,區域性異常是在<action></action>標籤內通過<exception-mapping/>標籤定義的的,而且需要指定結果字串result="my",和exception="com.mao.myException"異常對映所指定的異常型別,拿此處來講,對映的就是咱們前面定義的myException異常,com.mao為該類所在的包。可以看出,區域性異常全部定義在<action></action>標籤之內。一快看下來就是,前臺表單交給exAction去處理,好,處理的過程中丟擲了一個myException異常,然後該異常返回了一個my的結果字串,然後,在下面<result name="my">/ecpt.jsp</result>標籤中定義此異常所返回的檢視。這裡也可以發現struts2框架的優點,耦合度低,前臺表單僅傳過來一個action,然後核心控制器filet截獲並匹配相應邏輯控制器action去處理,處理完成後不是直接用檢視的形式顯示出來,而是返回一個字串my,然後再通過相應字串對映到相應檢視。這大大提高了程式碼的複用性,哪天我們需要對映到不同檢視時,只需修改<result>對映就可以(好了,扯多了)

5:這是返回的ecpt.jsp頁面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  異常資訊:<s:property value="exception.message"/>
</body>
</html>


這裡的exception就是指的咱們定義的異常com.mao.myException.

另外提示一點,本人在測試的時候由於在此頁面中一直沒有加

<%@taglib prefix="s" uri="/struts-tags" %>

這樣就沒法使用struts2標籤,也就一直沒法輸出異常資訊,希望大家不要犯此類低階錯誤。

6:執行結果

在表單輸入user或者User


二:全域性異常:

1:同樣拿這個使用者登入介面來講,前面的表單,控制器exAction都已經給出,不再多說,我們直接看Struts.xml配置資訊的如何配置全域性異常:

<!-- 定義全域性結果對映 -->

	  <global-results>
	    <result name="sql">/ecpt.jsp</result>
	    <result name="root">/ecpt.jsp</result>
	  </global-results>
	  <!-- 定義全域性異常 -->
	  <global-exception-mappings>
	      <exception-mapping result="sql" exception="java.sql.SQLException"/>
	      <exception-mapping result="root" exception="java.lang.Exception"/>
	  </global-exception-mappings></span></span>

以上就定義了全域性結果對映和全域性異常對映,可以看出全域性結果對映和全域性異常都需要包含在<global...></global...>中,相當於,加上這個標籤,你們就牛X了,就可以在全域性有用了。說回來:全域性異常需要定義在<global-exception-mappings></global-exception-mappings>中,這個標籤就相當於給他們加了牛X屬性,然後再在這裡面通過<exception-mapping result="" exception=""/>標籤定義全域性異常對映(與區域性相同)另外<exception-mapping/>標籤注意結束形式,全域性異常不能定義在<action></action>標籤中,因為它需要在全域性起作用,而不是某個action中起作用。:

2:結果:我們分別輸入sql和正確的使用者名稱密碼 mao  3214顯示


三:總結:

區域性異常對映只對該Action有效,全域性異常對映對所有Action有效。

但是區域性異常對映"執行力"強,在都區域性異常和全域性異常都定義了相同對映的情況,程式會先去區域性對映尋找相應的<result name="">所返回的檢視,如果有,返回該檢視,如果沒有,那好,去全域性對映裡找。

例如:

          <global-results>
	    <result name="my">/welcom.jsp</result>
	  </global-results>
	  <!-- 定義全域性異常 -->
	  <global-exception-mappings>
	      <exception-mapping result="my" exception="com.mao.myException"/>
	  </global-exception-mappings>
	    <!-- 定義區域性異常和區域性結果集 -->
	    <action name="exAction" class="com.mao.ExceptionAction">
	      <exception-mapping result="my" exception="com.mao.myException"/>
	    </action>
如上,我們在區域性以及全域性異常對映裡都定義了com.mao.myException的對映,而且返回結果字串都為my,程式會先去區域性找,發現並沒有找到相應的<result name="my">定義的返回檢視,這時他就會去全域性找,正好找到有個定義的<result name="my">所以將返回welcom.jsp頁面,記住一句話:在區域性對映和全域性對映都存在相同<resule name="">屬性,而且區域性異常對映指定了jsp頁面的情況下,全域性對映永遠都是"備胎"。