Struts2 的工作原理如下图所示。这里我们一步步介绍每一步的核心内容。
1.客户端初始化一个对Servlet容器(如Tomcat)的请求
2.这个请求通过一系列过滤器(其中一个是可选的过滤器,称为 ActionContextCleanUp,它对于集成 Struts 2 和其他框架,例如 SiteMesh Plugin 很有用)。
3.然后调用FilterDispatcher,FilterDispatcher询问Action Mapper来决定这个请求是否需要调用一个Action。
FilterDispatcher是控制器的核心,也是mvc中c控制层的核心。下面粗略分析一下我理解的filter Dispatcher工作流程和原理:Filter Dispatcher初始化和核心doFilter启用
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 抛出 IOException, ServletException ...{
HttpServletRequest 请求 = (HttpServletRequest) 请求;
HttpServletResponse 响应 = (HttpServletResponse) res;
ServletContext servletContext = filterConfig .getServletContext();
//这里处理HttpServletRequest和HttpServletResponse。
DispatcherUtils du = DispatcherUtils .getInstance();
du.prepare(request, response);//像方法名一样进行locale、encoding和特殊请求参数设置。
尝试 ...{
request = du .wrapRequest(request, servletContext);//打包请求
} 捕捉 (IOException e) ...{
String message = "无法使用 MultipartRequestWrapper 包装 servlet 请求!" ;
LOG.error(消息,e);
抛出新的 ServletException(消息,e);
}
ActionMapperIF mapper = ActionMapperFactory .getMapper();//获取动作映射器
ActionMapping mapping = mapper .getMapping(request);//映射获取动作
如果(映射 ==空)...{
// 这个请求中没有任何动作,我们应该寻找静态资源吗?
String resourcePath = RequestUtils .getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) ...{
resourcePath = 请求.getPathInfo();
}
if ("true".equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))
&& resourcePath.startsWith("/webwork")) ...{
字符串 名称 = resourcePath .substring("/webwork".length());
findStaticResource(名称,响应);
} 别的 ...{
// 这是一个正常的请求,让它通过
链.doFilter(请求,响应);
}
// WW 在这里完成了它的工作
返回;
}
对象 o = null ;
尝试 ...{
//setupContainer(请求);
o = beforeActionInvocation (request, servletContext);
//下面分析整个框架的核心方法。
du.serviceAction(请求,响应,servletContext,映射);
} 最后 ...{
afterActionInvocation(request, servletContext, o);
ActionContext.setContext(null);
}
}
du.serviceAction(请求,响应,servletContext,映射);
//该方法询问Action Mapper是否需要调用Action来处理请求。如果 Action Mapper 决定需要调用某个 Action,FilterDispatcher 就会处理对 ActionProxy 的请求。
public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) ...{
HashMap extraContext = createContextMap (requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig()); //实例化Map请求,询问ActionMapper是否需要调用Action来处理请求。
extraContext.put(SERVLET_DISPATCHER, 这个);
OgnlValueStack 堆栈 = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
如果(堆栈!= null)...{
extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack));
}
尝试 ...{
ActionProxy 代理 = ActionProxyFactory .getFactory().createActionProxy(namespace, actionName, extraContext);
//这里的actionName是通过两个getAction Name通道解析的。FilterDispatcher 处理对 ActionProxy 的请求。这是 Servlet Dispatcher 的 TODO:。
request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
proxy.execute();
//ActionProxy通过代理方式执行
如果(堆栈!= null)...{
request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);
}
} 捕捉(配置异常 e)...{
log.error("找不到动作", e);
发送错误(请求,响应,HttpServletResponse.SC_NOT_FOUND,e);
} 捕捉(异常 e)...{
log.error("无法执行动作", e);
sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
}
4.如果ActionMapper决定需要调用一个Action,FilterDispatcher处理对ActionProxy的请求
5.ActionProxy通过ConfigurationManager查询框架的配置文件,找到需要调用的Action类。在这里,我们通常从 struts.xml 中读取配置。
6.ActionProxy 创建一个 ActionInvocation 的实例。
7.ActionInvocation 实例使用命名方式调用。在Action调用前后,都涉及到Intercepter的调用。
通过上述介绍相信大家对Struts2工作原理已经有所了解,大家如果想了解更多相关知识,可以关注一下极悦的Java视频,里面的课程内容从入门到精通,细致全面,通俗易懂,适合没有基础的小白学习,希望对大家能够有所帮助。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习