Struts2执行流程
2017-04-20 21:33
393 查看
1. 请求示意图
2. 一个请求在Struts2框架中的处理步骤:
1. 客户端初始化一个指向Servlet容器的请求
2. 根据web.xml配置,请求先经过ActionContextCleanUp过滤器,主要清理当前线程中ActionContext和Dispatcher
3. 请求经过插件过滤器(该步可以略过)
4. 请求经过StrutsPrepareAndExecuteFilter核心过滤器,执行doFilter方法,在该方法中,询问ActionMapper来决定这个请求是否需要调用Action
5. 如果ActionMapper决定调用某个Action,则ActionMapper会返回一个ActionMapping实例(存储Action的配置文件),并创建ActionProxy(Action代理)对象,将请求交给代理对象继续处理
6. ActionProxy对象根据ActionMapping和Configuration Manager询问框架的配置文件,找到需要调用的Action类
7. ActionProxy对象创建时,会同时创建一个ActionInvocation的实例
8. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器的调用
9. 一旦Action执行完毕,ActionInvocation实例负责struts.xml中的配置创建并返回到result结果视图,result通常是一个需要被表示的JSP或者FreeMarker的模板,也可能是另外的一个Action链
10. 如果要在返回result之前做些什么,可以实现PreResultListener接口,PreResultListener可以在Interceptor中实现,也可以在Action中实现
11. 根据Result对象信息,生成用户响应信息response
3. 源码分析阶段
3.1 服务器启动阶段
1. 服务器启动后,进入web.xml,跳进配置的核心过滤器StrutsPrepareAndExecuteFilter
2. 类内部首先是三个变量的声明
[/code]
3. 进入到init方法
[/code]
4.对于第5行
[/code]
进入到FilterHostConfig内部查看,发现FilterHostConfig主要是用来获取Servlet上下文、web.xml中的init-param配置的param-name获取param-value的值
[/code]
dispatcher中serviceAction方法
[/code]
1. 请求示意图
2. 一个请求在Struts2框架中的处理步骤:
1. 客户端初始化一个指向Servlet容器的请求
2. 根据web.xml配置,请求先经过ActionContextCleanUp过滤器,主要清理当前线程中ActionContext和Dispatcher
3. 请求经过插件过滤器(该步可以略过)
4. 请求经过StrutsPrepareAndExecuteFilter核心过滤器,执行doFilter方法,在该方法中,询问ActionMapper来决定这个请求是否需要调用Action
5. 如果ActionMapper决定调用某个Action,则ActionMapper会返回一个ActionMapping实例(存储Action的配置文件),并创建ActionProxy(Action代理)对象,将请求交给代理对象继续处理
6. ActionProxy对象根据ActionMapping和Configuration Manager询问框架的配置文件,找到需要调用的Action类
7. ActionProxy对象创建时,会同时创建一个ActionInvocation的实例
8. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器的调用
9. 一旦Action执行完毕,ActionInvocation实例负责struts.xml中的配置创建并返回到result结果视图,result通常是一个需要被表示的JSP或者FreeMarker的模板,也可能是另外的一个Action链
10. 如果要在返回result之前做些什么,可以实现PreResultListener接口,PreResultListener可以在Interceptor中实现,也可以在Action中实现
11. 根据Result对象信息,生成用户响应信息response
3. 源码分析阶段
3.1 服务器启动阶段
1. 服务器启动后,进入web.xml,跳进配置的核心过滤器StrutsPrepareAndExecuteFilter
2. 类内部首先是三个变量的声明
[/code]
3. 进入到init方法
[/code]
4.对于第5行
[/code]
进入到FilterHostConfig内部查看,发现FilterHostConfig主要是用来获取Servlet上下文、web.xml中的init-param配置的param-name获取param-value的值
[/code]
dispatcher中serviceAction方法
[/code]
2. 一个请求在Struts2框架中的处理步骤:
1. 客户端初始化一个指向Servlet容器的请求
2. 根据web.xml配置,请求先经过ActionContextCleanUp过滤器,主要清理当前线程中ActionContext和Dispatcher
3. 请求经过插件过滤器(该步可以略过)
4. 请求经过StrutsPrepareAndExecuteFilter核心过滤器,执行doFilter方法,在该方法中,询问ActionMapper来决定这个请求是否需要调用Action
5. 如果ActionMapper决定调用某个Action,则ActionMapper会返回一个ActionMapping实例(存储Action的配置文件),并创建ActionProxy(Action代理)对象,将请求交给代理对象继续处理
6. ActionProxy对象根据ActionMapping和Configuration Manager询问框架的配置文件,找到需要调用的Action类
7. ActionProxy对象创建时,会同时创建一个ActionInvocation的实例
8. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器的调用
9. 一旦Action执行完毕,ActionInvocation实例负责struts.xml中的配置创建并返回到result结果视图,result通常是一个需要被表示的JSP或者FreeMarker的模板,也可能是另外的一个Action链
10. 如果要在返回result之前做些什么,可以实现PreResultListener接口,PreResultListener可以在Interceptor中实现,也可以在Action中实现
11. 根据Result对象信息,生成用户响应信息response
3. 源码分析阶段
3.1 服务器启动阶段
1. 服务器启动后,进入web.xml,跳进配置的核心过滤器StrutsPrepareAndExecuteFilter
2. 类内部首先是三个变量的声明
protected PrepareOperations prepare;
protected ExecuteOperations execute;
protected List<Pattern> excludedPatterns = null;
[/code]
3. 进入到init方法
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
[/code]
4.对于第5行
FilterHostConfig config = new FilterHostConfig(filterConfig);
[/code]
进入到FilterHostConfig内部查看,发现FilterHostConfig主要是用来获取Servlet上下文、web.xml中的init-param配置的param-name获取param-value的值
public class FilterHostConfig implements HostConfig {
private FilterConfig config;
public FilterHostConfig(FilterConfig config) {
this.config = config;
}
public String getInitParameter(String key) {
return config.getInitParameter(key);
}
public Iterator<String> getInitParameterNames() {
return MakeIterator.convert(config.getInitParameterNames());
}
public ServletContext getServletContext() {
return config.getServletContext();
}
}
[/code]
dispatcher中serviceAction方法
/**
* Load Action class for mapping and invoke the appropriate Action method, or go directly to the Result.
加载Action类用于映射,执行相应的Action方法,或者直接转到Result视图
* <p/>
* This method first creates the action context from the given parameters,
这个方法首先从给定的参数创建action上下文
* and then loads an <tt>ActionProxy</tt> from the given action name and namespace.
然后,从给定的action名和名称空间中加载一个ActionProxy
* After that, the Action method is executed and output channels through the response object.
之后,action方法被执行以及通过响应对象输出通道
* Actions not found are sent back to the user via the {@link Dispatcher#sendError} method,
Action如果没有发现,将通过sendError方法返回用户提示
* using the 404 return code.
使用404返回代码
* All other errors are reported by throwing a ServletException.
其他的错误将被抛出ServletException异常
*
* @param request HttpServletRequest 对象
* @param response HttpServletResponse对象
* @param mapping ActionMapping对象
* @throws ServletException when an unknown error occurs (not a 404, but typically something that
* would end up as a 5xx by the servlet container)
* @param context Our ServletContext object
*/
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
//如果先前有一个值栈,那么创建一个新的副本,并传递给新的Action使用
//从request中获取到ValueStack对象
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
//判断ValueStack是否为空
boolean nullStack = stack == null;
if (nullStack) {
//为空,获取ActionContext
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
//如果ActionContext不为空,通过ActionContext获取ValueStack---通过查看ActionContext,发现ActionContext包含ValueStack,
stack = ctx.getValueStack();
}
}
if (stack != null) {
//把ValueStack放入ActionContext中
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
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!
//如果ActionMapping决定直接返回到结果视图,完成
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);
}
}
[/code]
1. 请求示意图
2. 一个请求在Struts2框架中的处理步骤:
1. 客户端初始化一个指向Servlet容器的请求
2. 根据web.xml配置,请求先经过ActionContextCleanUp过滤器,主要清理当前线程中ActionContext和Dispatcher
3. 请求经过插件过滤器(该步可以略过)
4. 请求经过StrutsPrepareAndExecuteFilter核心过滤器,执行doFilter方法,在该方法中,询问ActionMapper来决定这个请求是否需要调用Action
5. 如果ActionMapper决定调用某个Action,则ActionMapper会返回一个ActionMapping实例(存储Action的配置文件),并创建ActionProxy(Action代理)对象,将请求交给代理对象继续处理
6. ActionProxy对象根据ActionMapping和Configuration Manager询问框架的配置文件,找到需要调用的Action类
7. ActionProxy对象创建时,会同时创建一个ActionInvocation的实例
8. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器的调用
9. 一旦Action执行完毕,ActionInvocation实例负责struts.xml中的配置创建并返回到result结果视图,result通常是一个需要被表示的JSP或者FreeMarker的模板,也可能是另外的一个Action链
10. 如果要在返回result之前做些什么,可以实现PreResultListener接口,PreResultListener可以在Interceptor中实现,也可以在Action中实现
11. 根据Result对象信息,生成用户响应信息response
3. 源码分析阶段
3.1 服务器启动阶段
1. 服务器启动后,进入web.xml,跳进配置的核心过滤器StrutsPrepareAndExecuteFilter
2. 类内部首先是三个变量的声明
protected PrepareOperations prepare;
protected ExecuteOperations execute;
protected List<Pattern> excludedPatterns = null;
[/code]
3. 进入到init方法
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
[/code]
4.对于第5行
FilterHostConfig config = new FilterHostConfig(filterConfig);
[/code]
进入到FilterHostConfig内部查看,发现FilterHostConfig主要是用来获取Servlet上下文、web.xml中的init-param配置的param-name获取param-value的值
public class FilterHostConfig implements HostConfig {
private FilterConfig config;
public FilterHostConfig(FilterConfig config) {
this.config = config;
}
public String getInitParameter(String key) {
return config.getInitParameter(key);
}
public Iterator<String> getInitParameterNames() {
return MakeIterator.convert(config.getInitParameterNames());
}
public ServletContext getServletContext() {
return config.getServletContext();
}
}
[/code]
dispatcher中serviceAction方法
/**
* Load Action class for mapping and invoke the appropriate Action method, or go directly to the Result.
加载Action类用于映射,执行相应的Action方法,或者直接转到Result视图
* <p/>
* This method first creates the action context from the given parameters,
这个方法首先从给定的参数创建action上下文
* and then loads an <tt>ActionProxy</tt> from the given action name and namespace.
然后,从给定的action名和名称空间中加载一个ActionProxy
* After that, the Action method is executed and output channels through the response object.
之后,action方法被执行以及通过响应对象输出通道
* Actions not found are sent back to the user via the {@link Dispatcher#sendError} method,
Action如果没有发现,将通过sendError方法返回用户提示
* using the 404 return code.
使用404返回代码
* All other errors are reported by throwing a ServletException.
其他的错误将被抛出ServletException异常
*
* @param request HttpServletRequest 对象
* @param response HttpServletResponse对象
* @param mapping ActionMapping对象
* @throws ServletException when an unknown error occurs (not a 404, but typically something that
* would end up as a 5xx by the servlet container)
* @param context Our ServletContext object
*/
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
//如果先前有一个值栈,那么创建一个新的副本,并传递给新的Action使用
//从request中获取到ValueStack对象
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
//判断ValueStack是否为空
boolean nullStack = stack == null;
if (nullStack) {
//为空,获取ActionContext
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
//如果ActionContext不为空,通过ActionContext获取ValueStack---通过查看ActionContext,发现ActionContext包含ValueStack,
stack = ctx.getValueStack();
}
}
if (stack != null) {
//把ValueStack放入ActionContext中
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
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!
//如果ActionMapping决定直接返回到结果视图,完成
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);
}
}
[/code]
相关文章推荐
- [置顶] struts2执行流程
- Struts2执行基本流程
- 【菜鸟学框架】——struts2结合框架分析执行流程
- SSH之Strust2--Struts2的执行流程
- SpringMVC与Struts2的区别及执行流程
- Java Web - Struts2基本执行流程
- Java程序员从笨鸟到菜鸟之(四十)细谈struts2(四)struts2中action执行流程和源码分析
- Struts2的执行流程
- struts2的执行流程与配置详解
- Struts2执行流程源码解析
- Java程序员从笨鸟到菜鸟之(四十)细谈struts2(四)struts2中action执行流程和源码分析
- (转)struts2的执行流程、工作原理
- Servlet中的Filter在Struts2中的执行流程
- Struts2的执行流程
- Struts2的执行流程
- 浅谈Struts2的执行流程
- struts2的执行流程
- 细谈struts2(四)struts2中action执行流程和源码分析
- Struts2执行流程
- Struts2的执行流程