1 异常链
当不需要用户来处理和关心原始的异常时,常见的做法是捕获原始的异常,把他们包装成一个新的不同类型的异常,然后再抛出异常。
所谓异常链就是把原始异常包装成新的异常类时,在新的异常类中封装了原始异常类
2 多样化异常
在实际应用中,有时需要一个方法同时抛出多个异常。
如果应用不支持在一个方法中抛出多个异常,用户每次将只能看到针对一个字段域的验证错误,当改正了一个错误后,重新提交表单,又会收到针对另一个字段域的验证错误,这会使得用户体验非常多差劲。
有效的做法是每次当用户提交表单后,都验证所有的字段,然后向用户显示所有的验证信息。不幸的是,在java中一次只能抛出一个异常。因此需要开发者自行设计支持多样化异常的异常类。
3 struts异常分析
在struts的控制层中,将java的异常类包装成ActionMessage。在struts中定义异常有两种方式:
扩展ModuleException和创建自定义的异常类体系。
扩展ModuleException :
优点,可以很好的和sturts的Resouce Bundle绑定。
ModuleException(String key)和ModuleException(String key,Object[] values)
key为错误消息key,values为对象数组类型的values参数。
自定义异常类:
如:
Java代码
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class BaseException extends Exception {
protected Throwable rootCause = null;
private List exception = new ArrayList<Throwable>();
private String messageKey = null;
private Object[] messageArgs = null;
public Throwable getRootCause() {
return rootCause;
}
public void setRootCause(Throwable rootCause) {
this.rootCause = rootCause;
}
public List getException() {
return exception;
}
public void addException(Throwable exception) {
this.exception.add(exception);
}
public String getMessageKey() {
return messageKey;
}
public void setMessageKey(String messageKey) {
this.messageKey = messageKey;
}
public Object[] getMessageArgs() {
return messageArgs;
}
public void setMessageArgs(Object[] messageArgs) {
this.messageArgs = messageArgs;
}
@Override
public void printStackTrace() {
printStackTrace(System.err);
}
@Override
public void printStackTrace(PrintStream s) {
printStackTrace(new PrintWriter(s));
}
@Override
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
if(getRootCause() != null){
getRootCause().printStackTrace(s);
}
s.flush();
}
}
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class BaseException extends Exception {
protected Throwable rootCause = null;
private List exception = new ArrayList<Throwable>();
private String messageKey = null;
private Object[] messageArgs = null;
public Throwable getRootCause() {
return rootCause;
}
public void setRootCause(Throwable rootCause) {
this.rootCause = rootCause;
}
public List getException() {
return exception;
}
public void addException(Throwable exception) {
this.exception.add(exception);
}
public String getMessageKey() {
return messageKey;
}
public void setMessageKey(String messageKey) {
this.messageKey = messageKey;
}
public Object[] getMessageArgs() {
return messageArgs;
}
public void setMessageArgs(Object[] messageArgs) {
this.messageArgs = messageArgs;
}
@Override
public void printStackTrace() {
printStackTrace(System.err);
}
@Override
public void printStackTrace(PrintStream s) {
printStackTrace(new PrintWriter(s));
}
@Override
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
if(getRootCause() != null){
getRootCause().printStackTrace(s);
}
s.flush();
}
}
因为有了rootCause exceptions messageKey 和messageArgs 这四个属性使得这个自定义异常类有了以下功能:
支持异常的级联,rootCause属性制定原始异常(异常链)
支持多样化异常,exceptions属性存放所有嵌套的异常
支持和struts的Resouce Bundle的绑定,messageKey属性指定消息key
支持复合式消息,messageArgs属性指定复合式消息中的参数。
处理异常的方法 :
NO。1
自己手动编写。
个人抛出异常方法:
if(满足一定条件){
throw new RuntionException(“错误提示信息”);
}
由自己try {}catch(){}进行捕获然后,用mapping.forwoard(“”)跳转到处理页面中来。
xxAction.java
Java代码
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
try {
getOrgnizationService().delete(id);
} catch (RuntimeException e) {
<SPAN style="COLOR: #000000">ActionMessages mesgs = new ActionMessages();
ActionMessage mesg = new ActionMessage("error.detail",e.getMessage());//error.detail为资源文件,e.getMessage()为得到的错误信息。他所处的地方为error.detail的参数所在地。
mesgs.add("error",mesg);
this.saveErrors(request, mesgs); //错误信息存入到页面中去。</SPAN>
return mapping.findForward("exception");
}
return mapping.findForward("OK");
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
try {
getOrgnizationService().delete(id);
} catch (RuntimeException e) {
ActionMessages mesgs = new ActionMessages();
ActionMessage mesg = new ActionMessage("error.detail",e.getMessage());//error.detail为资源文件,e.getMessage()为得到的错误信息。他所处的地方为error.detail的参数所在地。
mesgs.add("error",mesg);
this.saveErrors(request, mesgs); //错误信息存入到页面中去。
return mapping.findForward("exception");
}
return mapping.findForward("OK");
}
struts-config.xml文件:
Xml代码
<action-mappings >
<action
attribute="orgnizationForm"
name="orgnizationForm"
parameter="method"
path="/orgnization"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy"
validate="false">
<forward name="exception" path="/error.jsp"></forward>
<forward name="OK" path="/main/orgnization.jsp" />
</action>
</action-mappings><STRONG><SPAN style="FONT-SIZE: medium"><SPAN style="COLOR: #ff0000"> </SPAN>
</SPAN>
</STRONG>
<action-mappings >
<action
attribute="orgnizationForm"
name="orgnizationForm"
parameter="method"
path="/orgnization"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy"
validate="false">
<forward name="exception" path="/error.jsp"></forward>
<forward name="OK" path="/main/orgnization.jsp" />
</action>
</action-mappings>
在页面调用这个时应该用<html:errors>即可把资源文件里面的错误信息显示出来。
NO。2
在项目中通常需要统一的错误处理。将异常throws出去,交给sturts来处理。
有两个缺点 :
不能处理带参数的异常!去给资源文件的参数赋值;
异常的类型在配置文件中是固定的,不能动态改变。
struts可以有两种方法对异常进行处理。
一种 是在struts配置文件里面的action下面(局部异常处理 ),用exception来处理
Xml代码
<action-mappings >
<action
attribute="orgnizationForm"
name="orgnizationForm"
parameter="method"
path="/orgnization"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<SPAN style="COLOR: #000000"><exception key="error.detail" type="<SPAN>java.lang.RuntimeException</SPAN>
" scope="request" path="/error.jsp"></exception></SPAN>
<forward name="OK" path="/main/orgnization.jsp" />
</action>
</action-mappings>
<action-mappings >
<action
attribute="orgnizationForm"
name="orgnizationForm"
parameter="method"
path="/orgnization"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<exception key="error.detail" type="java.lang.RuntimeException
" scope="request" path="/error.jsp"></exception>
<forward name="OK" path="/main/orgnization.jsp" />
</action>
</action-mappings>
另一种 方法是在struts的配置文件中的global-exception为全局的异常 :
Xml代码
<global-exceptions>
<exception key="error.detail" type="java.lang.RuntimeException" scope="request" path="/error.jsp"></exception>
</global-exceptions>
<global-exceptions>
<exception key="error.detail" type="java.lang.RuntimeException" scope="request" path="/error.jsp"></exception>
</global-exceptions>
NO。3 (推荐)
使用自定义的异常类来继承原始的异常。用自定义的异常类来处理整个工程的异常。在一个异常类中使用多种异常。用一个异常类来代表不同的异常消息。
首先,定义自己的异常类:他要继承RuntimeException
Java代码
package edu.hust.util;
import java.io.PrintStream;
import java.io.PrintWriter;
public class SystemException extends RuntimeException {
<SPAN style="COLOR: #000000">private String key;</SPAN>
private Object[] values;
public String getKey(){
return key;
}
public Object[] getValues(){
return values;
}
public SystemException() {
super();
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
public SystemException(String message) {
super(message);
}
public SystemException(Throwable cause) {
super(cause);
}
public SystemException(String message,String key){
super(message);
this.key = key;
}
public SystemException(String message,String key,Object values){
super(message);
this.key = key;
this.values = new Object[]{values};
}
public SystemException(String message,String key,Object[] values){
super(message);
this.key = key;
this.values = values;
}
}
package edu.hust.util;
import java.io.PrintStream;
import java.io.PrintWriter;
public class SystemException extends RuntimeException {
private String key;
private Object[] values;
public String getKey(){
return key;
}
public Object[] getValues(){
return values;
}
public SystemException() {
super();
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
public SystemException(String message) {
super(message);
}
public SystemException(Throwable cause) {
super(cause);
}
public SystemException(String message,String key){
super(message);
this.key = key;
}
public SystemException(String message,String key,Object values){
super(message);
this.key = key;
this.values = new Object[]{values};
}
public SystemException(String message,String key,Object[] values){
super(message);
this.key = key;
this.values = values;
}
}
在抛出异常的地方:
Java代码
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
try {
getOrgnizationService().delete(id);
} catch (RuntimeException e) {
throw new SystemException("有子机构,不能删除!","error.detail2");//去对应上面的构造函数,知道error.detail2为key。
}
return mapping.findForward("OK");
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
try {
getOrgnizationService().delete(id);
} catch (RuntimeException e) {
throw new SystemException("有子机构,不能删除!","error.detail2");//去对应上面的构造函数,知道error.detail2为key。
}
return mapping.findForward("OK");
}
在配置文件中:
Xml代码
<global-exceptions>
<exception
key="error.detail" <SPAN style="COLOR: #000000"> </SPAN>
type="edu.hust.SystemException"
scope="request"
path="/error.jsp"
handler="edu.hust.util.SystemExceptionHandler">
</exception>
</global-exceptions>
<global-exceptions>
<exception
key="error.detail"
type="edu.hust.SystemException"
scope="request"
path="/error.jsp"
handler="edu.hust.util.SystemExceptionHandler">
</exception>
</global-exceptions>
异常处理类:
Java代码
package edu.hust.util;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ExceptionHandler;
import org.apache.struts.config.ExceptionConfig;
public class SystemExceptionHandler extends ExceptionHandler {
@Override
public ActionForward execute(Exception ex, ExceptionConfig ae,
ActionMapping mapping, ActionForm formInstance,
HttpServletRequest request, HttpServletResponse response)
throws ServletException {
ActionForward forward = null;
if( null != ae.getPath()){
forward = new ActionForward(ae.getPath());//获得默认的path
}else{
forward = mapping.getInputForward();
}
if(ex instanceof SystemException){
ActionMessage error = null;
SystemException sysExce = (SystemException) ex;
String key = sysExce.getKey(); //获得key
if( null == key){ //如果可以为空
error = new ActionMessage(ae.getKey(),sysExce.getMessage());
}else{
if(null != sysExce.getValues()){ // 可以不为空,且有参数
error = new ActionMessage(key,sysExce.getValues());
}else{
error = new ActionMessage(key);
}
}
this.storeException(request, key, error, forward, ae.getScope());
return forward;
}
return super.execute(ex, ae, mapping, formInstance, request, response); //异常不属于自定义异常类
}
}