- 浏览: 841863 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
renzhengzhi:
请教一下楼主,公有云和私有云的开发,具体要做哪些工作呢?我拿到 ...
4,云的4 种模式 -
SangBillLee:
我用了solr5.5,用SolrQuery查询,没法高亮,不知 ...
solr5.x快速入门 -
lw900925:
这翻译读起来真是别扭。
solr in action翻译-第一章1.1 -
springjpa_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring MVC性能提升 -
h416373073:
正遇到了此问题不知如何解决, 多谢分享
solr错误
ActionMapping创建完成,就开始执行exece方法。
if (mapping == null) { boolean handled = execute.executeStaticResourceRequest(request, response); if (!handled) { chain.doFilter(request, response); } } else { execute.executeAction(request, response, mapping); }
因为mapping创建了,所以一定不为空,一定执行execut方法。
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException { dispatcher.serviceAction(request, response, servletContext, mapping); }
核心还是在Dispatcher,
代码如下:
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); } }
首先是创建一个额外的 actionContext
Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
然后获取ValueStack
ValueStack在处理request的时候放入的,所以现在可以直接取出来。
所以执行下面的代码。
if (stack != null) { extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack)); }
额外的actionContext里面添加一个ValueStack
public ValueStack createValueStack(ValueStack stack) { ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, allowStaticMethodAccess); container.inject(result); stack.getContext().put(ActionContext.CONTAINER, container); return result; }
然后获取action 相关的信息,通过actionMapping获取。
String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod();
ActionProxy很重要。
ActionProxy为Action的代理对象 。ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类。
ActionProxy创建一个ActionInvocation的实例。ActionInvocation在ActionProxy层之下,它表示了
Action的执行状态,或者说它控制的Action的执行步骤。它持有Action实例和所有的Interceptor。
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false);
实现的代码如下:
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); }
创建一个 ActionInvocation,默认的实现是Default.
ActionInvocation代表一个action的执行状态。
定义如下:
public interface ActionInvocation extends Serializable { /** * Get the Action associated with this ActionInvocation. * * @return the Action */ Object getAction(); boolean isExecuted(); ActionContext getInvocationContext(); /** * Get the ActionProxy holding this ActionInvocation. * * @return the ActionProxy. */ ActionProxy getProxy(); Result getResult() throws Exception; /** * Gets the result code returned from this ActionInvocation. * * @return the result code */ String getResultCode(); /** * Invokes the next step in processing this ActionInvocation. * <p/> * If there are more Interceptors, this will call the next one. If Interceptors choose not to short-circuit * ActionInvocation processing and return their own return code, they will call invoke() to allow the next Interceptor * to execute. If there are no more Interceptors to be applied, the Action is executed. * If the {@link ActionProxy#getExecuteResult()} method returns <tt>true</tt>, the Result is also executed. * * @throws Exception can be thrown. * @return the return code. */ String invoke() throws Exception; ....部分代码 }
需要说明的是 ActionProxy getProxy();
功能是获取当前ActionInvocation的action代理。
最终的action不是具体实现,而是通过ActionProxy代理创建完成。
public interface ActionProxy { /** * Gets the Action instance for this Proxy. * * @return the Action instance */ Object getAction(); /** * Gets the alias name this ActionProxy is mapped to. * * @return the alias name */ String getActionName(); /** * Gets the ActionConfig this ActionProxy is built from. * * @return the ActionConfig */ ActionConfig getConfig(); /** * Sets whether this ActionProxy should also execute the Result after executing the Action. * * @param executeResult <tt>true</tt> to also execute the Result. */ void setExecuteResult(boolean executeResult); /** * Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed. * * @return the status */ boolean getExecuteResult(); /** * Gets the ActionInvocation associated with this ActionProxy. * * @return the ActionInvocation */ ActionInvocation getInvocation(); /** * Gets the namespace the ActionConfig for this ActionProxy is mapped to. * * @return the namespace */ String getNamespace(); /** * Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext * ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal. * * @return the result code returned from executing the ActionInvocation * @throws Exception can be thrown. * @see ActionInvocation */ String execute() throws Exception; /** * Gets the method name to execute, or <tt>null</tt> if no method has been specified (meaning <code>execute</code> will be invoked). * * @return the method to execute */ String getMethod(); /** * Gets status of the method value's initialization. * * @return true if the method returned by getMethod() is not a default initializer value. */ boolean isMethodSpecified(); }
ActionProxy是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。
DefaultActionInvocation()->init()->createAction()。
最后通过调用ActionProxy.exute()-->ActionInvocation.invoke()-->Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction()
这里的步骤是先由ActionProxyFactory创建ActionInvocation和ActionProxy.
继续回到执行代码中
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) { DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); container.inject(proxy); proxy.prepare(); return proxy; }
ActionInvocation里的ActionProxy是在这里创建的默认提供的DefaultActionProxy
protected DefaultActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) { this.invocation = inv; this.cleanupContext = cleanupContext; if (LOG.isDebugEnabled()) { LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName); } this.actionName = StringEscapeUtils.escapeHtml4(actionName); this.namespace = namespace; this.executeResult = executeResult; this.method = StringEscapeUtils.escapeEcmaScript(StringEscapeUtils.escapeHtml4(methodName)); }
然后调用代理的预处理工作
proxy.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); } invocation.init(this); } finally { UtilTimerStack.pop(profileKey); } }
首先是获取ActionConfig
config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName);
public synchronized ActionConfig getActionConfig(String namespace, String name) { ActionConfig config = findActionConfigInNamespace(namespace, name); // try wildcarded namespaces if (config == null) { NamespaceMatch match = namespaceMatcher.match(namespace); if (match != null) { config = findActionConfigInNamespace(match.getPattern(), name); // If config found, place all the matches found in the namespace processing in the action's parameters if (config != null) { config = new ActionConfig.Builder(config) .addParams(match.getVariables()) .build(); } } } // fail over to empty namespace if ((config == null) && (namespace != null) && (!"".equals(namespace.trim()))) { config = findActionConfigInNamespace("", name); } return config; }
ActionConfig findActionConfigInNamespace(String namespace, String name) { ActionConfig config = null; if (namespace == null) { namespace = ""; } Map<String, ActionConfig> actions = namespaceActionConfigs.get(namespace); if (actions != null) { config = actions.get(name); // Check wildcards if (config == null) { config = namespaceActionConfigMatchers.get(namespace).match(name); // fail over to default action if (config == null) { String defaultActionRef = namespaceConfigs.get(namespace); if (defaultActionRef != null) { config = actions.get(defaultActionRef); } } } } return config; }
如果config创建失败,抛出异常
下面是resolveMethod的实现代码。
private void resolveMethod() { // if the method is set to null, use the one from the configuration // if the one from the configuration is also null, use "execute" if (StringUtils.isEmpty(this.method)) { this.method = config.getMethodName(); if (StringUtils.isEmpty(this.method)) { this.method = ActionConfig.DEFAULT_METHOD; } methodSpecified = false; } }
然后是invocation的初始化。
invocation.init(this);
public void init(ActionProxy proxy) { this.proxy = proxy; Map<String, Object> contextMap = createContextMap(); // Setting this so that other classes, like object factories, can use the ActionProxy and other // contextual information to operate ActionContext actionContext = ActionContext.getContext(); if (actionContext != null) { actionContext.setActionInvocation(this); } createAction(contextMap); if (pushAction) { stack.push(action); contextMap.put("action", action); } invocationContext = new ActionContext(contextMap); invocationContext.setName(proxy.getActionName()); // get a new List so we don't get problems with the iterator if someone changes the list List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors()); interceptors = interceptorList.iterator(); }
interceptor初始化的时候先创建一个createContextMap
contextmap是通过刚开始的时候额外的 contextmap提供的。
protected Map<String, Object> createContextMap() { Map<String, Object> contextMap; if ((extraContext != null) && (extraContext.containsKey(ActionContext.VALUE_STACK))) { // In case the ValueStack was passed in stack = (ValueStack) extraContext.get(ActionContext.VALUE_STACK); if (stack == null) { throw new IllegalStateException("There was a null Stack set into the extra params."); } contextMap = stack.getContext(); } else { // create the value stack // this also adds the ValueStack to its context stack = valueStackFactory.createValueStack(); // create the action context contextMap = stack.getContext(); } // put extraContext in if (extraContext != null) { contextMap.putAll(extraContext); } //put this DefaultActionInvocation into the context map contextMap.put(ActionContext.ACTION_INVOCATION, this); contextMap.put(ActionContext.CONTAINER, container); return contextMap; }
然后把当前的actioninvocation放入context 中,然后返回
contextMap.put(ActionContext.ACTION_INVOCATION, this); contextMap.put(ActionContext.CONTAINER, container);
然后讲当前的actioninvocation 放入actioncontext中
ActionContext actionContext = ActionContext.getContext(); if (actionContext != null) { actionContext.setActionInvocation(this); }
然后创建action
createAction(contextMap);
具体代码如下
protected void createAction(Map<String, Object> contextMap) { // load action String timerKey = "actionCreate: " + proxy.getActionName(); try { UtilTimerStack.push(timerKey); action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap); } catch (InstantiationException e) { throw new XWorkException("Unable to intantiate Action!", e, proxy.getConfig()); } catch (IllegalAccessException e) { throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig()); } catch (Exception e) { String gripe = ""; if (proxy == null) { gripe = "Whoa! No ActionProxy instance found in current ActionInvocation. This is bad ... very bad"; } else if (proxy.getConfig() == null) { gripe = "Sheesh. Where'd that ActionProxy get to? I can't find it in the current ActionInvocation!?"; } else if (proxy.getConfig().getClassName() == null) { gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; } else { gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ", defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; } gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]"); throw new XWorkException(gripe, e, proxy.getConfig()); } finally { UtilTimerStack.pop(timerKey); } if (actionEventListener != null) { action = actionEventListener.prepare(action, stack); } }
action通过objectFactory创建
action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
具体的代码如下:
public Object buildBean(String className, Map<String, Object> extraContext, boolean injectInternal) throws Exception { Class clazz = getClassInstance(className); Object obj = buildBean(clazz, extraContext); if (injectInternal) { injectInternalBeans(obj); } return obj; }
public Class getClassInstance(String className) throws ClassNotFoundException { if (ccl != null) { return ccl.loadClass(className); } return ClassLoaderUtil.loadClass(className, this.getClass()); }
通过class类加载器创建
然后讲当前的action注入容器中。
if (injectInternal) {
injectInternalBeans(obj);
}
struts2中的ObjectFactory到底是什么呢?
struts2包装了ObjectFactory,自成了一个StrutsObjectFactory,他是继承自ObjectFactory的一个类,因此struts2默认产生action的类就不使用xwork的ObjectFactory了,而是使用StrutsObjectFactory。
struts2的插件struts2-spring-plugin-2.1.8.1.jar,又做了一个对象工厂,StrutsSpringObjectFactory,它的父类是xwork的SpringObjectFactory,最原始的父类也是ObjectFactory,我想xwork提供SpringObjectFactory的目的就是让实现这继承这个类,实现spring工厂。
于是struts2中也就是说有3个 对象工厂,
org.apache.struts2.spring.StrutsSpringObjectFactory(struts2的spring插件提供)
org.apache.struts2.impl.StrutsObjectFactory(struts2自带)
com.opensymphony.xwork2.ObjectFactory(xwork自带)。
他们都可以用于产生action。
在xwork中默认使用ObjectFactory,在struts2中默认使用StrutsObjectFactory。使用struts2的spring插件的时候默认使用StrutsSpringObjectFactory,这些都是自动的,其中前两个都是struts2的内容。都是由
<constant name="struts.objectFactory" value="spring" />
来控制,这里的value,就是
<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
在这bean里面定义的是哪个工厂,struts2就用哪个工厂。
但是不管是哪个工厂最终这些都是有xwork控制完成的。
我们可以查看
xwork的DefaultActionInvocation类的createAction(Map<String, Object> contextMap)方法。这个方法就是工厂对象产生action的方法。我们可以看到这个类中的定义的对象工厂是
protected ObjectFactory objectFactory;
然后没有实例化,而是通过xwork的注入机制注入
@Inject
public void setObjectFactory(ObjectFactory fac) {
this.objectFactory = fac;
}
这个地方用的是最原始的ObjectFactory工厂,但是通过我们的配置为什么能变成StrutsSpringObjectFactory或StrutsObjectFactory呢?
这个还没有看完,单我想是多态造成的,因为ObjectFactory是StrutsSpringObjectFactory和StrutsObjectFactory的父类,可以用任意的子类实例化父类。
我想是通过解读
<constant name="struts.objectFactory" value="xia" />
这个配置,来确定注入 objectFactory的那个子类。
我们可以在DefaultActionInvocation的createAction方法打印一下objectFactory
会发现,使用不同的对象工厂,那么这里会打印相应的工厂。绝对不只是ObjectFactory这个父类
List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors()); interceptors = interceptorList.iterator();最终是通过ActionConfig创建并返回的
// 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); }然后执行execute方法
public String execute() throws Exception { ActionContext previous = ActionContext.getContext(); ActionContext.setContext(invocation.getInvocationContext()); try { // This is for the new API: // return RequestContextImpl.callInContext(invocation, new Callable<String>() { // public String call() throws Exception { // return invocation.invoke(); // } // }); return invocation.invoke(); } finally { if (cleanupContext) ActionContext.setContext(previous); } }return 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 = (InterceptorMapping) 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); } }核心的是
public abstract class AbstractInterceptor implements Interceptor { /** * Does nothing */ public void init() { } /** * Does nothing */ public void destroy() { } /** * Override to handle interception */ public abstract String intercept(ActionInvocation invocation) throws Exception; }
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 { resultCode = invokeActionOnly(); }
每个拦截器中的代码的执行顺序,在Action之前,拦截器的执行顺序与堆栈中定义的一致;而在Action和Result之后,拦截器的执行顺序与堆栈中定义的顺序相反。
Interceptor拦截类型
从上面的分析,我们知道,整个拦截器的核心部分是invocation.invoke()这个函数的调用位置。事实上,我们也正式根据这句代码的调用位置,来进行拦截类型的区分的。在Struts2中,Interceptor的拦截类型,分成以下三类:
1. before
before拦截,是指在拦截器中定义的代码,它们存在于invocation.invoke()代码执行之前。这些代码,将依照拦截器定义的顺序,顺序执行。
2. after
after拦截,是指在拦截器中定义的代码,它们存在于invocation.invoke()代码执行之后。这些代码,将一招拦截器定义的顺序,逆序执行。
PreResultListener
有的时候,before拦截和after拦截对我们来说是不够的,因为我们需要在Action执行完之后,但是还没有回到视图层之前,做一些事情。Struts2同样支持这样的拦截,这种拦截方式,是通过在拦截器中注册一个PreResultListener的接口来实现的。
如:在拦截器中使用如下代码,其中MyPreResultListener实现了PreResultListener 接口并在beforeResult方法中做了一些事情然后在拦截器类中加入action.addPreResultListener(new MyPreResultListener());
从源码中,我们可以看到,我们之前提到的Struts2的Action层的4个不同的层次,在这个方法中都有体现,他们分别是:拦截器(Interceptor)、Action、PreResultListener和Result。在这个方法中,保证了这些层次的有序调用和执行
发表评论
-
struts源码之九
2012-12-16 16:11 1870strtsu2完成request的封装后,就创建ActionM ... -
struts源码之八
2012-12-16 15:04 1541创建完成ActionContext后,strtus2将当Dis ... -
struts源码之七
2012-12-16 14:37 1162struts2一个请求的处理过程分析 strtus2的 ... -
Struts2_ValueStack,OGNL详解
2012-12-15 22:24 10035引言: 闲话不多说,最近项目结束,天天泡在CSDN论坛上,不乏 ... -
struts源码之六
2012-12-15 22:05 1066struts2请求核心流程图如下: 粗略的化了一下 ... -
struts源码之五
2012-12-15 20:35 965struts2请求流程一个简图。如下图所示 只画出了前半部分 ... -
struts源码之四
2012-12-14 23:01 1058初始化Dispatcher完成, init.init ... -
struts源码之三
2012-12-14 22:36 1237在init初始化方法中我们看到这样一句 InitOpera ... -
struts源码之二
2012-12-14 22:03 1037struts2初始化静态流程如下: 详细描述 ... -
struts源码之一
2012-12-14 21:59 1366Struts2架构图 Struts2部分类介绍 ... -
Struts2中,radio标签的默认选中问题
2011-10-28 08:59 1068在Struts2中,radio标签可以使用一个list来输 ... -
struts2的itrator循环使用
2011-09-21 11:20 1086下拉框的输出 <s:iterator value=&qu ... -
Struts2通用的Action配置
2010-09-02 17:15 1650<action name="*_*" ... -
struts2的Result配置
2010-08-12 15:38 1265在struts-default.xml <resu ... -
Struts2概述
2010-07-23 15:29 1130Struts2其实并不是一个陌 ...
相关推荐
在Eclipse中关联Struts2.1.8源码,可以帮助开发者更好地理解和调试代码。步骤包括: - 下载Struts2.1.8的源码包。 - 在Eclipse中,右键点击项目,选择"Build Path" -> "Configure Build Path" -> "Libraries" -> ...
struts源码包,解压后会有一个src文件夹,此文件夹下的就是struts的源码。
孙卫琴 struts 源码 孙卫琴 struts 源码 孙卫琴 struts 源码
最新版的Struts2源码可以从GitHub的Apache官方仓库获取,这为我们提供了深入理解其内部工作原理和定制功能提供了可能。 Struts2的核心特性包括: 1. **Action与结果**:在Struts2中,业务逻辑处理主要由Action类...
通过深入研究Struts源码,我们可以了解到框架如何处理请求、执行业务逻辑以及如何将数据呈现给用户。这对于提升Java Web开发技能,理解MVC模式,以及进行性能优化都有着极大的帮助。同时,熟悉源码也有助于开发者更...
这篇博文“Struts2源码解读”深入剖析了Struts2的核心机制,帮助开发者更好地理解和利用这个框架。源码分析是提升编程技能和解决问题的关键,特别是对于复杂的框架如Struts2,理解其内部工作原理能够帮助我们优化...
本项目源码提供了一个基础的Struts2应用程序实例,对于初学者来说,这是一个很好的学习资源,可以深入理解Struts2的工作原理和架构。 Struts2的核心组件包括: 1. **Action类**:Action类是业务逻辑的载体,它是...
深入理解Struts2的源码对于提升Java Web开发技能,尤其是在面试中讨论底层实现时,具有非常重要的价值。 首先,我们来看看Struts2的核心组件和设计理念: 1. **Action**:在Struts2中,Action类是业务逻辑处理的...
Struts2 源码分析 Struts2 是一个基于MVC 模式的Web 应用程序框架,它的源码分析可以帮助我们更好地理解框架的内部机制和工作流程。下面是Struts2 源码分析的相关知识点: 1. Struts2 架构图 Struts2 的架构图...
10. **生命周期管理**: Struts2中的Action实例默认为多例,但可以通过配置改为单例,以优化性能。同时,Struts2还支持Spring等依赖注入框架,方便管理Action的依赖关系。 深入学习Struts2的源码,有助于理解其运行...
通过阅读Struts2的源码,我们可以深入了解框架如何处理请求、如何调度Action以及如何应用拦截器来扩展功能。这有助于开发者更好地定制和优化他们的应用程序,提高代码质量和性能。在实际开发中,对源码的理解能帮助...
本资料“struts2学习 源码”旨在帮助初学者理解Struts2的核心概念和工作原理,通过来自达内的详细代码实例来提供直观的学习体验。 Struts2框架的关键特性包括: 1. **动作(Action)**:在Struts2中,业务逻辑通常...
这里的"struts-1.3.9 源码"指的是Struts 1.x系列的第9次次要版本的源代码。Struts 1.3.9是在2008年发布的,它提供了许多增强和修复了之前版本中的问题,以提高框架的稳定性和安全性。 首先,我们来看看`LICENSE.txt...
在深入理解Struts2的工作原理时,源码分析是必不可少的步骤。Struts2的核心设计理念和设计模式相比Struts1.x有了显著的变化,这使得它成为一个独立且成熟的框架。 首先,Struts2的架构基于WebWork的核心,这意味着...
通过对Struts 1.2.9源码的深入学习,开发者可以了解Web应用的典型开发流程,掌握如何有效地组织和管理复杂的业务逻辑,以及如何优雅地处理用户交互。虽然Struts 1已逐渐被Struts 2和Spring MVC等更新框架替代,但它...
STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析...
struts2.0工程源码(完整的struts2.0学习工程源码) 这是一个完整的工程源码,包括所用到的jar包和发布配置文件。 导入到eclipse里几个运行,struts2.0入门学习工程,适合struts2.0广大爱好者和初学者学习和交流。
在深入理解Struts 2的源码之前,我们需要先了解其核心概念和组件。 1. **Action类与ActionMapping** Struts 2的核心是Action类,它是业务逻辑处理的中心。每个Action类对应一个用户请求,处理后返回一个Result。...
孙卫琴 struts 源码 孙卫琴 struts 源码 孙卫琴 struts 源码 103m
通过深入学习OGNL的源码,开发者可以更好地定制和优化Struts2应用,提升性能,增强安全性,并能解决遇到的特定问题。这是一项值得投入时间和精力的任务,特别是对于那些希望在Web开发领域有深入理解的人来说。