首先感谢“郡主”对个人支持,她帮忙完善了跳转地址重定向问题。 java
1. 目标——什么异常须要咱们处理 web
一般来讲,在业务流程中已经将大部分异常进行处理,由于大部分异常是继承java.lang.Exception,因此开发人员在IDE环境中能够轻松识别并使用try catch语句块进行处理。可是别忘了java.lang.RuntimeException。struts框架有两种异常处理方式:action的exception配置和global-exceptions配置 ajax
<action-mappings> <action path="/Test" scope="request" type="com.sg.LoginAction" parameter="method" > <forward name="index" path="/index.jsp"/> <exception key="error.action.message" type="java.lang.RuntimeException"></exception> </action> </action-mappings>
<global-exceptions> <exception key="error.message" type="java.lang.RuntimeException" path="/common/errorPage.jsp" /> </global-exceptions>若LoginAction的方法抛出的RuntimeException(事实上RuntimeException的子类也能够),struts会尝试在action配置中查找对应的exception配置并进行处理,若没有找到,则查找global-exceptions配置并处理,二者都没有找到,struts框架会抛出ServletException让web容器处理。
3. 一般的处理思路以及struts框架的弊端
3.1 action的exception和global-exception的选择
因为项目中,按模块、按功能划分后的action配置会不少,显然在使用action的exception配置进行同一的RuntimeException处理配置的工做量很是大,global-exceptions是咱们的选择。
3.2 global-exceptions的配置
RuntimeException的子类很是多,咱们不能把每个RuntimeException的子类都进行配置。还好struts框架对于异常的处理能够对Exception进行向上转型并处理,好比Action抛出的NullPointerException,struts会按照NullPointerException->RuntimeException->Exception->Throwable的顺序一次查找是否有对应的处理。
3.3 邪恶的struts1框架
1) struts1的global-exeptions是针对配置文件的,假设项目按照功能划分的struts-user.xml和struts-department.xml,这两个配置的中的global-exeptions配置是不能共用的。
2) 为了便于项目组对模块进行划分,struts的配置文件一般会设置不一样的前缀(prefix,最后会有关于prefix的简单介绍),ActionForward根据前缀的路径进行跳转,所以不一样的struts的配置文件可能须要配置不一样的跳转地址。 apache
4. ExceptionHandler带来的起色
框架的目的之一是为了让开发人员忽略技术使用细节,转而将更多的精力放在业务逻辑实现上。为了绕开struts的复杂的异常处理,咱们使用struts的ExceptionHandler。
ExceptionHandler是struts默认异常处理类,在Action方法执行发生异常时,ExceptionHander将捕获异常,并进行更进一步的处理(如将异常根据配置的不一样放入request或session、配置key国际化等),经过继承ExceptionHandler,咱们能够尝试进行地址的统一跳转。
struts的跳转是经过ActionForward的信息进行的,因此在ExceptionHandler子类中创新统一的ActionForward便可,代码以下:
session
public class CommonExceptionHandler extends ExceptionHandler { private static final Logger logger = Logger.getLogger(CommonExceptionHandler.class); /** 统一跳转地址路径 */ private static final String EXCEPTION_PAGE_PATH = "/common/exceptionPage.jsp"; public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { logger.info("统一异常处理 begin"); logger.error("Action抛出了未捕获的异常", ex); /* * 判断是否为ajax请求 * 如果ajax请求,因为页面处理方式不一致,不作页面提示 */ String ajaxFlg = request.getHeader("X-Requested-With"); if(ajaxFlg != null) { logger.info("请求类型为ajax请求!"); logger.info("统一异常处理 end"); return null; } /* 调用父类方法,方法中会将exception信息放入request */ super.execute(ex, ae, mapping, formInstance, request, response); /* 设置同一跳转路径 */ ActionForward forward = new ActionForward("excepationPage", EXCEPTION_PAGE_PATH , false, ""); logger.info("统一异常处理 end"); return forward; } }代码中有两处须要注意:
/** * Construct a new instance with the specified values. * * @param name Name of this forward * @param path Path to which control should be forwarded or redirected * @param redirect Should we do a redirect? * @param module Module prefix, if any */ public ActionForward(String name, String path, boolean redirect, String module) { super(); setName(name); setPath(path); setRedirect(redirect); setModule(module); }module指Module prefix,咱们项目在根目录下的/common/exceptionPage.jsp,因此使用struts-config.xml的prefix,若使用其余配置文件的prefix须要自行修改。
<servlet> <servlet-name>controller</servlet-name> <servlet-class> org.apache.struts.action.ActionServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value> /WEB-INF/struts/struts-config.xml </param-value> </init-param> <init-param> <param-name>config/page/user</param-name> <param-value> /WEB-INF/struts/config/struts-user.xml </param-value> </init-param> <init-param> <param-name>config/page/user/department</param-name> <param-value> /WEB-INF/struts/config/struts-department.xml </param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet>struts1框架要求param-name必须以config开头,不然不处理。去掉config/,后面内容就是该配置文件的惟一标识,而这个就是prefix。struts-config.xml比较特别,它的prefix使用空串("")。