Struts流程分析+源码分析

1、初始化工作

读取配置---转换器-----读取插件

当struts-config.xml配置文件加载到内存,则会创建两个map:ActionConfigs,FromBeans。这两个map都交由ModuleConfig对象管理

a、ActionConfigs的Map装载每个Action配置信息---ActionMapping

b、名为FromBeans的map装载FormBean配置信息---FormBeanConfig

接收请求ActionServlet的doPost方法进行处理,调用process方法,而process方法会创建RequestProcessor对象并调用其process方法

ActionServlet的doPost方法

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException {

process(request, response);

}

ActionServlet的process方法

protected void process(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {

ModuleUtils.getInstance().selectModule(request, getServletContext());

ModuleConfig config = getModuleConfig(request);

RequestProcessor processor = getProcessorForModule(config);

if (processor == null) {

processor = getRequestProcessor(config);

}

processor.process(request, response);

}

RequestProcessor对象的process方法,也是整个ActionServlet的整个核心控制流程

public void process(HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException {

// Identify the path component we will use to select a mapping

String path = processPath(request, response);

if (path == null) {

return;

}

this.processCachedMessages(request, response);

// Identify the mapping for this request

ActionMapping mapping = processMapping(request, response, path);

if (mapping == null) {

return;

}

// Check for any role required to perform this action

if (!processRoles(request, response, mapping)) {

return;

}

// Process any ActionForm bean related to this request

ActionForm form = processActionForm(request, response, mapping);

processPopulate(request, response, form, mapping);

// Validate any fields of the ActionForm bean, if applicable

try {

if (!processValidate(request, response, form, mapping)) {

return;

}

} catch (InvalidCancelException e) {

ActionForward forward = processException(request, response, e, form, mapping);

processForwardConfig(request, response, forward);

return;

} catch (IOException e) {

throw e;

} catch (ServletException e) {

throw e;

}

// Process a forward or include specified by this mapping

if (!processForward(request, response, mapping)) {

return;

}

if (!processInclude(request, response, mapping)) {

return;

}

// Create or acquire the Action instance to process this request

Action action = processActionCreate(request, response, mapping);

if (action == null) {

return;

}

// Call the Action instance itself

ActionForward forward =

processActionPerform(request, response, action, form, mapping);

// Process the returned ActionForward instance

processForwardConfig(request, response, forward);

}

1、struts工作流程:

@@、processPath()-->截取.do前路径

RequestProcessor对象的process方法的调用processPath方法截取.do前路径

源码如下:

String path = processPath(request, response);

http://127.0.0.1:8080/struts_login/login.do?

username="admin"&password="admin"

path = request.getServletPath();

path=/login.do?username="admin"&password="admin"

int slash = path.lastIndexOf("/");

slash =0;

int period = path.lastIndexOf(".");

period=6;

if ((period >= 0) && (period > slash)) {

path = path.substring(0, period);

path=/login

}

return (path);

--------------------------------------------------------------------

@@、processMapping()-->根据上一步解析的路径,找到请求路径找到在actionConfigs的map里取得所对应的ActionMapping对象

核心源码如下:

protected ActionMapping processMapping(HttpServletRequest request,

HttpServletResponse response, String path)

throws IOException {

// Is there a mapping for this path?

ActionMapping mapping =

(ActionMapping) moduleConfig.findActionConfig(path);

// If a mapping is found, put it in the request and return it

if (mapping != null) {

request.setAttribute(Globals.MAPPING_KEY, mapping);

return (mapping);

}

<action-mappings>

<action path="/login"

type="com.struts.LoginAction"

name="loginForm"

scope="request"

validate="true"

>

<forward name="success" path="/login_success.jsp"/>

<forward name="error" path="/login_error.jsp"/>

</action>

</action-mappings>

---------------------------------------------------------------------

@@、processActionForm()--->根据解析action配置的name值找是否scope所对应的域里是否有该请求对应的actionfrom对象,没有则根据actionfrom配置的type的值反射创建actionFrom对象并存入request

protected ActionForm processActionForm(HttpServletRequest request,HttpServletResponse response, ActionMapping mapping) {

ActionForm instance = RequestUtils.createActionForm

(request, mapping, moduleConfig, servlet);

if (instance == null) {

return (null);

}

if ("request".equals(mapping.getScope())) {

request.setAttribute(mapping.getAttribute(), instance);

} else {

HttpSession session = request.getSession();

session.setAttribute(mapping.getAttribute(), instance);

}

return (instance);

}

public static ActionForm createActionForm(HttpServletRequest request,ActionMapping mapping, ModuleConfig moduleConfig,ActionServlet servlet) {

String attribute = mapping.getAttribute();

if (attribute == null) {

return (null);

}

String name = mapping.getName();

//到formBeans的Map中取得FormBeanConfig对象

FormBeanConfig config = moduleConfig.findFormBeanConfig(name);

if (config == null) {return (null);}

ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());

try {if (instance != null ) {return (instance); }

return createActionForm(config, servlet);

}

private static ActionForm lookupActionForm(HttpServletRequest request, String attribute, String scope)

{// Look up any existing form bean instance

ActionForm instance = null;

HttpSession session = null;

if ("request".equals(scope)) {

instance = (ActionForm) request.getAttribute(attribute);

} else {

session = request.getSession();

instance = (ActionForm) session.getAttribute(attribute);

}

return (instance);

}

-------------------------------------------------------------------------------------------------------------------------------

@@、processPopulate()-->从request里拿出name值所对应的actionform并根据actionform配置自动收集请求参数到对象并存入request里

protected void processPopulate(HttpServletRequest req,HttpServletResponse response,

ActionForm form,

ActionMapping mapping)

throws ServletException {

if (form == null) {

return;

}

form.reset(mapping, request);//收集表单数据前对 表单bean的属性初始化

RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),

request);

RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),request);

public static void populate(Object bean,String prefix,String suffix,HttpServletRequest request)

throws ServletException {

HashMap properties = new HashMap();

Enumeration names = null;

names = request.getParameterNames();

while (names.hasMoreElements()) {

String name = (String) names.nextElement();

String stripped = name;

Object parameterValue = null;

parameterValue = request.getParameterValues(na

me);

properties.put(stripped, parameterValue);

}

BeanUtils.populate(bean, properties);

}

public static void populate(Object bean, Map properties)

throws IllegalAccessException, InvocationTargetException {

if ((bean == null) || (properties == null)) {

return;

}

Iterator names = properties.keySet().iterator();

while (names.hasNext()) {

String name = (String)

names.next();

Object value = properties.get(name);

setProperty(bean, name, value);

//收集表单数据后对表单bean的属性值进行验证

if (!processValidate(request, response, form, mapping)) {

return;

}

-------------------------------------------------------------------------

@@、processActionCreate()--->根据action配置type的值创建action对象.

processActionCreate创建action对象(这里actions是HashMap对象,用map实现创建action对象是单例,而且在创建的过程是加锁防止多个线程在用一个时刻访问同一个action请求)

源码如下:

protected Action processActionCreate(HttpServletRequest request,

HttpServletResponse response, ActionMapping mapping)

throws IOException {

//通过maping对象获取action的类型(全类名用于反射创建对象)

String className = mapping.getType();

Action instance;

//在创建action的过程中加锁确保线程同步

synchronized (actions) {

instance = (Action) actions.get(className);

if (instance != null) {

return (instance);

}

try {

instance = (Action) RequestUtils.applicationInstance(className);

} catch (Exception e) {

return (null);

}

actions.put(className, instance);

}

if (instance.getServlet() == null) {

instance.setServlet(this.servlet);

}

return (instance);

}

---------------------------------------------------------------------------------------------------------------------------------

@@、processActionPerform()---->调用processActionPerform()把request,response,actionform,actionmapping参数注入action对象的execte方法.创建action对象成功则执行ActionForward forward = processActionPerform(request, response, action, form, mapping);其实质是调用execute方法并注入requst,rresponse,actionform,mapping参数并返回ActionFword的转向信息。

protected ActionForward processActionPerform(HttpServletRequest request,HttpServletResponse            response,Action action,ActionForm form,ActionMapping mapping)throws IOException, ServletException {

try {

return (action.execute(mapping, form, request, response));

} catch (Exception e) {

return (processException(request, response,

e, form, mapping));

}

}

---------------------------------------------------------------------

@@、processForwardConfig()--->执行execte方法后,返回的是ActionForward对象(封装了转向信息和转向方式),根据配置文件的forward标签里的name的值拿和path值注入actionforward对象,返回给actionservlet,actionservlet对actionforward进行分析(不写redirect则默认服务器跳转,否则是客户端跳转)转向结果页面

protected void processForwardConfig(HttpServletRequest request,

HttpServletResponse response,ForwardConfig forward)throws IOException, ServletException {

if (forward == null) { return;}

String forwardPath = forward.getPath();

String uri = null;

uri = forwardPath;

if (forward.getRedirect()) //如果为重定向

{

response.sendRedirect( uri);//客户端跳转

} else {

doForward(uri, request, response); //服务端端跳转

}

}

protected void doForward(

String uri,

HttpServletRequest request,

HttpServletResponse response)

throws IOException, ServletException {

RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);

rd.forward(request, response);

}

时间: 2024-10-23 05:30:02

Struts流程分析+源码分析的相关文章

Android应用层View绘制流程与源码分析

Android应用层View绘制流程与源码分析 1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系: 看见没有,如上图中id为content的内容就是整个View树的结构,所以对每个具体View对象的操作,其实就是个递归的实现. 前面<Android触摸屏事件派发机制详解与源码分析一(View篇)>文章的3-1

Struts2请求处理流程及源码分析

1.1 Struts2请求处理 1. 一个请求在Struts2框架中的处理步骤: a) 客户端初始化一个指向Servlet容器的请求: b) 根据Web.xml配置,请求首先经过ActionContextCleanUp过滤器,其为可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助(SiteMesh Plugin),主要清理当前线程的ActionContext和Dispatcher: c) 请求经过插件过滤器,如:SiteMesh.etc等过滤器: d) 请求经过核心过滤器Filte

Android视图View绘制流程与源码分析(全)

来源:[工匠若水 http://blog.csdn.net/yanbober] 1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系: 看见没有,如上图中id为content的内容就是整个View树的结构,所以对每个具体View对象的操作,其实就是个递归的实现. 前面<Android触摸屏事件派发机制详解与源码分析一(

Django CBV流程及源码分析

Django 实现视图的方法有两种,一种是FBV(function base view)即基于函数的视图,还一种高级的就是CBV(class base view),通过阅读源码你会发现它本质上还是基于FBV的.FBV的优点是用法和写法都比较简单适合刚开始学的同学使用,缺点就是不能用的面向对象的几大特性只用函数进行封装代码多的时候会显得代码很冗余,而CBV就很好的解决了这些问题.并且Django官方在后面的Django版本中加入了很多基于CBV的类,方便我们快速开发.我们先简单的看下Django在

Spring源码分析——源码分析环境搭建

1.在Windows上安装Gradle gradle工具类似于maven,用于项目的构建,此处主要用于构建spring源码,以便我们将spring源码导入eclipse. 开发环境 Java:JDK8(必须是JDK或JRE7以上,使用java -version查看当前电脑java版本) 操作系统:Windows 安装步骤 下载最新的Gradle压缩包:Gradle官网:https://gradle.org/,当前最新版本下载地址:https://gradle.org/releases/,下载bi

Yarn任务提交流程(源码分析)

Based on Hadoop 2.7.1 JobSubmitter addMRFrameworkToDistributedCache(Configuration conf) : mapreduce.application.framework.path, 用于指定其他framework的hdfs 路径配置,默认yarn的可以不管 Token相关的方法:读取认证信息(支持二进制.json),并将其添加至相应的fileSystem中,以便以同样权限访问文件系统 copyAndConfigureFil

Spring MVC请求处理流程及源码分析

从接受请求到返回响应,Spring MVC框架的众多组件都伸胳膊挽袖子行动起来,各司其职,有条不紊地完成份内的工作.在整个框架中,DispatcherServlet处于核心的位置,它负责协调和组织不同组件,共同完成请求响应的工作.和大多数Web MVC框架一样,Spring MVC通过一个前端Servlet处理器接收所有的请求,并将具体工作委托给其它组件进行具体的处理,DispatcherServlet就是 Spring MVC的前端Servlet处理器.下面我们对Spring MVC处理请求的

【React源码分析】组件通信、refs、key和ReactDOM

React源码系列文章,请多支持:React源码分析1 - 组件和对象的创建(createClass,createElement)React源码分析2 - React组件插入DOM流程React源码分析3 - React生命周期详解React源码分析4 - setState机制React源码分析5 -- 组件通信,refs,key,ReactDOMReact源码分析6 - React合成事件系统 1 组件间通信 父组件向子组件通信 React规定了明确的单向数据流,利用props将数据从父组件传

kube-proxy源码分析

摘要:假设你对kube-proxy的工作原理有一定的了解,本文基于kubernetes v1.5代码对kube-proxy的源码目录结构进行了分析,并以iptables mode为例进行了完整流程的源码分析,给出了其内部实现的模块逻辑图,希望对你深入理解kube-proxy有所帮助. kube-proxy介绍 请参考我的另一篇博文:kube-proxy工作原理 源码目录结构分析 cmd/kube-proxy //负责kube-proxy的创建,启动的入口 . ├── app │ ├── conn