Struts2默认拦截器(ExceptionMappingInterceptor)的使用及源码阅读
定义
捕获异常并定位到指定视图。
ps:从这给类的原型,可以帮助我们思考异常如何以日志形式记录,可以再此类的基础上进行扩展。这个待日后有慢慢琢磨。
使用
1.局部exception配置使用
Action源码:
struts-xxx.xml配置:
- public class SourceCoreAction {
- public String error() throws ClassNotFoundException {
- System.out.println("do the error!");
- Class.forName("xxx");
- return "success";
- }
- }
- <span style="white-space:pre"> </span><action name="error" class="com.company.strutstudy.web.action.core.SourceCoreAction"
- method="error">
- <interceptor-ref name="exception"></interceptor-ref><!--只有一个默认拦截器起作用,好debug-->
- <result name="input">/core/exception.jsp</result>
- <result name="success">/core/ok.jsp</result>
- <exception-mapping result="input" exception="java.lang.Exception"></exception-mapping>
- </action>
2.全局exception配置使用
Action源码不变,参考局部exception
struts-xxx.xml配置:
- <struts>
- <package name="exception" extends="struts-default" abstract="true">
- <global-results>
- <result name="input">/core/exception.jsp</result>
- </global-results>
- <global-exception-mappings>
- <exception-mapping result="input" exception="java.lang.Exception"></exception-mapping>
- </global-exception-mappings>
- </package>
- <package name="core" extends="exception">
- <action name="error"class="com.company.strutstudy.web.action.core.SourceCoreAction" method="error">
- <interceptor-ref name="exception"></interceptor-ref>
- <result name="success">/core/ok.jsp</result>
- </action>
- </package>
- </struts>
源码阅读
- public class ExceptionMappingInterceptor extends AbstractInterceptor {
- protected static final Log log = LogFactory.getLog(ExceptionMappingInterceptor.class);
- protected Log categoryLogger;
- protected boolean logEnabled = false;
- protected String logCategory;
- protected String logLevel;
- ....getset省略
- public String intercept(ActionInvocation invocation) throws Exception {
- String result;
- /*
- * 处理action或拦截器执行的异常
- */
- try {
- result = invocation.invoke();
- } catch (Exception e) {
- //默认为false
- if (logEnabled) {
- handleLogging(e);
- }
- //获取全局或局部与该action相关的exception映射信息
- List exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
- //获取异常发生以后的逻辑视图(resultcode)
- String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
- if (mappedResult != null) {
- result = mappedResult;
- //将异常信息压入栈顶,异常信息可在页面通过ognl进行获取。
- publishException(invocation, new ExceptionHolder(e));
- } else {
- throw e;
- }
- }
- return result;
- }
- /**
- * Handles the logging of the exception.
- *
- * @param e the exception to log.
- */
- protected void handleLogging(Exception e) {
- if (logCategory != null) {
- if (categoryLogger == null) {
- // init category logger
- categoryLogger = LogFactory.getLog(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(Log logger, Exception e) {
- if (logLevel == null) {
- logger.debug(e.getMessage(), e);
- return;
- }
- 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");
- }
- }
- private String findResultFromExceptions(List exceptionMappings, Throwable t) {
- String result = null;
- // Check for specific exception mappings.
- if (exceptionMappings != null) {
- int deepest = Integer.MAX_VALUE;
- for (Iterator iter = exceptionMappings.iterator(); iter.hasNext();) {
- ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) iter.next();
- 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().indexOf(exceptionMapping) != -1) {
- // 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);
- }
- /**
- * Default implementation to handle ExceptionHolder publishing. Pushes given ExceptionHolder on the stack.
- * Subclasses may override this to customize publishing.
- *
- * @param invocation The invocation to publish Exception for.
- * @param exceptionHolder The exceptionHolder wrapping the Exception to publish.
- */
- protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) {
- invocation.getStack().push(exceptionHolder);
- }
- }