Struts2执行流程
来源:互联网 发布:恒扬数据股份有限公司 编辑:程序博客网 时间:2024/06/06 02:09
ActionMapping:在一个web应用中,每个资源都必须通过URI来进行引用。 资源包括HTML页面,JSP页面,和定制动作。为了给定制动作一个 URI或者说路径,Struts框架提供了一个 ActionMapping对象保存当前Action状态的一个类,struts.xml文件中的一个<action>标签,通常要指定name和namespace
ActionMapper:ActionMapper可能会返回一个ActionMapping,如果返回一个ActionMapping对象的话,说明是一个struts请i去,如果返回一个null,责说明没有一个Action和它相匹配,是一个非struts请求
ActionProxy:通过webwork和xwork交互关系图可以看出,它是action和xwork中间的一层。 正因为ActionProxy的存在导致Action调用更加简洁。
ActionInvocation:一个ActionInvocation包含了一系列的拦截器,通过反复的进行invoke()方法,执行action,执行相应结果。
Struts2运行图解
核心控制器2.1.3版本之后,struts的filterDispatcher核心控制器变成了StrutsPrepareAndExecuteFilte,如图:
struts2 运行流程
- 请求发给StrutsPrepareAndExecuteFilter
- StrutsPrepareAndExecuteFilter询问ActionMapper;该请求是否是一个Struts2请求(即是否返回一个非空的ActionMapping对象)
- 若ActionMapping认为该请求是一个Struts2请求,啧StrutsPrepareAndExecuteFilter把请求处理交给ActionProxy。
- ActionProxy通过Configuration Manager询问框架的配置文件(即struts.xml),确定需要调用的Action类及action方法。
- ActionProxy创建一个ActionInvocation的实例,并进行初始化
- ActionInvocation实例在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
- Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。调用结果的execute方法,渲染结果。在渲染的过程中可能使用struts2框架中的标签。
- 执行各个拦截器invocation.invoke()之后的代码
- 把结果发送给客户端
源码
- 请求发给StrutsPrePareAndExecuteFilter类的doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; try { prepare.setEncodingAndLocale(request, response); prepare.createActionContext(request, response); prepare.assignDispatcherToThread(); if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) { chain.doFilter(request, response); } else { request = prepare.wrapRequest(request); //获取一个ActionMapping对象,如果对象返回空,说明该请求是一个非Struts请求 ActionMapping mapping = prepare.findActionMapping(request, response, true); if (mapping == null) { boolean handled = execute.executeStaticResourceRequest(request, response); if (!handled) { chain.doFilter(request, response); } } else { execute.executeAction(request, response, mapping); } } } finally { prepare.cleanupRequest(request); }}15行,进入findActionMapping方法。获取了一个ActionMapping对象,如果对象是空,是一个非Struts请求,紧接着chain.dofilter(request,response);
21行,如果ActionMapping不为空,那么执行executeAction方法
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) { if (handleException || devMode) { sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e); } else { throw new ServletException(e); } } finally { UtilTimerStack.pop(timerKey); }}27行,createActionProxy创建ActionProxy,
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) { ActionInvocation inv = new DefaultActionInvocation(extraContext, true); container.inject(inv); return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);}5行
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) { StrutsActionProxy proxy = new StrutsActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); container.inject(proxy); proxy.prepare(); return proxy;}
5行,创建好了一个ActionProxy对象并返回,里面包含了className还有methodName(我的是默认的execute方法)
37行,执行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; }11行,invocation.invoke方法
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 if (!executed) { if (preResultListeners != null) { for (Object preResultListener : preResultListeners) { PreResultListener listener = (PreResultListener) preResultListener; String _profileKey = "preResultListener: "; try { UtilTimerStack.push(_profileKey); listener.beforeResult(this, resultCode); } finally { UtilTimerStack.pop(_profileKey); } } } // now execute the result, if we're supposed to if (proxy.getExecuteResult()) { executeResult(); } executed = true; } return resultCode; } finally { UtilTimerStack.pop(profileKey); }}10行,判断是否还有下一个拦截器,可以来看一下里面拦截器的集合
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack>
没有配置拦截器栈,默认为defaultStack拦截器栈,看到第一个和最后一个相匹配
21行,执行目标方法;
public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {Object action = actionInvocation.getAction();String methodName = actionInvocation.getProxy().getMethod();if (methodName == null) {// if null returns (possible according to the docs), use the default execute methodName = DEFAULT_INVOCATION_METHODNAME;}Method method = getPrefixedMethod(prefixes, methodName, action);if (method != null) {method.invoke(action, new Object[0]);}}44行,执行result
private void executeResult() throws Exception { result = createResult(); String timerKey = "executeResult: " + getResultCode(); try { UtilTimerStack.push(timerKey); if (result != null) { result.execute(this); } else if (resultCode != null && !Action.NONE.equals(resultCode)) { throw new ConfigurationException("No result defined for action " + getAction().getClass().getName() + " and result " + getResultCode(), proxy.getConfig()); } else { if (LOG.isDebugEnabled()) { LOG.debug("No result returned for action " + getAction().getClass().getName() + " at " + proxy.getConfig().getLocation()); } } } finally { UtilTimerStack.pop(timerKey); } }8行, 执行目标方法
public void execute(ActionInvocation invocation) throws Exception { lastFinalLocation = conditionalParse(location, invocation); doExecute(lastFinalLocation, invocation); }继续往下执行
public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { if (LOG.isDebugEnabled()) { LOG.debug("Forwarding to location " + finalLocation); } PageContext pageContext = ServletActionContext.getPageContext(); if (pageContext != null) { pageContext.include(finalLocation); } else { HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation); //add parameters passed on the location to #parameters // see WW-2120 if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) { String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1); Map<String, Object> parameters = getParameters(invocation); Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true); if (queryParams != null && !queryParams.isEmpty()) parameters.putAll(queryParams); } // if the view doesn't exist, let's do a 404 if (dispatcher == null) { response.sendError(404, "result '" + finalLocation + "' not found"); return; } //if we are inside an action tag, we always need to do an include Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE); // If we're included, then include the view // Otherwise do forward // This allow the page to, for example, set content type if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) { request.setAttribute("struts.view_uri", finalLocation); request.setAttribute("struts.request_uri", request.getRequestURI()); dispatcher.forward(request, response); } else { dispatcher.include(request, response); } } }41行,将页面进行转发,然后再执行倒序执行各个拦截器。把结果发送给客户端。
0 0
- Struts2执行流程
- struts2执行流程分析
- struts2的执行流程
- struts2的执行流程
- struts2执行流程
- struts2执行流程
- struts2执行流程
- Struts2执行流程
- struts2执行流程
- struts2的执行流程
- Struts2执行流程
- Struts2框架执行流程
- struts2的执行流程
- struts2执行流程
- Struts2的执行流程
- struts2的执行流程
- Struts2执行基本流程
- Struts2的执行流程
- pcl 点投影到某个平面
- [UVA]572 oil disposition
- 仿小红书根据图片高度自适应viewpager高度轮播图
- Java三大主流框架概述
- oracle dba 一天
- Struts2执行流程
- Linux文件系统简介
- TCP/IP协议族——IP分组的交付和转发
- Java I/O系统
- .git目录删不掉
- Android mmm单独编译模块 错误提示 APPS/Settings_intermediates/classes-full-debug.jar] Error 41
- Android常用的图片加载库
- 我的收藏
- Android面试题