在struts2的struts-default.xml中定义了一个name为exception拦截器,实现类是com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor,它的作用是对action中的异常进行处理(输出异常日志,与配置文件中的<exception-mapping/>匹配).
该拦截器有三个参数,分别是:
a、logEnabled (可选) -是否将异常信息打印到日志中,默认为false
b、logLevel (可选) - 打印异常的日志级别,可选(trace, debug, info, warn, error, fatal),默认是debug
c、logCategory (可选) - 指定logger的种类,默认使用"com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"
首先说明一下 struts.xml 中的<exception-mapping/>配置。
<exception-mapping/> 是将异常类型与result进行对应,该元素需要指定两个属性:1,exception:此属性指定该异常映射所设置的异常类型。 2,result:此属性指定Action出现该异常时,系统转入result属性所指向的结果。 而 <exception-mapping/>也分为两种:1,局部异常映射:﹤exception-mapping/﹥元素作为﹤action/﹥元素的子元素配置。2,全局异常映射:﹤exception-mapping/﹥元素作为﹤global-exception-mappings/>元素的子元素配置。
例如:
<package name="test_Alias" extends="struts-default" namespace="/alias">
<global-exception-mappings>
<exception-mapping result="input" exception="java.lang.Exception"/>
</global-exception-mappings>
<action name="from" class="com.warning.interceptor.action.AliasAction1" method="_name">
<result name="success" type="chain">to</result>
<exception-mapping result="input" exception="java.lang.RuntimeException"/>
</action>
</package>
使用Struts2的标签来输出异常信息:
<s:property value="exception"/>:输出异常对象本身。
<s:property value="exceptionStack"/>: 输出异常堆栈信息。
由于exception拦截器已经在默认拦截器栈defaultStack中,所以无需进行配置。
接下来我们看一下exception拦截器都做了什么事情:
public String intercept(ActionInvocation invocation) throws Exception {
String result;
try {
//先执行action,如果action中抛出异常,进入catch块,没有异常直接返回
result = invocation.invoke();
} catch (Exception e) {
//isLogEnabled()的返回值如果是true,这进入handleLogging()方法,打印异常信息。handleLogging的值在初始化拦截器时候指定,默认为false
if (isLogEnabled()) {
handleLogging(e);
}
//获取action中所有的<exception-mapping>配置
List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
//执行findResultFromExceptions()方法,返回异常信息对应的result
String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
if (mappedResult != null) {
result = mappedResult;
//利用异常对象构建一个ExceptionHolder对象,然后push到值栈的顶部,该方法调用的是invocation.getStack().push(exceptionHolder);ExceptionHolder类中存在两个方法:getException()返回异常对象本省、getExceptionStack()方法调用e.printStackTrace()方法把异常栈信息出入到一个PrintWriter流中,然后从流中获取到一个字符串返回(该字符串和调用e.printStackTrace()后控制台输出的错误信息一样),这就是为什么可以使用<s:property value="exception"/>和 <s:property value="exceptionStack"/>获取到异常信息了。
publishException(invocation, new ExceptionHolder(e));
} else {
throw e;
}
}
return result;
}
接下来我们分别看一下handleLogging方法和findResultFromExceptions方法分别做了些什么事情:
protected void handleLogging(Exception e) {
if (logCategory != null) {
//如果配置了logCategory参数,则根据参数初始化logger
if (categoryLogger == null) {
// init category logger
categoryLogger = LoggerFactory.getLogger(logCategory);
}
//打印异常信息
doLog(categoryLogger, e);
} else {
doLog(LOG, e);
}
}
/**
* Performs the actual logging.
*
* @param logger the provided logger to use.
* @param e the exception to log.
*/
protected void doLog(Logger logger, Exception e) {
//如果配置了logEnabled参数与为true,但未配置logLevel 参数,则使用logger.debug()方法打印日志(这样的效果像logLevel 的默认值为debug)。
if (logLevel == null) {
logger.debug(e.getMessage(), e);
return;
}
//根据logLevel参数调用不通方法打印日志。
if ("trace".equalsIgnoreCase(logLevel)) {
logger.trace(e.getMessage(), e);
} else if ("debug".equalsIgnoreCase(logLevel)) {
logger.debug(e.getMessage(), e);
} else if ("info".equalsIgnoreCase(logLevel)) {
logger.info(e.getMessage(), e);
} else if ("warn".equalsIgnoreCase(logLevel)) {
logger.warn(e.getMessage(), e);
} else if ("error".equalsIgnoreCase(logLevel)) {
logger.error(e.getMessage(), e);
} else if ("fatal".equalsIgnoreCase(logLevel)) {
logger.fatal(e.getMessage(), e);
} else {
throw new IllegalArgumentException("LogLevel [" + logLevel + "] is not supported");
}
}
protected String findResultFromExceptions(List<ExceptionMappingConfig> exceptionMappings, Throwable t) {
String result = null;
//寻找exceptionMappings中与异常最匹配的result
if (exceptionMappings != null) {
int deepest = Integer.MAX_VALUE;
for (Object exceptionMapping : exceptionMappings) {
ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) exceptionMapping;
int depth = getDepth(exceptionMappingConfig.getExceptionClassName(), t);
if (depth >= 0 && depth < deepest) {
deepest = depth;
result = exceptionMappingConfig.getResult();
}
}
}
return result;
}
/**
* Return the depth to the superclass matching. 0 means ex matches exactly. Returns -1 if there's no match.
* Otherwise, returns depth. Lowest depth wins.
*
* @param exceptionMapping the mapping classname
* @param t the cause
* @return the depth, if not found -1 is returned.
*/
public int getDepth(String exceptionMapping, Throwable t) {
return getDepth(exceptionMapping, t.getClass(), 0);
}
private int getDepth(String exceptionMapping, Class exceptionClass, int depth) {
if (exceptionClass.getName().contains(exceptionMapping)) {
// Found it!
return depth;
}
// If we've gone as far as we can go and haven't found it...
if (exceptionClass.equals(Throwable.class)) {
return -1;
}
return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1);
}
handleLogging方法打印日志,findResultFromExceptions方法从配置中寻找与异常最匹配的result返回。
版权所有,转载请标明出处:http://blogwarning.iteye.com/blog/1334947
分享到:
相关推荐
例如,`struts-default.xml`中包含了默认的拦截器栈,如`params`拦截器用于处理请求参数,`exception`拦截器用于处理异常,`validation`拦截器进行数据校验。 在深入源码之前,我们需要了解几个关键类: 1. `...
总结起来,Struts2的拦截器机制是其强大功能之一,它使得开发者能够轻松地在Action执行流程中插入自定义逻辑。通过创建和配置拦截器,我们可以实现诸如权限验证、日志记录等功能,提升应用的安全性和可维护性。在...
2. **默认拦截器栈**:`defaultStack`包含了Struts2内置的一些拦截器,如`params`(处理参数),`i18n`(处理国际化),`exception`(处理异常)等。 3. **应用全局拦截器**:现在,所有Action都会在执行前经过`...
Struts2是一个流行的Java web框架...总的来说,Struts2的默认拦截器提供了全面的功能支持,使得开发者能够构建安全、高效且易于维护的Web应用程序。理解并熟练掌握这些拦截器的使用,将有助于提升开发效率和应用质量。
当请求到达控制器时,Struts2会依次调用这个栈中的拦截器,每个拦截器都有机会处理请求,然后决定是否将请求传递给下一个拦截器或直接返回响应。 创建一个简单的Struts2拦截器,你需要遵循以下步骤: 1. 创建拦截...
默认拦截器栈`defaultStack`包含了Struts2预定义的一些拦截器,如`params`、`i18n`等。在添加自定义拦截器时,可以将其插入到默认拦截器栈中,也可以创建自定义的拦截器栈。 ### 五、测试与优化 完成上述步骤后,你...
`defaultStack`是Struts2提供的默认拦截器栈,包含了如`exception`、`params`、`i18n`等常用拦截器。 了解了拦截器的基本原理后,我们可以通过`Struts2.x 拦截器.avi`这个视频文件深入学习Struts2拦截器的实现细节...
-- 其他默认拦截器 --> <result name="success">/success.jsp <result name="invalid">/error.jsp ``` 至此,你已经掌握了Struts2拦截器的基本使用。实际开发中,你可以根据项目需求灵活组合和扩展拦截...
- 使用`<default-interceptor-ref>`定义默认拦截器栈,所有未明确指定拦截器的动作都将使用这个栈。 4. **自定义拦截器**: - 创建一个新的Java类,实现`Interceptor`接口并重写`intercept()`方法。 - 在`...
Struts2作为一款流行的Java Web框架,其核心机制之一就是拦截器(Interceptor)。拦截器是AOP(面向切面编程)思想在Struts2中的具体实现,它允许开发者在动作执行前后插入自定义的处理逻辑,提升了代码的可复用性和...
-- 将自定义拦截器添加到默认拦截器栈中 --> <!-- 配置Action使用自定义拦截器栈 --> <result name="profanityError">/errorPage.jsp <!-- 其他结果配置 --> </struts> ``` 在上述配置中,`...
### Struts2 拦截器与验证框架详解 #### 一、Struts2概述 Struts2是一个基于Java的企业级Web应用开发框架,它继承了Struts1的优点,并在此基础上进行了很多改进,使得开发更加灵活高效。Struts2的核心是拦截器...
在Struts2中,拦截器(Interceptor)是实现业务逻辑控制和增强功能的重要机制,而国际化(Internationalization,简称i18n)则能帮助我们构建支持多语言的Web应用。下面将详细解释这两个知识点以及它们如何在Struts2...
配置拦截器通常在struts.xml文件中进行,可以定义默认拦截器栈,也可以为特定的包和Action指定特定的拦截器。 下面是一个简单的配置拦截器的例子,这里定义了一个名为“test”的拦截器,并通过class属性指定拦截器...
默认情况下,所有Action都会应用名为`defaultStack`的默认拦截器栈。如果你需要添加自定义拦截器,可以显式地引用它们。 ```xml <result>success.jsp ``` 在上述配置中,`someAction`会先经过`...
### Struts2内置拦截器简介 Struts2框架在实现MVC模式时,为了更好地管理请求处理过程中的各个阶段,引入了拦截器机制。通过拦截器可以对请求进行预处理或后处理,使得代码更加模块化和易于维护。Struts2提供了一...
通过分析这些源代码,我们可以了解自定义拦截器的实现方式以及与默认拦截器如何协同工作。 而`WebRoot`目录则包含了Web应用的静态资源,如HTML、CSS、JavaScript文件,以及Struts2的配置文件(如`struts.xml`)和...
Struts2默认提供了一系列内置拦截器,每种拦截器都有其特定的功能: 1. **alias**:别名拦截器,主要用于简化不同Action间参数的共享,特别是当需要在不同Action间传递同名但不同作用域的参数时,可以通过`aliases`...
Struts2 拦截器是Struts2框架的核心组件之一,它允许开发者在Action执行前后插入自定义的处理逻辑,实现对请求的预处理和后处理,从而增强应用程序的功能和控制流程。以下是对Struts2拦截器原理与实现的详细解析: ...
- **默认拦截器**:Struts2提供了一些内置的拦截器,比如`params`用于处理请求参数,`exception`用于异常处理,`i18n`处理国际化,`validation`执行字段验证等。这些默认拦截器的配置可以在`struts-default.xml`文件...