- 浏览: 3479 次
- 性别:
最新评论
struts2的执行过程
1.首先进入StrutsPrepareAndExecuteFilter这个filter,执行doFilter方法
2.做完所有准备工作之后,初始化后的ExecuteOperations执行executeAction
3.ExecuteOperations实际上是个代理类,内部调用dispatcher的serviceAction方法
在这个方法中首先拿到当前线程(ActionContext维护一个ThreadLocal),并且得到valueStack,接着得到映射中的信息(namespace,method,name),根据这些信息创建代理对象
4.以下是具体创建代理对象和ActionInvocation的过程
DefaultActionProxyFactory(createActionProxy())
4.1.代理对象的准备工作 DefaultActionProxy(prepare())
4.2.proxy会初始化actionInvocation,其中包括上下文环境,值栈,以及拦截器
5.当所有的准备工作都做好之后,回到ExecuteOperations中,执行proxy.execute()方法,实际执行的是StrutsActionProxy的execute()方法
6.此时actionInvocation开始执行。
7.1.所有拦截器执行完之后调用invokeActionOnly
8.得到result对象并跳转到相应页面
根据字符串跳转到相应的页面 StrutsResultSupport(execute())
注:本文仅涉及struts2的执行过程,具体的细节和详细的步骤暂不讨论!
1.首先进入StrutsPrepareAndExecuteFilter这个filter,执行doFilter方法
public void doFilter(ServletRequest req,ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; try { //设置Encoding和Locale prepare.setEncodingAndLocale(request, response); prepare.createActionContext(request, response); //将dispatcher绑定到当前线程 prepare.assignDispatcherToThread(); if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) { chain.doFilter(request, response); } else { request = prepare.wrapRequest(request); //查找配置中是否有映射 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); } }
2.做完所有准备工作之后,初始化后的ExecuteOperations执行executeAction
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException { dispatcher.serviceAction(request, response, servletContext, mapping);}
3.ExecuteOperations实际上是个代理类,内部调用dispatcher的serviceAction方法
在这个方法中首先拿到当前线程(ActionContext维护一个ThreadLocal),并且得到valueStack,接着得到映射中的信息(namespace,method,name),根据这些信息创建代理对象
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException { Map<String, Object> extraContext = createContextMap(request, response, mapping, context); ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); boolean nullStack = stack == null; if (nullStack) { //得到当前线程的ActionContext ActionContext ctx = ActionContext.getContext(); if (ctx != null) { //得到ValueStack 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 (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { //开始执行 proxy.execute(); } if (!nullStack) { request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); } } catch (ConfigurationException e) { 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); } }
4.以下是具体创建代理对象和ActionInvocation的过程
DefaultActionProxyFactory(createActionProxy())
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) { //创建ActionInvocation ActionInvocation inv = new DefaultActionInvocation(extraContext, true); container.inject(inv); return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); } public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) { //创建proxy StrutsActionProxy proxy = new StrutsActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); container.inject(proxy); proxy.prepare(); return proxy; }
4.1.代理对象的准备工作 DefaultActionProxy(prepare())
protected void prepare() { String profileKey = "create DefaultActionProxy: "; try { UtilTimerStack.push(profileKey); config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName); if (config == null && unknownHandlerManager.hasUnknownHandlers()) { config = unknownHandlerManager.handleUnknownAction(namespace, actionName); } if (config == null) { throw new ConfigurationException(getErrorMessage()); } resolveMethod(); if (!config.isAllowedMethod(method)) { throw new ConfigurationException("Invalid method: " + method + " for action " + actionName); } //actionInvocation的初始化 invocation.init(this); } finally { UtilTimerStack.pop(profileKey); } }
4.2.proxy会初始化actionInvocation,其中包括上下文环境,值栈,以及拦截器
DefaultActionInvocation(init()) public void init(ActionProxy proxy) { this.proxy = proxy; Map<String, Object> contextMap = createContextMap(); ActionContext actionContext = ActionContext.getContext(); if (actionContext != null) { //将actionInvocation放入上下文环境中 actionContext.setActionInvocation(this); } createAction(contextMap); if (pushAction) { //将action置于valueStack中 stack.push(action); contextMap.put("action", action); } //创建invocationContext上下文 invocationContext = new ActionContext(contextMap); invocationContext.setName(proxy.getActionName()); //初始化拦截器 List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors()); interceptors = interceptorList.iterator(); }
5.当所有的准备工作都做好之后,回到ExecuteOperations中,执行proxy.execute()方法,实际执行的是StrutsActionProxy的execute()方法
public String execute() throws Exception { ActionContext previous = ActionContext.getContext(); ActionContext.setContext(invocation.getInvocationContext()); try { //生成的actionInvocation开始执行 return invocation.invoke(); } finally { if (cleanupContext) ActionContext.setContext(previous); } }
6.此时actionInvocation开始执行。
public String invoke() throws Exception { String profileKey = "invoke: "; try { UtilTimerStack.push(profileKey); if (executed) { throw new IllegalStateException("Action has already executed"); } //依次执行每个拦截器 actionInvocation相当于一个中转站,每个拦截器执 //行完,又返回actionInvocation执行 if (interceptors.hasNext()) { final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next(); String interceptorMsg = "interceptor: " + interceptor.getName(); UtilTimerStack.push(interceptorMsg); try { resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); } finally { UtilTimerStack.pop(interceptorMsg); } } else { //所有拦截器执行完之后调用invokeActionOnly方法 resultCode = invokeActionOnly(); } 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); } } } if (proxy.getExecuteResult()) { //根据得到的字符串跳转到对应的页面 executeResult(); } executed = true; } return resultCode; } finally { UtilTimerStack.pop(profileKey); } }
7.1.所有拦截器执行完之后调用invokeActionOnly
public String invokeActionOnly() throws Exception { return invokeAction(getAction(), proxy.getConfig()); } protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception { //得到action类中调用方法的名称 String methodName = proxy.getMethod(); if (LOG.isDebugEnabled()) { LOG.debug("Executing action method = " + actionConfig.getMethodName()); } String timerKey = "invokeAction: " + proxy.getActionName(); try { UtilTimerStack.push(timerKey); boolean methodCalled = false; Object methodResult = null; Method method = null; try { method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY); } catch (NoSuchMethodException e) { try { String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1); //构成Method对象 method = getAction().getClass().getMethod(altMethodName, EMPTY_CLASS_ARRAY); } catch (NoSuchMethodException e1) { if (unknownHandlerManager.hasUnknownHandlers()) { try { methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName); methodCalled = true; } catch (NoSuchMethodException e2) { throw e; } } else { throw e; } } } 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) { Throwable t = e.getTargetException(); if (actionEventListener != null) { String result = actionEventListener.handleException(t, getStack()); if (result != null) { return result; } } if (t instanceof Exception) { throw (Exception) t; } else { throw e; } } finally { UtilTimerStack.pop(timerKey); } } //保存后面要用到的字符串,否则返回 protected String saveResult(ActionConfig actionConfig, Object methodResult) { if (methodResult instanceof Result) { this.explicitResult = (Result) methodResult; container.inject(explicitResult); return null; } else { return (String) methodResult; } }
8.得到result对象并跳转到相应页面
private void executeResult() throws Exception { result = createResult(); String timerKey = "executeResult: " + getResultCode(); try { UtilTimerStack.push(timerKey); if (result != null) { //封装的result执行 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); } }
根据字符串跳转到相应的页面 StrutsResultSupport(execute())
public void execute(ActionInvocation invocation) throws Exception { lastFinalLocation = conditionalParse(location, invocation); doExecute(lastFinalLocation, invocation); } ServletDispatcherResult(doExecute()) 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); 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 (dispatcher == null) { response.sendError(404, "result '" + finalLocation + "' not found"); return; } Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE); 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); } } }
注:本文仅涉及struts2的执行过程,具体的细节和详细的步骤暂不讨论!
相关推荐
Struts1工作原理浅析
Struts1工作原理浅析【转】
Struts1工作原理浅析 1.引入struts1 2.struts1工作原理 3.struts1工作机制 4.struts1的安装于基本配置 5.ActionServlet
Struts2执行流程 1. web.xml 部署描述符 2. FilterDispatcher 实现StrutsStatics, Filter接口 (1)Filter:一个filter是一个对象用于执行过滤任务为每个请求资源(一个servlet或静态内容),或响应一个资源,或两者.过滤...
Struts2漏洞检查工具,可快速检测struts命令执行漏洞,支持批量导入验证,存在可利用的漏洞后,可远程执行命令及文件上传等操作。方便管理人员了解其危害。
Struts2远程命令执行漏洞解析 漏洞解析 远程命令 Struts2
struts1.2的执行原理的总结以及关于struts MVC原理的总结
struts2执行顺序,清楚描述从处理请求到返回response的整个流程
首先客户端发送HttServletErquest的请求,这个请求经过一系列的过滤器链(Filter),这里是有顺序的,首先经过ActionContext CleanUp,然后再经过其他过滤器(Othter Filters、SiteMesh等),最后再到...
struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别...
这张流程图 深刻的描述了 struts2的执行流程 帮助了解Struts2
struts2工作原理、请求响应流程。。。。。。。。。。。。。。。
Struts2 工作原理 Struts2框架 有图
Struts 2框架本身大致可以分为3个部分:核心控制器FilterDispatcher、业务控制器Action和用户实现的企业业务逻辑组件。 核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。...
Struts2远程代码执行漏洞分析(S2-013)1
struts1工作原理 struts2工作原理 struts1和struts2比较 spring mvc工作原理 struts和spring mvc比较
2.如果您使用基于Jakarta插件,请升级到Apache Struts 2.3.32或2.5.10.1版本。(强烈推荐) 3.升级到2.3.32所用到的jar包: freemarker-2.3.22.jar ognl-3.0.19.jar struts2-convention-plugin-2.3.32.jar struts2-...
《Struts2技术内幕:深入解析Struts2架构设计与实现原理》以Struts2的源代码为依托,通过对Struts2的源代码的全面剖析深入探讨了Struts2的架构设计、实现原理、设计理念与设计哲学,对从宏观上和微观上去了解Struts2...
struts的执行过程详细解说。 使用举例的方式进行了说明。