struts2的错误处理
来源:互联网 发布:我的世界0.14.1枪械js 编辑:程序博客网 时间:2024/06/06 14:31
Action执行时是被DefaultActionInvocation对象的invoke方法调用
而在Action执行之前又有一批拦截器
拦截器的调用也是被DefalutActionInvocation对象invoke方法调用
最初调用到DefalutActionInvocation对象invoke方法是由ActionProxy的execute方法调用。
来看一下action执行的部分代码。
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {try{ if (!methodCalled) { methodResult = method.invoke(action, EMPTY_OBJECT_ARRAY); } return saveResult(actionConfig, methodResult); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + ""); } catch (InvocationTargetException e) { // We try to return the source exception. Throwable t = e.getTargetException(); }
这里就是捕获了没有这个方法和调用目标异常,没有捕获其他异常,遇到其他异常直接往上抛。
那么我们看看那个方法调用到这个方法
public String invoke() throws Exception { String profileKey = "invoke: "; try { UtilTimerStack.push(profileKey); if (executed) { throw new IllegalStateException("Action has already executed"); } if (interceptors.hasNext()) { final InterceptorMapping interceptor = interceptors.next(); String interceptorMsg = "interceptor: " + interceptor.getName(); UtilTimerStack.push(interceptorMsg); try { resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); } finally { UtilTimerStack.pop(interceptorMsg); } } else { resultCode = invokeActionOnly(); } // this is needed because the result will be executed, then control will return to the Interceptor, which will // return above and flow through again }
这个invoke方法继续往上抛异常,看看谁调用invoke方法呢?proxy.execute()方法
public String execute() throws Exception { ActionContext nestedContext = ActionContext.getContext(); ActionContext.setContext(invocation.getInvocationContext()); String retCode = null; String profileKey = "execute: "; try { UtilTimerStack.push(profileKey); retCode = invocation.invoke(); } finally { if (cleanupContext) { ActionContext.setContext(nestedContext); } UtilTimerStack.pop(profileKey); } return retCode; }
这里继续往上抛,再看看在那个方法里调用了这个execute()方法呢?
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException { Map<String, Object> extraContext = createContextMap(request, response, mapping, context); // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); boolean nullStack = stack == null; if (nullStack) { ActionContext ctx = ActionContext.getContext(); if (ctx != null) { stack = ctx.getValueStack(); } } if (stack != null) { extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack)); } String timerKey = "Handling request from Dispatcher"; try { UtilTimerStack.push(timerKey); String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); Configuration config = configurationManager.getConfiguration(); ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack()); // if the ActionMapping says to go straight to a result, do it! if (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { proxy.execute(); } // If there was a previous value stack then set it back onto the request if (!nullStack) { request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); } } catch (ConfigurationException e) { // WW-2874 Only log error if in devMode if(devMode) { String reqStr = request.getRequestURI(); if (request.getQueryString() != null) { reqStr = reqStr + "?" + request.getQueryString(); } LOG.error("Could not find action or result\n" + reqStr, e); } else { if (LOG.isWarnEnabled()) { LOG.warn("Could not find action or result", e); } } sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e); } catch (Exception e) { sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e); } finally { UtilTimerStack.pop(timerKey); } }
在这个dispatcher的serviceAction方法进行了捕获。并用sendError进行了处理
public void sendError(HttpServletRequest request, HttpServletResponse response, ServletContext ctx, int code, Exception e) { Boolean devModeOverride = FilterDispatcher.getDevModeOverride(); if (devModeOverride != null ? devModeOverride : devMode) { response.setContentType("text/html"); try { FreemarkerManager mgr = getContainer().getInstance(FreemarkerManager.class); freemarker.template.Configuration config = mgr.getConfiguration(ctx); Template template = config.getTemplate("/org/apache/struts2/dispatcher/error.ftl"); List<Throwable> chain = new ArrayList<Throwable>(); Throwable cur = e; chain.add(cur); while ((cur = cur.getCause()) != null) { chain.add(cur); } HashMap<String,Object> data = new HashMap<String,Object>(); data.put("exception", e); data.put("unknown", Location.UNKNOWN); data.put("chain", chain); data.put("locator", new Locator()); template.process(data, response.getWriter()); response.getWriter().close(); } catch (Exception exp) { try { response.sendError(code, "Unable to show problem report: " + exp); } catch (IOException ex) { // we're already sending an error, not much else we can do if more stuff breaks } } } else { try { // WW-1977: Only put errors in the request when code is a 500 error if (code == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) { // send a http error response to use the servlet defined error handler // make the exception availible to the web.xml defined error page request.setAttribute("javax.servlet.error.exception", e); // for compatibility request.setAttribute("javax.servlet.jsp.jspException", e); } // send the error response response.sendError(code, e.getMessage()); } catch (IOException e1) { // we're already sending an error, not much else we can do if more stuff breaks } } }
这里获取错误信息模版,将信息放入到模版中进行输出到浏览器
那么我们如何修改错误信息呢?这里我们不必修改,我们要利用好struts2提供的拦截器,这里有一个exception拦截器
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
在默认拦截器栈的栈顶。
那么我们来看看exception拦截器的intercept方法
@Override public String intercept(ActionInvocation invocation) throws Exception { String result; try { result = invocation.invoke(); } catch (Exception e) { if (isLogEnabled()) { handleLogging(e); } List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings(); ExceptionMappingConfig mappingConfig = this.findMappingFromExceptions(exceptionMappings, e); if (mappingConfig != null && mappingConfig.getResult()!=null) { Map parameterMap = mappingConfig.getParams(); // create a mutable HashMap since some interceptors will remove parameters, and parameterMap is immutable invocation.getInvocationContext().setParameters(new HashMap<String, Object>(parameterMap)); result = mappingConfig.getResult(); publishException(invocation, new ExceptionHolder(e)); } else { throw e; } } return result; }
执行invocation.invoke();时对异常信息进行了捕获捕获好异常信息就执行下面的代码,去找配置文件中的错误exception-error节点,获取result名称,然后执行publishException()方法
protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) { invocation.getStack().push(exceptionHolder); }
这里将错误信息放入栈顶,然后params过滤器就会错误信息,set到action的成员变量中。
解决方案 :
<package name="struts-global" namespace="/" extends="struts-default"> <global-results> <result name="errHandler" type="chain"> <param name="actionName">errorProcessor</param> </result> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="errHandler" /> </global-exception-mappings> <action name="errorProcessor" class="ErrorProcess"> <result>error.jsp</result> </action> </package>
- struts2的错误处理
- struts2的统一错误处理
- 处理struts2自带的错误提示
- Struts2 错误处理
- struts2 异常处理 404错误
- struts2系列学习笔记(8)---------------类型转换的错误处理
- 错误处理——struts2.xml的result里传多个参数
- struts2遇见的错误
- struts2的常见错误
- struts2表单错误处理和数据验证
- Struts2的处理流程
- struts2的处理流程
- Struts2的处理流程
- Struts2的处理流程
- struts2的异常处理
- struts2的处理流程
- struts2的处理流程
- Struts2的异常处理
- Android程序获取手机IMU数据
- uva1635(唯一分解定理,杨辉三角二项式递推公式)
- 性能优化
- J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP
- javascript模块化编程
- struts2的错误处理
- Struts1进阶(四)
- 求逆元
- postgresql Connection to database failed: FATAL: no pg_hba.conf entry for host "10.129.195.161", us
- 每周一书-《模糊测试-强制发掘安全漏洞的利器》
- SVN命令总结
- 微信开放平台apk的应用签名的获取
- windows7开启Windows Media Player Network Sharing Service 失败的解决办法
- Java实现排序算法——归并排序