AWS MVC 详解

  由于新工作是在AWS PaaS平台上进行开发,为不耽误工作,先整理一下AWS MVS的使用规范,快速上手。对AWS PaaS平台的相关介绍留到以后再来补充。本文几乎是对官方学习文档的整理,有遗漏的后补。

1.简介

  AWS MVC(Model-View-Controller),轻量级、高性能,是开发AWS App的标准框架,同时AWS PaaS自身也是基于它开发。与传统开源的Spring MVC、Strusts2相比:

  • 清晰、干净、请求驱动(请求-响应)的轻量级Web编程框架
  • 学习难度远小于Spring MVCStrusts2
  • No ServletNo JSPJust J2SE,更容易的开发调试和问题追踪
  • 与AWS平台架构兼容的会话安全、DAO、I18N国际化、日志、审计和SLA告警机制
  • 没有值栈、OGNL表达式、标签库等增加代码复杂度和性能下降的架构缺陷
  • 优于Strusts2的注解编程和方法拦截,能直接根据注解绑定Request参数,更简洁
  • 对处理结果是HTML、JSON、XML数据结构和错误码的统一处理,避免业务架构缺陷
  • 提供了一套基于JQueryJQuery Mobile的AWS UI库,针对企业级需求进行了增强封装
  • 内核采用了NIO通信和多线程池化管理,能够充分对计算资源的扩容做出适应,实现纵向扩展(Scale Up)
  • 为多个集群节点提供自我发现和自我纠正能力,简化部署和运维,轻松实现弹性的横向扩展(Scale Out)

特点:基于请求驱动,使用了前端控制器模式设计,再根据请求映射规则分发给相应的后端逻辑控制器(动作/处理器)进行处理

AWS MVC 详解

上图,前端控制器(AWS Web Server / Front Controller)和后端处理控制(AWS App Server / Controller)是AWS MVC的核心通信框架,黄色区域(视图组装、模型、模版)写业务逻辑,元素描述:

AWS Web Server 安装有AWS Portal的标准Servlet容器,例如:Tomcat、WebLogic
AWS App Server 安装有AWS Server的应用服务器,所有的业务逻辑在这里处理
Servlet 前端控制器 接收所有来自用户的请求,封装后转发给AWS App服务器
后端处理控制器 通过注解拦截到方法,绑定逻辑处理程序
View视图组装 实现业务逻辑,返回处理的结果
Model模型 资源处理对象,如处理逻辑、对象、国际化、Dao处理、缓存
Template模版 基于静态模版的渲染,处理成动态页面结果

AWS MVC编程框架的主要组成部分:

  • 提交请求(submit)
  • 前端参数解析
  • 后端控制器(controller)
  • 业务对象封装(ModelBean)
  • DAO封装
  • Cache缓存
  • View视图(返回结果)
  • 页面模版渲染(Template)

其它(略):提高生产环境下的SLA服务可用性;应用的分发、安装和卸载;对计算资源的扩容做出适应,实现纵向扩展(Scale Up)、获得线性的横向扩展(Scale Out)

2. 框架详解

2.1 提交请求

AWS MVC基于Command命令请求驱动,约定5类常见url请求地址,都可以通过GET/POST提交

url 类型 说明
./w text/html (web)-请求结果一定是普通Web页面数据时
./jd application/json (json data)-请求结果一定是ResponseObject Json
./xd application/xml (xml data)-请求结果一定是ResponseObject XML
./df application/octet-stream(成功)
application/json(失败)
(download file)-文件下载流,如下载失败或权限校验不通过,返回Json处理结果
./uf application/json (upload file)-文件上传流,返回Json处理结果

测试:启动完本地AWS服务,浏览器输入请求url:http://localhost:8088/portal/r/w?cmd=API_BENCHMARK_TEST&p=Hello AWS

说明

  1.8088是安装AWS开发服务的默认Web端口号

  2./portal/是默认的Web App根名

  3.返回结果:“Hello AWS”,如下:

  • AWS MVC 详解

·Web可靠性编程习惯

  任何请求在极端环境或服务故障时都会发生错误。如果在浏览器背后(如一个Ajax请求)发送的HTTP返回一个特定数据结构或操作状态值,那么AWS MVC会要求你在Java代码使用ResponseObject对象进行封装,并在前端对result进行检查,只有当resultok时从data中读取结果,否则应该检查errorCodemsg项,并处理该异常(如提醒操作者或其他操作)。模拟一个停机故障:关闭AWS服务,但保持Web服务的正常运行,在浏览器中输入以下URL请求:http://localhost:8088/portal/r/jd?cmd=API_BENCHMARK_TEST&p=Hello AWS

  说明

  1.使用./jd请求一个json数据结果,模拟加载ajax数据

  2.获得了非预期的“Hello AWS”

  {
  result: "error",
  msg: "AWS Instance Server连接失败!(590)"
  }

result值类型

  • ok(操作成功)
  • error(服务端发生错误,错误描述在msg项)
  • warning(服务端发生警告,警告描述在msg项)
 3.查看结果:↓

  AWS MVC 详解

默认编码字符集:utf-8

常规请求必须参数

  • sid(用户会话)
  • cmd(请求指令。命名规范:前缀为该应用的Id,后面是动作名,中间以下划线分割,区分大小写

  AWS MVC 详解

Web层配置文件

  每个AWS App的Web资源被独立的定义在webapp根目录apps/%AppId%下。如果该应用需要cmd处理,至少应定义一个接参配置文件,并建议命名为action.xml如果使用AWS自带的Developer开发工具,该配置文件可忽略,AWS Developer会自动根据Controller类同步构建该配置)。配置文件存为 UTF-8 NO BOM,格式为一个或多个符合Schema规范、以action(不区分大小写)开头、后缀为xml的文件。action.xml位置及内容示例:

  AWS MVC 详解

<?xml version="1.0" encoding="utf-8"?>
<aws-actions>
<cmd-bean name="%AppId%_xxx1">
<param name="p1" />
</cmd-bean>
<cmd-bean name="%AppId%_xxx2">
<param name="p1" />
</cmd-bean>
<cmd-bean name="%AppId%_xxx3">
<param name="p1" type="body"/>
</cmd-bean>
</aws-actions> 实际项目中配置
AWS MVC 详解

cmd-bean的type属性:

  • type不配置时,该参数的值来自请求中查询参数或者application/x-www-form-urlencoded类型内容中请求参数
  • type=body时,该参数的值来自请求内容application/xml、application/json等类型的值,Controller将接收到请求内容的字符串值
  • type=cookie时,该参数的值来自请求内容的cookie,Controller将接收到对应namecookie
  • type=header时,该参数的值来自请求内容的header,Controller将接收到对应nameheader

2.1.1 Form Submit提交

  普通表单提交处理方式,包括HTML的form提交和js提交。如下模拟一个数值运算场景,由浏览器提交两个数值和运算类型,经过前端控制器传参和后端控制器的接参,最终抵达逻辑区

a) HTML提交:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>数据计算</title>
<!-- JQuery -->
<script type="text/javascript" src="../commons/js/jquery/scripts/jquery.js"></script>
<!-- AWS UI -->
<link rel="stylesheet" type="text/css" href="../commons/css/awsui.css">
<script type="text/javascript" src="../commons/js/awsui.js"></script>
</head>
<body>
<form id="editForm" method="post" action="./jd?sid=<#sid>&cmd=%AppId%_calculation">
<table class="awsui-ux">
<tr>
<td class="awsui-ux-title">计算</td>
<td class="required">
<input id="number1" name="number1" class="awsui-textbox" />
<select id="sign" name="sign" class="awsui-select">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input id="number2" name="number2" class="awsui-textbox" />
<span> = </span>
<input id="results" name="results" class="awsui-textbox" />
</td>
</tr>
<tr>
<td class="awsui-ux-title" colspan="2" style="text-align: center; ">
<span id="submitBtn" class="button blue">提交</span>
</td>
</tr>
</table>
</form>
</body>
</html>
注:上述源码中,<#sid>在实际运行中由实际的用户会话Id替代

b) JavaScript提交:

$('#submitBtn').click(function(e) {
// 提交表单
$('#editForm').submit();
});

c) 前端传参配置(Web层action.xml配置文件)

<?xml version="1.0" encoding="utf-8"?>
<aws-actions>
<cmd-bean name="%AppId%_calculation">
<param name="number1" />
<param name="number2" />
<param name="sign" />
</cmd-bean>
</aws-actions>
  • 声明%AppId%_calculation命令,%AppId%是你实际的应用Id
  • 该命令接收number1,number2,sign三个参数

d) 后端接参处理

方式1(推荐)

@Mapping("%AppId%_calculation")
public String calculation(UserContext me, int number1, int number2, @Param(defaultValue = "+")String sign) {
TestWeb web = new TestWeb(me);
return web.calculation(number1, number2, sign);
}
  • 显示定义与变量名匹配的方法参数
  • UserContext是AWS MVC内置对象,获得当前操作者上下文信息
方式2
@Mapping("%AppId%_calculation")
public String calculation(UserContext me, RequestParams params) {
// 参数接收
int number1 = params.getInt("number1"); // 获取整数类型
int number2 = params.getInt("number2"); // 获取整数类型
String sign = params.get("sign", "+"); // 获取字符串类型,第二个参数为默认值,以下方式相同
// Boolean bool = params.getBoolean('paramsName'); // 获取Boolean类型
// Double number = params.getDouble('paramsName'); // 获取浮点型参数
TestWeb web = new TestWeb(me);
return web.calculation(number1, number2, sign);
}
  • 不定义方法参数,动态从RequestParams对象中读取变量
  • 这种方式可以让你的代码更灵活,但不利于重构

e) View层逻辑处理

public class TestWeb extends ActionWeb {
public TestWeb() {
}
public TestWeb(UserContext ctx) {
super(ctx);
}
public String calculation(int number1, int number2, String sign) {
ResponseObject ro = ResponseObject.newOkResponse();
// 处理逻辑
// ro.put("newNum",newNum);
return ro.toString();
}
}

2.1.2 Ajax请求

1)AWS在JQuery ajax基础上对常用异步请求封装,提供4类请求(request、load、post、get),并对底层进行了统一的处理,如异常拦截。方法说明:

  1.awsui.ajax.request

    a) 通过 HTTP 请求加载远程数据,参考jQuery.ajax()。

    b) 参数:url,[settings]。分别是String,Object类型
    url:一个用来包含发送请求的URL字符串。
    settings:AJAX 请求设置。所有选项都是可选的。

  2.awsui.ajax.load

    a) 载入远程 HTML 文件代码并插入至 DOM 中。默认使用 GET 方式 - 传递附加参数时自动转换为 POST 方式

    b) 参数:url,[data,[callback]]。类型:String,Map/String,Callback
    url:待装入 HTML 网页网址。
    data:发送至服务器的
key/value 数据。
    callback:载入成功时回调函数

  3.awsui.ajax.post

    a) 简单POST 请求,成功可调用回调函数

    b) 参数:url,[data],[callback],[type]。类型:String,Map,Function,String
    url:发送请求地址。
    data:待发送 Key/value
参数。
    callback:发送成功时回调函数。
    type:返回内容格式,xml,
html, script, json, text, _default

  4.awsui.ajax.get

    a) 简单GET 请求。请求成功时可调用回调函数

    b) url,[data],[callback],[type]。类型:String,Map,Function,String
    url:发送请求地址。
    data:待发送 Key/value
参数。
    callback:发送成功时回调函数。
    type:返回内容格式,xml,
html, script, json, text, _default。

  5,awsui.ajax.ok

    a) 验证是否为返回状态是否为成功

    b) data:ajax请求后的返回对象

  6.awsui.ajax.responseObject

    a)验证是否为ResponseObject对象

    b)data:字符串或对象。

  7.awsui.ajax.alert

    a)弹出请求提示消息

    b)data,
model, callback
。类型:Object,
boolean,Function
    data: 异步请求返回对象。
    model: 消息提示框的展示模式,是否为模态。
    callback:弹出消息提示后回调函数

示例代码

awsui.ajax.request 示例

awsui.ajax.request({
type: "POST",
url: "./jd?sid="+sid+"&cmd=%AppId%_calculation",
data: "number1=15&number2=1032&sign=+",
ok : function(r) {
//请求处理成功
},
err : function(r){
//请求处理错误
}
});

awsui.ajax.load 示例

awsui.ajax.load("./jd?sid="+sid+"&cmd=%AppId%_calculation", { number1: 15, number2: 1032, sign: '+' }, function(data){
awsui.ajax.alert(data, true, function(){ alert('callback'); });
});

awsui.ajax.post 示例

awsui.ajax.post("./jd?sid="+sid+"&cmd=%AppId%_calculation", { number1: 15, number2: 1032, sign: '+' }, function(data) {
awsui.ajax.alert(data, true, function(){ alert('callback'); });
}, 'json');

awsui.ajax.get 示例

awsui.ajax.get("./jd?sid="+sid+"&cmd=%AppId%_calculation", { number1: 15, number2: 1032, sign: '+' }, function(data) {
if(awsui.ajax.responseObject(data))
awsui.ajax.alert(data, true, function(){ alert('callback'); });
}, 'json');

awsui.ajax.ok 示例

if(awsui.ajax.ok(data))
alert(data['msg']);

awsui.ajax.responseObject 示例

if(awsui.ajax.responseObject(data))
awsui.ajax.alert(data, true, function(){ alert('callback'); });

awsui.ajax.alert 示例

awsui.ajax.alert(data, true, function(){ alert('callback'); });

2)后端接参

@Mapping("%AppId%_calulation")
public String calculation(UserContext me, int number1, int number2, String sign) {
TestWeb web = new TestWeb(me);
return web.calculation(number1, number2, sign);
}

3)View层逻辑处理

public class TestWeb extends ActionWeb {
public TestWeb() {
}
public TestWeb(UserContext ctx) {
super(ctx);
}
public String calculation(int number1, int number2, String sign) {
ResponseObject ro = ResponseObject.newOkResponse();
// 处理逻辑
// ro.put("newNum",newNum);
return ro.toString();
}
}

2.1.3 上传文件

AWS容器对各资源提供沙箱管理,对文件读写提供了一套完善的DC(Doc Center)机制,文件必须通过DC处理器进行处理。AWS对文件上传封装了一个公用的组件,能够满足常用浏览器(IE8+, Firefox,Google Chrome,Safari,平板UC等)的文件上传功能。

a)服务端插件注册和声明

注册DCPluginProfile要声明repositoryName(存放文件的根目录名)和文件处理器(继承com.actionsoft.bpms.server.fs.AbstFileProcessor)。

  • 有关DC开发详细内容,参见《AWS 插件扩展开发参考指南》
  • 有关DC API操作(如读、写文件),参见aws-api-doc提供的DCAPI

b)客户端调用

upfile是AWS UI封装的通用文件上传组件,采用双核技术(IE8/IE9提供Flash模式,对支持HTML5的浏览器采用无插件模式)实现批量文件上传、文件类型过滤、文件大小控制和上传进度控制,对各类浏览器提供了较好的体验支持。

  i)上传组件的资源引用

<link rel="stylesheet" type="text/css" href="../commons/css/awsui.css"/>
<script type="text/javascript" src="../commons/js/jquery/scripts/jquery.js"></script>
<script type="text/javascript" src="../commons/js/awsui.js"></script>

  ii)用JavaScript打开上传对话框

<script type="text/javascript">
$(function(){
//myUpfile对象绑定upfile组件
$("#myUpfile").upfile({
sid: "<#sid>", // 会话ID
appId: "com.actionsoft.apps.poc.plugin", // 应用ID
groupValue: "dir1", // DC大类,建议变量规则
fileValue: "dir2", // DC小类,建议变量规则
numLimit: "2", //最多一次允许上传几个,0(无限制)
filesToFilter : [["Images (*.jpg; *.jpeg; *.gif; *.png; *.bmp)","*.jpg; *.jpeg; *.gif; *.png; *.bmp"]],
repositoryName: "myfile", // 该应用申请的DC名
done: function(e, data){
//事件回调函数
//上传完成后,开始调用导入代码
if (awsui.ajax.ok(data.result.data)) {//判断请求是否执行成功
//可以调用公共方法处理提示信息
awsui.ajax.alert(data.result.data);
//或者自行处理提示信息
//$.simpleAlert('文件上传成功!');
// downloadURL
var url = data.result.data.data.attrs.url;
//如果定义了其他返回的属性,也需要使用data.result.data.data.attrs调用
} else {
// 上传失败,提示出错误信息
awsui.ajax.alert(data.result.data);
}
}
}); });
</script>

  iii)上传按钮的定义

<span id="myUpfile" class="button green" onclick="return false;">上传</span>

上述客户端调用示例,也可从AWS企业应用商店安装扩展插件概念验证应用,所有源码在src目录下

AWS MVC 详解

c)参数说明

  • 属性
Name Type Description Default
sid(*-必须) String 会话ID  
appId(*-必须) String 应用ID  
repositoryName(*-必须) String DC插件定义  
groupValue(*-必须) String 文件大类  
fileValue(*-必须) String 文件小类  
filesToFilter String var filter = [["Images (.jpg; .jpeg; .gif; .png; .bmp)",".jpg; .jpeg; .gif; .png; .bmp"]]; 不过滤,可上传所有文件
sizeLimit number 文件大小限制 25*1024*1024(25M)
numLimit int 上传个数限制 0(无限制)
  • 事件
Name Param Description
add e 事件;data(返回的数据) 文件被添加到上传列表时触发,当返回false时,可阻止上传。
例如: //data.files 为上传文件的数组
add:function(e, data){
     //data.files 为上传文件的数组
     $.each(data.files, function(index, file) {
        // file.name 文件名称 file.size 文件大小 file.type 文件类型
    }) if(size==0){ //空文件不允许上传 return false;
} }
progress e 事件;data(返回的数据) 文件上传中触发
done e 事件;data(返回的数据) 单个文件上传完毕后触发
error e 事件;data(返回的数据) 单个文件上传失败后触发。
可能是web服务器也可能是app服务器造成的失败
complete   文件成功上传结束后触发

2.1.4 下载文件

下载DC仓库内文件的url必须由DCContextgetDownloadURL()获取。

  • 以下是获取文件下载链接的Java示例

    // 构造下载附件的url链接
    UserContext me = getContext();
    String appId = "xxxxxx"; //该App Id名
    String repositoryName = "orderFile"; //该App的DC仓库根目录
    String groupValue = yearMonth; //一级目录为年月,201402
    String fileValue = orderId; //订单Id
    String fileName = "order.jpg"; //文件名
    DCContext context = new DCContext(me, SDK.getDCAPI().getDCProfile(appId, repositoryName), appId, groupValue, fileValue, fileName);
    result.put("url", context.getDownloadURL());
  • JavaScript示例

    window.open(url);
    // or
    window.location.href = url;

2.2 后端处理控制器

就这么简单,提交的请求已经被AWS MVC传输至AWS应用层。

AWS MVC的后端控制器以@Controller注解到普通的Java类,并为该方法增加@Mapping("%Command%")注解即可。控制器会负责将前端cmd参数名与该Java方法的参数名进行匹配和赋值,完成拦截、绑定和执行过程。

下面是一个Controller示例

@Controller
public class ABCController {
// Test1
@Mapping("%AppId%_xxx1")
public String apiTestHome(UserContext me, String p1) {
return "Hi,p1="+p1;
}
//Test2
@Mapping("%AppId%_xxx2")
public String apiInfo(UserContext me, String p2) {
ABCWeb abc= new ABCWeb(me);
return abc.getMainPage(p2);
}
}

注解

控制器只负责拦截、绑定和执行cmd方法,对于该方法的具体实现应交给View层处理,不建议直接在Controller中完成逻辑处理。

注解 说明
@Controller 类注解。声明该类是一个后端处理控制器
@Mapping 方法注解。声明该方法将响应一个前端Web请求,参数值是该cmd值

默认每个请求必须含有sid的会话信息,如开发者要求在无session场景下执行服务端请求,可参考如下语法

@Mapping(value = "%AppId%_xxx3",
session = false,
noSessionEvaluate = "无安全隐患",
noSessionReason = "用于MVC框架稳定性测试")
  • value,cmd的名称
  • session,是否拦截sessionId进行合法性校验
  • noSessionEvaluate,对安全隐患做出评估说明
  • noSessionReason,设计该cmd的原因或功效

被标记为无session验证的请求是非常不安全的,原因是AWS无法识别请求者身份。开发者应审慎评估该请求背后执行的逻辑规则,不会被用于恶意处理

参数映射

以下参数可以出现在方法参数中

参数 说明
UserContext对象类型 【可选】获取AWS用户会话对象
RequestParams对象类型 【可选】获取请求参数,Key为变量名,Value为值
clientIp变量名 【可选】String类型。客户端ip地址
responseType变量名 【可选】String类型。请求结果类型(W/JD/XD...)见Message常量
%变量名% 【可选】cmd的参数名,支持String、Integer、Boolean、Long、Double类型。变量的命名来自具体请求中提供的参数

package包结构命名建议

  • /model/ 存放modelBean类
  • /dao/ 存放DAO类
  • /cache/ 存放cache类
  • /web/ 存放view类
  • /util/ 存放util或service逻辑处理类

注意事项

第一次创建Controller类并进行调试时,需要编译jar文件至该app的lib目录下,否则可能会提示找不到cmd异常。这是一个设计缺陷,我们计划在时间充分的时候修复

下图为实例:

AWS MVC 详解

AWS MVC 详解

AWS MVC 详解

2.3 View视图

不建议直接在处理控制器中完成业务处理过程。

在AWS MVC框架中,View层负责实现具体的业务逻辑,组织处理结果。View提供客户端用户会话、身份及设备等信息,通过继承ActionWeb,完成View的开发。

开发示例

public class ABCWeb extends ActionWeb {
public ABCWeb (UserContext uc) {
super(uc);
}
public String getMainPage(String p2) {
return “Hi,p2=”+p2;
}
}

异常处理

当操作发生错误时,框架将抛出uncheck异常(如AWSDataAccessException),如果你的逻辑没有方案或需求去处理这个异常可以继续向外抛出。

当操作发生参数非法、执行非法等常见View层处理逻辑场景时,建议抛出如下异常(详细请参见异常处理章节)

  • AWSIllegalArgumentException 非法参数异常造成错误的访问请求,对应400错误
  • AWSObjectNotFindException 资源未找到异常,对应404错误
  • AWSForbiddenException 访问被拒绝异常,对应403错误

框架范围之外的util或service层

如果业务处理逻辑相对复杂,建议将逻辑操作封装成util类或service类

识别访问者设备类型

通常你在为PC端浏览器的界面交互编程。如果需要你的程序能够更好的服务于其他移动设备,可以调用UserContext.getDeviceType()方法获取到当前用户的设备类型。

  • LoginConst.DEVICE_PC PC桌面电脑
  • LoginConst.DEVICE_TABLET 平板电脑
  • LoginConst.DEVICE_MOBILE 智能手机

与View相关的常见开发

  • Server端开发
    • 模版渲染(HTML静态文件+标签)
    • ModelBean封装
    • DAO封装
    • Cache封装
  • Web端开发
    • JavaScript
    • CSS
    • 熟悉portal/commons下的各种组件资源,如AWS UI、JQuery Mobile

2.3.1 HTML Document

  AWS MVC提供了页面模版处理框架,通过定义模版变量和程序对变量的处理生成最终页面内容。

  提交请求的响应结果通常是一个完整的HTML Document。在一些前端动态拼装场景,局部DOM结构也可以被独立的定义成模版文件。但有时局部DOM无需使用模版,直接由程序动态组装。

  模版被存放在该应用安装目录的template/page下,通常以html或htm后缀结尾(命名区分大小写)。除内容符合标准HTML、CSS、JavaScript规范外,模版标签变量定义的规则是,将需要程序生成的部分以<#变量名>替换,最终由HtmlPageTemplate.merge()混合成用户浏览器中的html内容。

如果该模版中出现的文字需要进行多语言处理,可以<I18N#变量名>定义,其中变量名是为该应用抽取的多语言配置项的Item的Key。

在View层程序中完成模版处理的示例

public class ABCWeb extends ActionWeb {
public ABCWeb (UserContext uc) {
super(uc);
}
public String getMainPage(String p2) {
Map<String, Object> macroLibraries = new HashMap<String, Object>();
macroLibraries.put("page_title", "hello");
macroLibraries.put("p2", p2);
macroLibraries.put("sid", getContext().getSessionId());
return HtmlPageTemplate.merge("%AppId%", "模版文件名", macroLibraries);
}
}

HTML模板示例

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><#page_title></title>
<!-- 在JS中使用变量,如果需要 -->
<script>
var sid = '<#sid>';
</script>
</head>
<body>
<form action="./w" method=post name=frmMain >
<!-- 在HTML中使用变量,如果需要 -->
p2的值是<b><#p2></b>
</form>
</body>
</html>

模版文件默认编码字符集

utf-8

HTML模版资源引用范围

  • AWS平台Web目录commons/下的js、css、图片等公共资源
  • AWS平台Web目录apps/%appId%/下自定义的资源(appId为本应用的id)
  • 建议使用相对路径,如../apps/xxx、../commons/xxx

2.3.2 非HTML结果

一些来自前端Ajax操作或服务请求通常需要响应一个结构化数据:

  • 一个操作结果是否成功
  • 一个被封装的数据结构

类型支持:

  • JSON
  • XML

ResponseObject

com.actionsoft.bpms.commons.mvc.view.ResponseObject

ResponseObject对象是AWS为开发者提供的一个通用数据对象封装,用于封装一个结构化处理结果。ResponseObject支持三种处理状态:

常量 说明
ResponseObject.SUCCESS ok 被成功处理。对应AWS UI中simpleAlertd的ok或info提示
ResponseObject.WARNING warning 操作发生警告。对应AWS UI中simpleAlertd的warning提示
ResponseObject.ERROR error 操作发生错误。对应AWS UI中simpleAlertd的error提示

状态值可在返回结果的result项检查,这是一个必须结构

msg-信息

当处理成功或发生失败时,应该将进阶的信息反馈给调用者。

//success msg
return ResponseObject.newOkResponse("a订单被取消").toString();
//或者
ResponseObject ro=ResponseObject.newOkResponse();
ro.msg("a订单被取消");
return ro.toString(); //warning msg
return ResponseObject.newWarnResponse("a订单已经发出").toString();
//或者
ResponseObject ro=ResponseObject.newWarnResponse();
ro.msg("a订单已经发出");
return ro.toString(); //error msg
return ResponseObject.newErrResponse("a订单取消失败,原因是xxxx").toString();
//或者
ResponseObject ro=ResponseObject.newErrResponse();
ro.msg("a订单取消失败,原因是xxxx");
return ro.toString();

补充信息可在返回结果的msg项检查,这是一个附加结构

data-数据

以key/value形式由开发者自定义,value可以是一个简单Java对象也可以是一个集合对象。

Map<String, Object> orderDetails = new HashMap<>();
orderDetails.put("orderId", "001");
orderDetails.put("customerId", "999");
orderDetails.put("customerName", "Actionsoft");
orderDetails.put("amount", Double.valueOf("980.01"));
ResponseObject ro = ResponseObject.newOkResponse();
ro.put("enabled", true);
ro.put("orderDetails", orderDetails);
return ro.toString();

数据可在返回结果的data项检查,这是一个附加结构

处理成JSON

默认ResponseObjecttoString()将数据结构拼装成JSON串。

return ro.toString();

含有状态信息的JSON结构

{
data: {
enabled: true,
orderDetails: {
amount: 980.01,
customerName: "Actionsoft",
customerId: "999",
orderId: "001"
}
},
msg: "",
result: "ok"
}
return ro.toDataString();

只有数据的JSON结构

{
enabled: true,
orderDetails: {
amount: 980.01,
customerName: "Actionsoft",
customerId: "999",
orderId: "001"
}
}

处理成XML

return ro.toXML();

含有状态的XML Document片段

<result type="ok" errorCode="" msg="" />

数据来自文件系统

如果你的Java程序读取本地文件系统的文件,建议文件名和内容强制以utf-8读和写。这样做的原因是中文系统的Window默认是936字符集(可以使用chcp命令查看和设置),而大部分OS Server以utf-8进行编码。

如果程序强制以utf-8处理文件,当AWS PaaS在部署一段时间后,客户希望在Windows和Linux之间做迁移时,能够确保用户数据编码格式的一致性。

2.4 业务对象封装

与其他MVC开发框架一样,编写出结构清晰的程序代码,需要对业务实体对象进行属性封装(概念如POJOJavaBean)。

AWS MVC提供了设计业务实体对象的父类ModelBeanIModelBean接口,采用ModelBean封装的业务实体对象,还有以下优势:

  • 提供方法转换成JSON数据结构
  • 提供方法转换成XML数据结构
  • 作为DAO处理的实体表结构对象
  • 作为集群Cache的数据结构对象

TestModel开发示例

public class TestModel extends ModelBean implements IModelBean {
private String id;
private String f1;
private double f2; public TestModel() {
} public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getF1() {
if (f1 == null) {
f1 = "";
}
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public double getF2() {
return f2;
}
public void setF2(double f2) {
this.f2 = f2;
}
}

IModelBean接口声明

/**
* AWS MVC框架中,表示实体业务对象接口
*/
public interface IModelBean extends Serializable {
/**
* 将当前对象转换成json处理对象
*/
public JSONObject toJsonObject();
/**
* 将当前对象转换成json串
*/
public String toJson();
/**
* 将当前对象转化成XML片段
*/
public String toXML();
}

2.5 DAO封装

  AWS的DAO基于对JDBC的直接封装,与当今流行的Hibernate、iBATIS相比,去除了O/R映射关系的直接依赖,并借鉴了Apache DBUtils设计思想,只在需要的场景完成O/R Mapping。

  采用AWS MVC的DAO优势如下:

  • 代码简单、直接,性能高
  • 无需拼写SQL语句,自动提供表查询、删除和更新操作
  • 屏蔽分页技术,自动适应不同数据库的物理分页
  • 提供自定义的RowMapper,将JDBC对象转换成业务实体对象(ModelBean
  • 提供操作复杂数据库操作的DBSql工具类
  • 所有操作受控于AWS SLA的质量和性能监控、告警

DaoObject类和方法介绍

Dao(Data Access Object)是一个设计模式,它是对数据访问的一种抽象。com.actionsoft.bpms.commons.mvc.dao.IDaoObject是AWS设计的数据库访问接口,DaoObject是实现了IDaoObject接口用于访问AWS本地数据库的抽象父类,该类对单主键数据库表的查询/更新/删除等常规操作提供了实现。

TestDao开发示例

  1. 继承ModelBean,实现业务实体对象
  2. 继承DaoObject,实现Dao处理对象

    public class TestDao extends DaoObject<TestModel> {
    
     public TestDao() {
    } /**
    * 插入一条测试记录
    */
    @Override
    public int insert(TestModel model) throws DataAccessException{
    model.setId(UUIDGener.getUUID());
    String sql = "INSERT INTO " + entityName() + "(ID,F1,F2)VALUES(:ID,:F1,:F2)";
    Map<String, Object> paraMap = new HashMap<>();
    paraMap.put("ID", model.getId());
    paraMap.put("F1", model.getF1());
    paraMap.put("F2", model.getF2());
    return DBSql.update(sql, paraMap);
    } /**
    * 更新一条测试记录
    */
    @Override
    public int update(TestModel model) throws DataAccessException{
    if (UtilString.isEmpty(model.getId())) {
    throw new DataAccessException("Method getId() Does Not Allow Empty!");
    }
    Map<String, Object> paraMap = new HashMap<>();
    paraMap.put("F1", model.getF1());
    paraMap.put("F2", model.getF2());
    // 不需要写sql,可调用基类封装的update方法
    return update(model.getId(), paraMap);
    } /**
    * 封装测试
    *
    * @param id
    * @param f2
    * @return
    */
    public int updateF2(String id, double f2) throws DataAccessException{
    Map<String, Object> paraMap = new HashMap<>();
    paraMap.put("F2", f2);
    return update(id, paraMap);
    } /**
    * 封装DBSql测试
    *
    * @return
    */
    public long count() {
    return DBSql.getLong("SELECT COUNT(ID) AS C FROM " + entityName(), "C");
    } /**
    * 封装DBSql测试
    *
    * @param f2
    * @return
    */
    public List<TestModel> queryByF1(String f1) {
    return query("F1=?", f1).orderBy("F2").desc().list();
    } /**
    * 该Dao实现的表名称
    */
    @Override
    public String entityName() {
    return "TEST_DAO";
    } /**
    * 构建该Dao从一条记录转换成对象的映射对象
    */
    @Override
    public RowMapper<TestModel> rowMapper() {
    return new Mapper();
    } /**
    * TestDao Mapper
    */
    private class Mapper implements RowMapper<TestModel> {
    public TestModel mapRow(ResultSet rset, int rowNum) throws SQLException {
    TestModel model = new TestModel();
    try {
    model.setId(rset.getString("ID"));
    model.setF1(rset.getString("F1"));
    model.setF2(rset.getDouble("F2"));
    } catch (Exception e) {
    e.printStackTrace();
    }
    return model;
    } }
    }

    异常处理

    当操作发生错误时,框架将抛出uncheck异常(如AWSDataAccessException),如果你的逻辑没有方案或需求去处理这个异常可以继续向外抛出。

当操作发生参数非法、执行非法等常见Dao处理逻辑场景时,建议抛出如下异常(详细请参见异常处理章节)

  • AWSIllegalArgumentException 非法参数异常造成错误的访问请求,对应400错误
  • AWSObjectNotFindException 资源未找到异常,对应404错误
  • AWSForbiddenException 访问被拒绝异常,对应403错误

默认编码字符集

utf-8

事务处理与资源释放

Spring MVC自动接管了事务与资源释放,这是非常棒的编程体验。为提高性能,目前AWS DAO框架未接管JDBC事务和自动完成Connection释放。

当你的程序需要事务支持时,可以遵循标准的JDBC编程规范,对Connection对象进行事务的开启、回滚或提交。

如果你的程序获得了一个新的Connection(如通过DBSql.open()),那么最终需要你的代码通过DBSql.close()释放这个连接。

物理表

建议使用AWS的BO模型设计和维护你的物理表结构,如果某些表必须由自己的sql创建(不推荐),那么需要遵循App开发规范中约定的表名前缀和sql安装/升级脚本规范。

数据库连接池

AWS MVC的数据库连接池使用了tomcat-jdbc,相关高级参数调优,可修改对应AWS安装目录bin/conf/db_pool.properties文件。

DBSql类和方法介绍

com.actionsoft.bpms.util.DBSql是和AWS数据库交互的工具类,它基于PreparedStatement实现了数据库的查询、插入、更新、批处理,DBSql一般用于DaoObject中。

  • get方法用于简单类型查询
  • query方法用于自定义复杂查询
  • update方法用于数据库的更新/插入/删除
  • batch方法用于批处理
  • open/close数据库连接/释放
  • 其它工具方法
// 查询单个字段
String value_a = DBSql.getString("select a from table_test where id=?", new Object[]{"id1"}); // 查询多个字段
Map<String,Object> value_map = DBSql.getMap("select a,b,c from table_test where id=?", "id1"); // 查询返回自定义对象,MyBean是java类
List<MyBean> list = DBSql.query("select a,b,c from table_test where id=?", new RowMapper<MyBean>() { @Override
public MyBean mapRow(ResultSet rs, int rowNum) throws SQLException {
MyBean mybean = new MyBean();
mybean.setA(rs.getString("a"));
return mybean;
} }, "id1");

详细请参见aws-api-docDBSql

2.6 Cache缓存

AWS MVC的Cache框架支持本地缓存和集群缓存,可以通过扩展AWS平台的Cache插件(Plugin)实现自己的缓存对象。

有关Cache开发详细内容,参见《AWS 插件扩展开发参考指南》

3 异常处理框架

  AWS MVC框架的异常处理过程如下所示

AWS MVC 详解

在上图中,请求者(用户或服务API)被前端控制器封装成指令并传输至AWS服务器,当图中红色、橙色和黄色区域异常发生后,由AWS的顶层异常拦截器捕获,向请求者返回错误消息。

在这个章节中,你将了解如下内容:

  • 错误码定义
  • 抛出异常
  • 处理异常

3.1 错误码

  通过对错误码定义,能够简单的帮助用户或开发者识别和理解异常性质,错误码与错误不是一对一关系,是错误类型的一种抽象代号。

  AWS的错误码参照了HTTP状态码定义。错误码以3位的数字代码表达,所有错误码首数字代表的一类错误。

首数字 说明
4 客户端错误
5 服务端错误
7 服务可用性
8 配合限制和其他

  当请求返回了AWS非预期消息或错误时,除了提供错误码,通常我们会根据具体的场景提供问题概要说明,如果是出错类异常,详细信息一定被记录到AWS的error.log文件。

码表

Code 描述 异常或发生场景
400 错误的参数请求(Bad Request)

通常当缺少必要参数,或者参数值格式不正确时,会返回该错误信息。此时可以查看相关文档确认每个参数的格式是否正确。例如:执行启动流程方法时,未提供processInstId参数

AWSIllegalArgumentException

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构

401 未授权被拒绝(Unauthorized)

当用户提供了无效的session,或者请求的鉴权结果不正确时,会返回该错误信息。

目前只适用于SOAP/REST API的Web层封装的错误代码,不适用于服务器端异常处理

当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构

403 访问被拒绝(Forbidden)

该请求是有效的,但操作是被禁止且不应该再次尝试时,会返回该错误信息。例如:要执行的任务实例已结束

AWSForbiddenException

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构

404 找不到资源对象(Not Find Resource)

当用户试图访问不存在的资源时,会返回该错误信息。例如:要执行的任务实例已不存;账户不存在

AWSObjectNotFindException
405 请求方法不允许(Method Not Allowed)

使用了不支持的请求方法去操作资源时,会返回该错误信息。例如:使用GET请求一个POST操作

* 目前只适用于REST API的Web层封装的错误代码,不适用于服务器端异常处理
408 资源请求超时(Request Timeout)

请求超出了等待时间,会返回该错误信息。例如:在调用AWS的SOAP或REST服务,连接至AWS服务器超时

* 目前只适用于SOAP/REST API的Web层封装的错误代码,不适用于服务器端异常处理
500 内部错误(Internal Server Error)

当服务器执行请求过程中,遇到内部处理错误时,会返回该错误信息。遇到这种错误,请检查AWS的错误日志,及时与我们联系

AWSException
所有继承该异常子类,未实现错误号的异常(getAPIErrorCode())
所有JDK或非AWS异常抛出,被系统捕获的

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构

520 引擎错误(Engine Error)

当服务器执行请求过程中,遇到流程引擎、表单引擎等引擎类错误时,会返回该错误信息。遇到这种错误,请检查AWS的错误日志,及时与我们联系

AWSEngineException
AWSExpressionException
521 传输转换错误(Transfer Error)

当服务器执行请求过程中,遇到导入导出或格式转换错误时,会返回该错误信息。遇到这种错误,请检查AWS的错误日志,及时与我们联系

AWSTransferException
530 应用容器错误(App Container Error)

当服务器执行请求过程中,遇到PaaS应用容器类错误时,会返回该错误信息。遇到这种错误,请检查AWS的错误日志,及时与我们联系

AppContainerException
540 应用商店错误(AppStore Error)

当服务器执行请求过程中,遇到PaaS与AppStore相互处理过程中发生错误时,会返回该错误信息。遇到这种错误,请检查AWS的错误日志,及时与我们联系

AppStoreException
550 业务错误(BPMN Error)

当BPMN引擎执行时由开发者抛出BPMNError业务异常时,会返回该错误信息。遇到这种错误,请与业务开发者联系

BPMNError
590 AWS Instance Server连接失败

当客户端以HTTP(S)经Web连接至AWS服务器时,未能正常建立通信连接时会返回该错误信息。遇到这种错误,可能是AWS服务已停止或Web与AWS之间的网络故障

Web层错误
591 处理AWS Instance Server响应时发生错误

当客户端以HTTP(S)与AWS服务器建立连接后,在发生指令请求等待返回结果发生错误时,会返回该错误信息。遇到这种错误,请检查AWS的错误日志,及时与我们联系

Web层错误
760 服务正在启动(Instance Starting)

当服务器正在启动尚未就绪时,会返回该错误信息。遇到这种错误,请稍后执行

*当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
761 服务正在关闭(Instance Stoping)

当服务器正在关闭时,会返回该错误信息。遇到这种错误,请不要再重复请求,服务器将被关闭

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
762 服务脱机(Instance Offline)

当服务器处于运行中,由运维人员暂停客户端响应时,会返回该错误信息。遇到这种错误,请联系系统管理员

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
770 应用正在启动(App Starting)

当访问的应用正在启动尚未就绪时,会返回该错误信息。遇到这种错误,请稍后执行

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
771 应用正在关闭(App Stoping)

当访问的应用正在关闭时,会返回该错误信息。遇到这种错误,请不要再重复请求,应用将被关闭

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
772 应用脱机(App Offline)

当应用处于就绪但依赖的应用未安装或暂停后,会返回该错误信息,如果该应用未被授权或订阅也会处于772状态。遇到这种错误,排出错误后再启动该应用

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
773 应用已卸载(App Uninstall)

当应用已经被卸载后,会返回该错误信息。遇到这种错误可以忽略,或访问应用管理,将卸载的应用还原

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
774 应用出错暂停(App Failed)

当应用启动失败后,会返回该错误信息。遇到这种错误,请检查该应用的日志,排出错误后再启动该应用

* 当客户端请求AWS服务时,若处于该场景将以该错误码返回到ResponseObject数据结构
800 许可配额限制(Quota Limit)

当资源配额超过许可限制时,会返回该错误信息。例如:超过许可的注册用户数

AWSQuotaException

* 当客户端请求并超过许可证允许的最大并发返回到ResponseObject中

如何使用错误码

  • 如果错误来自AWSException及其子类,可以通过getAPIErrorCode()在Java代码中获取
  • 如果错误来自客户端API,可通过ResponseObject结构的errorCode读取

3.2 异常抛出

  AWS平台提供的异常对象都是uncheck类型,开发者可以根据处理的需要进行捕获,如果开发者非常明确的要抛出这些异常,那么可以不对其处理。

AWSAPIException外,所有AWS内部异常的父类都是AWSExceptione,常见异常如下:

Exception 说明
AWSAPIException API调用异常(uncheck)
AWSException AWS平台异常(以下均内部使用,uncheck)【通用】
AWSClassLoaderException 类加载异常
AWSEngineException 引擎内部异常(流程、表单、报表等,见该类常量)
BPMNDefException BPMN定义异常(设计阶段)
BPMNError BPMN规范要求捕获的异常抛出(运行阶段)
AWSDataAccessException 数据操作异常。如数据库操作、JSON数据操作
AWSIllegalArgumentException 参数校验异常【通用】
AppStoreServiceException 访问AWS企业应用商店异常

常用异常

虽然AWS平台定义了很多异常对象,但是对于应用开发者,只需要熟练掌握以下几个,即可满足大部分开发场景的需要:

  • AWSIllegalArgumentException(400)
  • AWSForbiddenException(403)
  • AWSObjectNotFindException(404)
  • AWSException(500)
//参数合法性异常
throw new AWSIllegalArgumentException("参数1", AWSIllegalArgumentException.FORMAT,"参数必须是0-9数字");
throw new AWSIllegalArgumentException("参数1", AWSIllegalArgumentException.EMPT);
throw new AWSIllegalArgumentException("参数1不能为空"); //操作被拒绝
throw new AWSForbiddenException("流程已经挂起,操作被拒绝");
throw new AWSForbiddenException("ctx类型不当,应给定begin()返回的上下文对象"); //对象不存在
throw new AWSObjectNotFindException("App文件不存在[" + appFile.getPath() + "]");
throw new AWSObjectNotFindException("流程定义未找到。processDefinitionId:" + processDefinitionId);

注意事项

  • 4类异常,通常可以直接抛出给前端处理
  • 5类异常,除非开发者捕获该异常也无法提供解决方案,否则应在上层逻辑捕获并处理
  • 7和8类异常属于底层非预期信息,开发者不必捕获可直接抛出
  • 在捕获异常时,不建议直接捕获Exception,除非你的意图是处理掉所有异常的抛出
  • 如果开发者的程序捕获了所有异常,应当使用e.printStackTrace(System.err)记录日志

3.3 异常处理

当异常被AWS MVC顶层框架捕获后,会根据cmd请求类型处理成客户端能够理解的文档格式。

请求类型 格式
./w HTML Document
./jd JSON Document
./xd XML Document

Java Exception处理

当发生底层Java异常或其他非AWSException异常时,AWS MVC将该异常封装成500错误。

异常日志

捕获的异常被记录至AWS logs目录下

  • error.log(单一部署)
  • error-%AWS节点名%.log(集群部署)

HTML Document警告页面

AWS MVC 详解

JSON Document数据结构

AWS MVC 详解

XML Document数据结构

AWS MVC 详解

4 国际化

4.1 多语言

AWS MVC框架对HTML/JavaScript多语言和Java程序多语言提供了一整套完善的开发方案,以下为AWS MVC的多语言处理架构。

AWS MVC 详解

AWS MVC每次接收到用户请求时,在会话对象(UserContext.getLanguage())提供了该用户的界面语言信息,AWS MVC为应用提供了两种常见解决方案:

Java程序

通过SDK.getAppAPI().i18nValue()获得指定用户界面的多语言资源配置

SDK.getAppAPI().i18NValue("com.actionsoft.apps.poc.api", me, "info1")

HTML模版

在HTML页面或JavaScript中出现的多语言标签,使用<I18N#变量名>替代,其中变量名为多语言资源配置ItemKey

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title><I18n#PageTitle></title> <script>
var var1 = "<I18n#Var1>";
var var2 = "<I18N#Var2>";
alert(var1);
alert(var2);
</script>
</head>
<body>
Hi,<I18n#PageTitle>
</body>
</html>

多语言资源文件

遵循AWS PaaS对App的资源定义规范,每个AWS应用的多语言资源配置文件被存放在应用安装目录/i18n/下。

该目录允许存在1个或多个符合Schema规范的xml文件,建议为自己的应用创建一个名为resource.xml的资源配置文件。

说明
item/key 多语言资源名,同个App下不允许重复
item/cn 中文简体
item/en 英文
item/big5 中文繁体
item/%lang% 其他扩展的语言名

resource.xml示例

<locale-config>
<lang>
<item key="info1">
<cn><![CDATA[这是中文简体语言]]></cn>
<en><![CDATA[This is the English language]]></en>
<big5><![CDATA[這是中文繁體語言]]></big5>
</item>
<item key="PageTitle">
<cn><![CDATA[这是标题]]></cn>
<en><![CDATA[This is Title]]></en>
<big5><![CDATA[這是標題]]></big5>
</item>
<item key="Var1">
<cn><![CDATA[这是变量1]]></cn>
<en><![CDATA[This is Var1]]></en>
<big5><![CDATA[這是變量1]]></big5>
</item>
<item key="Var2">
<cn><![CDATA[这是变量2]]></cn>
<en><![CDATA[This is Var2]]></en>
<big5><![CDATA[這是變量2]]></big5>
</item>
</lang>
</locale-config>

多语言资源文件管理

建议访问AWS企业应用商店,安装“多语言管理工具”。

该工具提供了可视化的多语言配置工具,能够极大提高翻译人员的工作效率。

如何扩展更多种语言

默认AWS PaaS只提供了中文简体、英文和中文繁体三种界面语言,可以安装“多语言管理工具”扩展更多种语言。

以下代码打印出当前AWS PaaS支持的语言集

List<LanguageModel> langs = SDK.getPlatformAPI().getlanguages();
for (LanguageModel lang : langs) {
System.out.println(lang.getName());
}

4.2 时区和工作日历

对于跨国企业/组织或长期国际差旅时,用户需要根据工作地点的时区获得与当地时间一致的日期信息,并遵守当地的节假日和企业工作时间要求。

在AWS MVC框架中,时区主要解决符合用户当地时间的日期显示;工作日历主要解决对员工有效工作时间的计算,如流程执行效率,并提供API来处理业务需求,如差旅请假时长计算。

AWS是如何处理时区的

时区和工作日历的管理和设置

工作日历API接口

5 附录1-编程资源

AWS MVC是一个开放的编程架构,你可以方便的将自己需要的工具包加入到自己的App中使用:

  • 三方Jar类库 存放到App安装目录的lib下
  • 三方JavaScript、CSS库 存放到Web层的apps/%appId%/

AWS PaaS提供的开源Jar类库

可在你的程序中直接使用AWS PaaS自带的一些第三方开源类库,这些Jar文件存放在AWS安装目录的bin/libbin/jdbc下。

类库 说明
commons-* Apache提供的若干工具类
barcode4j 条形码生成
cajo RMI工具类
csv CSV数据处理工具
xalan/... XML数据处理
json-lib JSON数据处理
poi Office文件处理
httpclient HTTP客户端
itext PDF处理
sigar 系统性能监控
log4j Java日志处理系统
cxf Web服务处理框架
... ...

AWS PaaS封装的Web UI

这些组件全部基于JQuery和JQueryMobile底层框架封装,使用这些UI有助于开发的应用界面与AWS其他应用保持一致的交互习惯。详细说明参见AWS UI章节

5.1 SDK API

AWS PaaS作为App运行的容器环境和资源平台,为App开发者提供了丰富的API,这些API可以直接在你的Java程序中使用。

AWS MVC 详解

对于API详细说明及用法,参见aws-api-doc(一个Java API Doc)。

MVC编程常用API

说明
SDK SDK API的总入口
ActionWeb Web(View)请求处理的父类
ModelBean 业务实体对象父类
DaoObject DAO对象父类
ResponseObject 返回JSON、XML结构化数据,如操作状态、业务数据
UserContext 用户会话,获得用户会话串、登录IP、语言、设备类型、用户组织等
AppAPI 多语言处理、跨应用的ASLP调用、应用日志
ORGAPI 访问组织结构相关接口
PermAPI 访问AWS权限相关接口
PortalAPI 访问或构建门户应用相关接口
RuleAPI 规则处理接口
DCAPI 文件处理接口

平台系统常用API

说明
PlatformAPI 查询平台及服务状态接口
ConfAPI 查询平台常用配置参数接口
SLAAPI 监控告警接口

BPM引擎常用API

说明
ProcessAPI 流程实例控制接口
TaskAPI 任务实例控制接口
ProcessExecuteQuery 引擎执行结果查询接口
ProcessQueryAPI 流程实例查询接口
TaskQueryAPI 任务查询接口
HistoryTaskQueryAPI 历史任务查询接口
DelegationAPI 任务委托/代理接口
RepositoryAPI 模型资源库访问接口
BOAPI BO操作接口
BOQueryAPI BO查询接口

监听器常见接口(事件编程)

说明
ValueListener 取值类监听器父类
ExecuteListener 执行类监听器父类
InterruptListener 中断类监听器父类

注意事项

  • 不推荐直接调用aws-api-doc未提供的接口方法
  • SDK API适用于在AWS Server端执行,不能用于Web层开发。如果你在Web层使用了不符合AWS MVC框架的开发模式,可以通过AWS CC发布Server API或封装ASLP服务来访问AWS Server端操作

5.2 AWS UI

为统一PaaS用户的交互体验(UX)和界面展示(UI),AWS MVC框架为开发者提供了一套基于JQuery封装的JavaScript UI组件库。目前这个UI库仍处在完善中,如果增强了用户体验或封装了新的UI类型,欢迎你的贡献!请邮件联系liujx@actionsoft.com.cn

了解每个AWS UI组件的文档、示例,可本地启动AWS服务后,在浏览器输入以下url访问。

http://localhost:8088/portal/commons/js/jquery/demo/index.html

在你的页面引入AWS UI

以下代码可将JQuery、AWS基本UI加入到你的页面中。对于部分专用UI,请参见相关示例引入特定的资源

<link rel="stylesheet" type="text/css" href="../commons/css/awsui.css">
<script type="text/javascript" src="../commons/js/jquery/scripts/jquery.js"></script>
<script type="text/javascript" src="../commons/js/awsui.js"></script>

5.3 量命名词汇表

为规范App开发者对专业变量的命名和识别,在这里给出一个词汇表参考。

设计期

命名参考
存储模型ID boDefId
表单模型ID formDefId
表单子表模型ID formItemDefId
流程模型ID processDefId
节点模型ID 通用:activityDefId
特定:userTaskDefId、serviceTaskDefId..
报表模型ID reportDefId
DW模型ID dwDefId
各种Context对象 如UserContext、TaskBehaviorContext...

建议:单独出现时命名变量为ctx或context,同时出现多个不同类型的Context时,使用userContext、taskContext区分

登录账户名 uid、uids(多个),对应ORGUSER的USERID字段
单位ID companyId
部门ID departmentId
角色ID roleId
小组ID teamId
小组成员ID teamMemberId

运行期

命名参考
流程实例ID 建议processInstId,可以使用processInstanceId
流程实例对象 建议processInst,可以使用processInstance
任务实例ID 建议taskInstId,可以使用taskId、taskInstanceId
任务实例对象 通用:建议taskInst,可以使用task、taskInstance
特定:建议historyTaskInst,可以使用historyTask、historyTaskInstance
BO表ID boId
BO表与流程实例绑定 通用:bindId
特定:纯流程驱动场景下,也可使用processInstId

6 附录2-程序文件

应用的安装、部署和运行由AWS PaaS自动化完成,但在开发阶段需要开发者了解这些资源结构。

Web层资源

Web层是指部署在Web Server(如Tomcat)的资源。AWS PaaS为每个App分配了独立的目录,被称为Web层根资源根目录。

你可以在这个目录中规划自己的js、css等资源结构。

//存放Web参数解析配置
%AWS-HOME%/webserver/webapps/portal/apps/%appId%/action.xml
//存放css
%AWS-HOME%/webserver/webapps/portal/apps/%appId%/css/
//存放js
%AWS-HOME%/webserver/webapps/portal/apps/%appId%/js/
//存放图片
%AWS-HOME%/webserver/webapps/portal/apps/%appId%/img/
//存放jsp程序(*不允许jsp直连数据库的开发模式,使用MVC cmd开发)
%AWS-HOME%/webserver/webapps/portal/apps/%appId%/jsp/
//自定义
%AWS-HOME%/webserver/webapps/portal/apps/%appId%/.../
  • %AWS-HOME%是AWS PaaS的安装根目录
  • %appId%是应用的Id名

App层资源

App层是指部署在AWS Server的资源。AWS PaaS为每个App分配了独立的目录,并通过安装、卸载库进行管理。

在开发的应用在容器仓库里处于install状态,与MVC编程相关的目录资源如下

//存放App的配置描述
%AWS-HOME%/apps/install/%appId%/manifest.xml
//存放App的LOGO
%AWS-HOME%/apps/install/%appId%/icon16.png
%AWS-HOME%/apps/install/%appId%/icon64.png
%AWS-HOME%/apps/install/%appId%/icon96.png
//存放程序编译的jar文件和第三方类库
%AWS-HOME%/apps/install/%appId%/lib/
//存放HTML模版
%AWS-HOME%/apps/install/%appId%/template/page/
//存放多语言资源
%AWS-HOME%/apps/install/%appId%/i18n/resource.xml

7 附录3-开发工具

AWS MVC的开发者可以根据自己的编程习惯选择开发工具。

AWS Developer

当安装了AWS PaaS开发环境后,会为开发者提供一个专有的开发工具。该工具基于Eclipse IDE封装,提供了专有的扩展插件,能够更直观、高效的进行AWS App开发。

//开发工具根目录
%AWS-HOME%/developer/

使用AWS Developer的优点

  • 无需配置即可在工程代码中启动、调试、编译和分发操作
  • 根据Controller类自动生成Web端接参配置文件,提高工作效率
  • 向导式开发
    • 创建App应用
    • 创建cmd请求
    • 创建ModelBean
    • 创建Dao
    • 创建Cache
    • 管理系统Jar包依赖
    • 创建各种AWS扩展插件...
  • 提供对App各类参数的配置管理
  • 内嵌支持SVN代码版本管理

Eclipse

对于熟悉AWS PaaS和App应用资源配置结构的开发者,也可以直接使用Eclipse完成所有的任务目标。

  1. 新建Java普通工程
  2. Java Build Path>Libraries下创建aws_lib库,增加以下资源
    %AWS-HOME%/bin/lib/*.jar(含子目录)
    %AWS-HOME%/bin/jdbc/*.jar
  3. 启动aws-infrastructure-common.jarStartUp
    com.actionsoft.bpms.server.AWSServer.StartUp
  4. 指定启动选项中Working directory目录
    %AWS-HOME%/bin

developer.csr

在你的团队正式开发应用前,应获得应用开发者证书(ISV)。证书文件路径如下

%AWS-HOME%/apps/developer.csr

8 微信企业号框架

微信企业号框架基于AWS MVC框架,将请求根据请求类型(URL跳转、消息/事件)交由不同的Servlet处理,再根据请求的映射规则分发给相应的后端逻辑控制器进行处理。

AWS MVC 详解

上图中的三个Servlet(AWS Web Server / 一般请求Servlet,WS Web Server /重定向Servlet,WS Web Server /回调Servlet),后端处理控制(AWS App Server / Controller)和微信企业号管理平台是微信企业号的核心通信框架,AWS微信App是开发者实现业务逻辑的区域,主要元素描述如下:

说明
AWS Web Server 安装有AWS Portal的标准Servlet容器,例如:Tomcat、WebLogic
AWS App Server 安装有AWS Server的应用服务器,所有的业务逻辑在这里处理
一般请求Servlet 接收URL跳转请求,收到请求后会检查是否带有包含用户认证信息的Cookie,如果包含则封装后转发给后端控制器,若不包含则构造微信OAuth验证链接,重定向到下面的重定向Servlet
重定向Servlet 处理微信OAuth验证请求,封装后转发给后端控制器,最终交由微信管理平台处理并返回验证结果。如果验证通过,将验证信息写入Cookie,最后重定向到原始URL
回调Servlet 微信企业号应用的回调地址指向此处。处理微信消息/事件请求,封装后转发给后端控制器,再由微信管理平台转发到指定的AWS微信App处理请求
后端处理控制器 通过注解拦截到方法,绑定逻辑处理程序
微信企业号管理平台 管理微信企业号应用,可为企业号应用设置、绑定菜单和指定处理消息/事件的AWS 微信App
AWS微信App 实现业务逻辑,一般包含H5页面(View视图组装,Model/Dao/Cache模型,Template模板),和消息/事件处理实现类。

9 文档历史记录

下表说明了对该文档所做出的重要更改。

类型 说明 修改日期
首次发布 这是AWS MVC框架参考指南的首次发布 2015年01月22日
上一篇:github文档


下一篇:git的安装以及生成ssh key