详解Webwork中Action 调用的方法


Posted in Javascript onFebruary 02, 2016

本文主要通过三个方面给大家介绍webwork action调用相关知识,三个方面分别是:

1.这部分框架类关系

2.Webwork 获取和包装 web 参数

3.DefaultActionProxyFactory、DefaultActionProxy、DefaultActionInvocation

一路走来,终于要开始 webwork 核心业务类的总结,webwork 通过对客户端传递的 web 参数重新包装,进行执行业务 Action 类,并反馈执行结果,本篇源码分析对应下图 WebWork 框架流转图中红色框的地方。

详解Webwork中Action 调用的方法

1.这部分框架类关系

详解Webwork中Action 调用的方法

2.Webwork 获取和包装 web 参数

•每个Web 框架或多或少的对 Web 请求参数的包装,用来拿来方便自己使用,当然webwork 也不例外。
•Webwork 每次响应请求的入口方法:

public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
try {
if (encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch (Exception localException) {
}
}
if (locale != null) {
response.setLocale(locale);
}
if (this.paramsWorkaroundEnabled) {
request.getParameter("foo");
}
request = wrapRequest(request); //封装 request请求
serviceAction(request, response, getNameSpace(request), getActionName(request), getRequestMap(request), getParameterMap(request), getSessionMap(request), getApplicationMap());
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
log.error(message, e);
sendError(request, response, , new ServletException(message, e));
}
}

•接受 request 、response 参数,并对 request 参数进行封装,这次封装主要是针对多媒体请求进行的特殊处理,例如项目中的文件上传请求,导出各种类型文件等...

•包装完 request 之后,service 方法调用 ServletDispatche.serviceAction() 方法,并调用 getApplicationMap、getSessionMap、getRequestMap、 getParameterMap、getActionName、getNameSpace 6 个方法开始了Action 业务逻辑调用前的前戏。

•getNameSpace 方法用来获得一个Action所属的名称空间,例如 : "/my/MyAction.action"则返回"/my",具体实现如下:

protected String getNameSpace(HttpServletRequest request){
String servletPath = request.getServletPath();
return getNamespaceFromServletPath(servletPath);
}
public static String getNamespaceFromServletPath(String servletPath){
servletPath = servletPath.substring(, servletPath.lastIndexOf("/"));
return servletPath;
}

•getActionName 返回请求的Action的名字,例如:"MyAction.action"则返回"MyAction",具体实现如下:

protected String getActionName(HttpServletRequest request){
String servletPath = (String)request.getAttribute("javax.servlet.include.servlet_path");
if (servletPath == null) {
servletPath = request.getServletPath();
}
return getActionName(servletPath);
}
protected String getActionName(String name){
int beginIdx = name.lastIndexOf("/");
int endIdx = name.lastIndexOf(".");
return name.substring(beginIdx == - ? : beginIdx + , endIdx == - ? name.length() : endIdx);
}

• getRequestMap 方法返回一个包含请求中所有属性的Map,具体实现类是 RequestMap,具体代码如下:

protected Map getRequestMap(HttpServletRequest request){
return new RequestMap(request);
}

•getParameterMap 方法返回一个包含请求中所有参数的Map,具体代码如下:

protected Map getParameterMap(HttpServletRequest request) throws IOException{
return request.getParameterMap();
}

•getSessionMap 方法返回一个包含 session 中所有属性的 Map,具体实现类是 SessionMap,具体代码如下:

protected Map getSessionMap(HttpServletRequest request){
return new SessionMap(request);
}

•getApplicationMap 方法返回一个包含 Application 中所有属性的Map,具体实现类 是ApplicationMap,具体代码如下:

protected Map getApplicationMap(){
return new ApplicationMap(getServletContext());
}

•WebWork之所以要把request 的属性、参数,session 中的属性,Application 中的属性封装成 Map,仅仅是为了自己使用方便。

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());
extraContext.put("com.opensymphony.xwork.dispatcher.ServletDispatcher", this);
OgnlValueStack stack = (OgnlValueStack) request.getAttribute("webwork.valueStack");
if (stack != null) {
extraContext.put("com.opensymphony.xwork.util.OgnlValueStack.ValueStack", new OgnlValueStack(stack));
}
try {
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
request.setAttribute("webwork.valueStack", proxy.getInvocation().getStack());
proxy.execute();
if (stack != null) {
request.setAttribute("webwork.valueStack", stack);
}
} catch (ConfigurationException e) {
log.error("Could not find action", e);
sendError(request, response, 404, e);
} catch (Exception e) {
log.error("Could not execute action", e);
sendError(request, response, 500, e);
}
}

•首先 ServiceAction 调用了createContextMap 创建Action 上下文(extraContext)。 它将JavaServlet 相关的对象进行包装,放入extraContext Map对象里。

•接着检查 上一个请求中是否有可用的值堆栈,如果有就放入extraContext 这个Map 对象里,供本次请求使用 。

•ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文 可以看作是一个容器(其实我们这里的容器就是一个Map 而已),它存放的是Action 在执行时需要用到的对象。

• ServletActionContext ( com.opensymphony.webwork. ServletActionContext),这个类直接继承了ActionContext,它提供了直接与JavaServlet 相关象访问的功能。

•OgnlValueStack主要的功能是通过表达式语言来存取对象的属性。

3.DefaultActionProxyFactory、DefaultActionProxy、DefaultActionInvocation

前戏终于做完了,Action 调用的三兄弟要登场进行最重要的操作了,就是下面这三句代码,与Webwork 学习之路(五)请求跳转前 xwork.xml 的读取代码有非常相似的写法和设计:

ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
request.setAttribute("webwork.valueStack", proxy.getInvocation().getStack());

proxy.execute(); •通过由前面获得的namespace、actionName、extraContext 创建调用代理 ActonProxy 实例,这里也就是 DefaultActionProxy,之后调用 了 ActionProxy.execute 方法来执行我们逻辑Action.execute。

•ActionProxy是一个接口,ActionProxyFactory则是一个抽象类,默认情况下它们是通过 DefaultActionProxy和DefaultActionProxyFactory来完成操作的。

•在 ActionProxyFactory 中有一个静态变量 factory ,它指向的是一个 DefaultActionProxyFactory 实例,代码如下:

static ActionProxyFactory factory = new DefaultActionProxyFactory();
public static void setFactory(ActionProxyFactory factory){
factory = factory;
}
public static ActionProxyFactory getFactory(){
return factory;
}

• DefaultActionProxyFactory 的 createActionProxy 方法返回了 DefaultActionProxy 实例。

public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext)throws Exception {
setupConfigIfActionIsCommand(namespace, actionName);
return new DefaultActionProxy(namespace, actionName, extraContext, true);
} •DefaultActionProxy的构造函数
protected DefaultActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult) throws Exception{
if (LOG.isDebugEnabled()) {
LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName);
}
this.actionName = actionName;
this.namespace = namespace;
this.executeResult = executeResult;
this.extraContext = extraContext;
this.config = ConfigurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(namespace, actionName);
if (this.config == null)
{
String message;
String message;
if ((namespace != null) && (namespace.trim().length() > 0)) {
message = LocalizedTextUtil.findDefaultText("xwork.exception.missing-package-action", Locale.getDefault(), new String[] {
namespace, actionName });
} else {
message = LocalizedTextUtil.findDefaultText("xwork.exception.missing-action", Locale.getDefault(), new String[] {
actionName });
}
throw new ConfigurationException(message);
}
prepare();
}

•将传入的名称空间、 Action 的名字等参数赋予本地变量,接着通过 ConfigurationManager 获得当前请求的 Action 的配置信息[这里在5中已经描述过]。接着调用自身的 prepare 方法创建一个 ActionInvocation 对象赋予自身变量 invocation。在之后的 execute 方法中通过操纵invocation 来实现我们自己写的Action 的调用。

protected void prepare() throws Exception {
this.invocation = ActionProxyFactory.getFactory().createActionInvocation(this, this.extraContext);
}

以上所示是针对Webwork中Action 调用 的相关知识,希望对大家有所帮助。

Javascript 相关文章推荐
JavaScript 函数式编程的原理
Oct 16 Javascript
JS图片根据鼠标滚动延时加载的实例代码
Jul 13 Javascript
jQuery prototype冲突的2种解决方法(附demo示例下载)
Jan 21 Javascript
jQuery之简单的表单验证实例
Jul 07 Javascript
JS从数组中随机取出几个数组元素的方法
Aug 02 Javascript
javascript 面向对象function详解及实例代码
Feb 28 Javascript
AngularJS点击添加样式、点击变色设置的实例代码
Jul 27 Javascript
javascript数组定义的几种方法
Oct 06 Javascript
JavaScript实现带有子菜单和控件的slider轮播图效果
Nov 01 Javascript
layUI实现三级导航菜单效果
Jul 26 Javascript
vue.js基于v-for实现批量渲染 Json数组对象列表数据示例
Aug 03 Javascript
详解VUE中的插值( Interpolation)语法
Oct 18 Javascript
JavaScript File API文件上传预览
Feb 02 #Javascript
javascript绘制漂亮的心型线效果完整实例
Feb 02 #Javascript
Webwork 实现文件上传下载代码详解
Feb 02 #Javascript
javascript自动切换焦点控制效果完整实例
Feb 02 #Javascript
原生js实现图片层叠轮播切换效果
Feb 02 #Javascript
Javascript实现的SHA-256加密算法完整实例
Feb 02 #Javascript
JavaScript实现的SHA-1加密算法完整实例
Feb 02 #Javascript
You might like
php中理解print EOT分界符和echo EOT的用法区别小结
2010/02/21 PHP
PHP三元运算的2种写法代码实例
2014/05/12 PHP
对PHP PDO的一些认识小结
2015/01/23 PHP
ThinkPHP实现更新数据实例详解(demo)
2016/06/29 PHP
php设计模式之策略模式应用案例详解
2019/06/17 PHP
javascript 面向对象编程基础:封装
2009/08/21 Javascript
Jquery数独游戏解析(一)-页面布局
2010/11/05 Javascript
jQuery文本框(input textare)事件绑定方法教程
2013/04/24 Javascript
你可能不知道的JavaScript的new Function()方法
2014/04/17 Javascript
使用JavaScript+canvas实现图片裁剪
2015/01/30 Javascript
javascript实现随时变化着的背景颜色
2015/04/02 Javascript
使用淘宝镜像cnpm安装Vue.js的图文教程
2018/05/17 Javascript
js实现各浏览器全屏代码实例
2018/07/03 Javascript
如何使用electron-builder及electron-updater给项目配置自动更新
2018/12/24 Javascript
微信小程序模板消息推送的两种实现方式
2019/08/27 Javascript
JavaScript 几种循环方式以及模块化的总结
2020/09/03 Javascript
Python open读写文件实现脚本
2008/09/06 Python
Python编程之属性和方法实例详解
2015/05/19 Python
浅谈Python的垃圾回收机制
2016/12/17 Python
Python基础语言学习笔记总结(精华)
2017/11/14 Python
python环形单链表的约瑟夫问题详解
2018/09/27 Python
CentOS 7下安装Python3.6 及遇到的问题小结
2018/11/08 Python
python rsync服务器之间文件夹同步脚本
2019/08/29 Python
解决python3.x安装numpy成功但import出错的问题
2020/11/17 Python
Stefania Mode美国:奢华设计师和时尚服装
2018/01/07 全球购物
法国亚马逊官方网站:Amazon.fr
2020/12/19 全球购物
银行求职推荐信范文
2013/11/30 职场文书
婚纱摄影师求职信范文
2014/04/17 职场文书
捐书活动总结
2014/05/04 职场文书
副校长竞聘演讲稿
2014/09/01 职场文书
幼儿教师师德师风自我剖析材料
2014/09/29 职场文书
群众路线个人自我剖析材料
2014/10/07 职场文书
2014年技术员工作总结
2014/11/18 职场文书
经典法律座右铭(50句)
2019/08/15 职场文书
mysql主从复制的实现步骤
2021/10/24 MySQL
Python编程中内置的NotImplemented类型的用法
2022/03/23 Python