泽元前端工程师对接后端指南

目录

一、安装配置

JDK安装

Tomcat安装

Eclipse安装

检出工程

运行工程

二、基本机制

UI类的基本结构

方法的编写

JSON输出方法

URL映射的方式

三、JS中调用后台方法

$.ajax()方法

四、ZHTML标签调用后台方法

<z:init>

<z:select>

<z:radio>

<z:checkbox>

<z:list>

<z:datalist>

五、自动映射

JSON文件和URL映射

映射机制

Server.sendRequest()自动映射到JSON文件

$.ajax()自动映射到JSON文件

Restful映射到json文件

<z:list>的使用

<z:datagrid>的使用

<z:datalist>的使用

<z:tree>的使用

<z:select>、<z:radio>、 <z:checkbox>的使用

六、简单UI方法编写

模拟数据的构造

模拟数据的增删改查

<z:list>的使用
<z:datalist>的使用
<z:datagrid>的使用

<z:tree>的使用
<z:select>、<z:radio>、 <z:checkbox>的使用

Server.sendRequest()的使用
jQuery.ajax()调用UI方法

Restful风格实现增删查改

一、安装配置

* JDK安装
  1. 默认方式安装JDK的exe文件即可,如果手上没有JDK安装程序可以去oracle官网下载
    http://www.oracle.com/technetwork/java/javase/archive-139210.html
  2. 安装完JDK后需要配置环境变量JAVA_HOME以及Path。

    右键“我的电脑”→属性→高级系统设置→高级→环境变量

image

点击环境变量→系统变量

新建环境变量JAVA_HOME的值填写的是JDK软件安装的目录,安装JDK时可以选择安装目录,如果没选择,默认在C:\Program Files目录下

image

修改环境变量Path,在Path中添加路径,如下图:

image

* Mysql安装
  1. mysql安装请参考官网文章
    http://www.zving.com/c/2017-03-10/261475.shtml

  2. mysql安装好了之后,找到mysql安装目录的my.ini文件,参照官网文章修改参数: http://www.zving.com/c/2013-10-17/257392.shtml

* Tomcat安装

tomcat一般使用压缩版本,只要解压压缩包到指定目录下即可。解压之后要测试是否可用,在解压的目录下找到bin目录,点击startup.bat文件运行tomcat,弹出控制台窗口,如果没有出现明显的异常,tomcat可用。

* Eclipse安装

解压Eclipse压缩包文件到指定目录,点击解压后目录下的eclipse.exe运行程序,运行正常时,会弹出eclipse初次使用的界面,选择workbrech图标进入工作台界面。在开始开发之前,Eclipse还需要做一些基础配置:JRE配置、Tomcat引入、开发工具ZDeveloper的安装以及JAVA格式模板导入。
1. JRE配置

选择eclipse菜单选项Window→Preferences→Java→Installed JREs,在这里配置在开发过程中需要用到的JDK。

![image](http://www.zving.com/upload/resources/image/2017/03/12/8287.png)

点击“Add”按钮,在弹出的对话框选择Standard VM选项,点击“Next”按钮,在弹出的对话框上点击“Directory”按钮,选择JDK的安装目录,点击“Finish”按钮,完成JRE的配置。

![image](http://www.zving.com/upload/resources/image/2017/03/12/8288.png)
  1. Tomcat引入

    选择eclipse菜单选项Window→Preferences→Server→Runtime Environments,在这里配置开发过程中需要用到的Tomcat。

    image

    点击“Add”按钮,在弹出对话框中选择所要配置的tomcat版本,点击“Next”按钮,选择tomcat的安装目录,还可以为tomcat指定运行的JDK,然后点击“Finish”,完成Tomcat的引入

    image

  2. 开发工具ZDeveloper安装

    开发工具ZDeveloper安装请参考官网文章http://www.zving.com/c/2015-11-19/260084.shtml

  3. JAVA格式模板导入

    编写Java代码的过程中,通常还会用到格式化的功能,一般是组合键CTRL+Shift+F,格式化按照指定模板的样式进行。

选择eclipse菜单选项Window→Preferences→Java→Code Style→Formatter

image

点击“Import”按钮,选择格式文件formatter.xml,点击“OK”按钮完成格式模板的导入。

  1. ZHTML文件语法加亮

    zhtml文件语法加亮请参考官网文章http://www.zving.com/c/2013-10-17/257397.shtml

* 检出工程
  1. 将SVN资源库显示在常用tab上,选择eclipse菜单选项Window→Show View→Other→SVN,选择SVN资源库,点击“OK”按钮,完成操作。

    image

  2. SVN资源库的菜单界面,右键新建“资源库位置”,输入工程SVN地址,点击“Finish”按钮完成工程SVN资源位置的添加。

    image

  3. 右键资源库位置,选择“检出为”,弹出的对话框信息确认,点击“Finish”按钮,检出工程。

    image

* 运行工程
  1. 参照检出工程步骤,需要在常用菜单上添加Server
  2. 在Server界面,右键New→Server,弹出新建Server对话框,选择对应tomcat版本,填写server name信息(用来区分不同工程的server),然后点击“Finish”按钮完成Server的新建。

    image

  3. 在Server界面双击刚才新建的Server,在弹出的Server配置界面上选择配置Modules

    image

  4. 点击“Add External Web Modules”按钮,弹出配置工程地址和应用别名的对话框,Document base选择工程UI目录,Path配置访问的应用path,比如这里是zcms。点击“OK”按钮完成Server的应用信息配置。

    image

  5. 点击Server界面的运行按钮(小虫图标或者播放按钮图标),运行应用。开发建议常用调试模式(小虫图标)。

    image

  6. 访问应用,一般在默认情况下本地方访问为http://localhost:8080/应用path,按照4的配置,我们这里的访问地址为:http://localhost:8080/zcms。

二、基本机制

* UI类的基本结构

UI类是和前台页面对应的后台业务处理程序。UI类的基础对象有请求数据对象Request、响应数据对象Response、Cookies,前后台交互时,取值和返回参数值同前台JS方式很相似。取得前台传值,字符串可以使用$V(“字段名”),数字可以使用$L(“字段名”)等方式,返回值可以使用$S(“字段名”,参数值),一些对象的详细内容可参考官网文章http://www.zving.com/c/2013-10-18/257404.shtml
一个最基本UI类应该包括几个部分:继承UIFacade、定义方法、声明前端调用URL、前台传参获取、响应参数设置、权限申明:

  //类别名命名
  @Alias("HelloWorld")
  public class HelloWorldUI extends UIFacade {
      //权限申明,表示无需登录即可访问的方法
      @Priv(login=false)
      public void sendMsg(){
          //后台获取前台传值方式类似于$V(Name)
          String msg=$V("Msg");
          //设置返回参数
          $S("Country","China");
          //反馈给前台调用成功信息
          success("Congratulations!Message:"+msg+"");
     }
  }
* 方法的编写

UI的方法一般为public公共方法,分为2类:一类是不带参数的用于发送ajax请求处理业务逻辑,例如常用的数据添加、修改、删除;一类是带参数的用于数据展示或者动态页面,通常带的参数有:DataGrid(表格数据对象)、DataList(数据列表对象)、ZAction(动态页面)、UploadAction(上传)、TreeAction(树)。一个基本的方法包含几个要素:权限声明、方法定义、前台传参获取、响应参数设置。有时候方法还会自带别名定义。

      @Priv(login=false)  //权限申明,表示无需登录即可访问的方法
      @Alias("sendmsg")  //方法前台调用的别名设置
      public void sendMsg(){
          //后台获取前台传值方式类似于$V(Name)
          String msg=$V("Msg");
          //设置返回参数
          $S("Country","China");
          //反馈给前台调用成功信息
          success("Congratulations!Message:"+msg+"");
     }
* JSON输出方法

在一些使用场景下,比如接口调用,我们还需要用到JSON格式数据的输出,需要用到2个类JSONObject,JSONArray。
1. JSONObject类,类的一个简单示例如下:

        //定义一个JSONObject对象,并且设置id和标题,在控制台输出
        JSONObject o = new JSONObject();
        o.put("id", 12);
        o.put("title", "示例");
        System.out.println(o.toString());
        

执行结果:

{"id":12,"title":"示例"}

常用的方法还有get(String key)、getString(String key)、getJSONObject(String key)、getJSONArray(String key)、toString()

  1. JSONArray类,类的一个简单示例如下:
//将取得的文章内容数据加入到JSONArray对象中
	JSONArray a = new JSONArray();
	DAOSet<ZCContent> set = new ZCContent().query(10, 0);
	for (ZCContent content : set) {
		JSONObject o = new JSONObject();
		o.put("id", content.getID());
		o.put("catalogid", content.getCatalogID());
		o.put("title", content.getTitle());
		o.put("author", content.getAuthor());
		o.put("summary", content.getSummary());
		a.add(o);
	}
	

执行结果:

[{"id":33,"catalogid":9227,"title":"2012诺贝尔奖","author":"admin","summary":""},{"id":120,"catalogid":9205,"title":"中国海军女舰员学习海军专用旗语信号","author":"admin","summary":"中国海军女舰员学习海军专用旗语信号"}]

常用的方法还有getJSONObject(int index)、toString()、getJSONArray(int index)、length()。

3.JSONObject和JSONArray可以嵌套使用,下面是一个使用实例:

//调用接口取得文章数据
    @Priv(login = false)
    @Alias(value = "articlelist", method = "get")
    public void getArticleList(ZAction za) {
    	try {
    		DAOSet<ZCContent> set = new ZCContent().query(10, 0);//取得数据
    		JSONObject jo = new JSONObject();
    		jo.put("total_count", set.size());
    		JSONArray a = new JSONArray();
    		for (ZCContent content : set) {
    			JSONObject o = new JSONObject();
    			o.put("id", content.getID());
    			o.put("catalogid", content.getCatalogID());
    			o.put("title", content.getTitle());
    			o.put("author", content.getAuthor());
    			o.put("summary", content.getSummary());
    			a.add(o);
    		}
    		jo.put("items", a);
    		$S("data", jo);//最后将封装好的json格式数据设置到Resopnse中。
    	} catch (Exception e) {
    		za.setStatusCode(500);
    		fail(e.getMessage());
    	} finally {
    		Restful.writeJSON(this, za);
    	}
    }
* URL映射的方式

框架前端调用后台UI方法时,对应的URL实际上是通过后台方法的别名来声明的。有2种形式,一种是通过类别名+方法名,一种是直接在方法上声明别名。

  //类别名命名
  @Alias("HelloWorld")
  public class HelloWorldUI extends UIFacade {
      //权限申明,表示无需登录即可访问的方法
      @Priv(login=false)
      public void sendMsg(){
          //后台获取前台传值方式类似于$V(Name)
          String msg=$V("Msg");
          //设置返回参数
          $S("Country","China");
          //反馈给前台调用成功信息
          success("Congratulations!Message:"+msg+"");
     }
  }

上述代码在前端调用方法时的URL为HelloWorld.sendMsg,方式是类别名+方法名。

      @Priv(login=false)  //权限申明,表示无需登录即可访问的方法
      @Alias("sendmsg")  //方法前台调用的别名设置
      public void sendMsg(){
          //后台获取前台传值方式类似于$V(Name)
          String msg=$V("Msg");
          //设置返回参数
          $S("Country","China");
          //反馈给前台调用成功信息
          success("Congratulations!Message:"+msg+"");
     }

上述代码在前端调用方法时的URL为sendmsg,方式是直接取方法定义的别名。

三、JS中调用后台方法

参数 数据类型 必须 说明
methodName String 后台方法名或方法别名,书写形式形如“包名.类名.方法名”
dataObj Object 通常是通过Form.getData()方法得到的一个含键值对的普通对象。
func function 数据获取后的回调函数,返回的数据作为这个函数的参数传入

Server.sendRequest(methodName, dataObj, func)方法是对$.ajax方法的套装,主要用于与泽元后端UI类进行数据交互。
使用示例参考知识库文章 http://www.zving.com/c/2013-10-09/257336.shtml

Server.sendRequest与$.ajax的区别在于
- Server.sendRequest总是请求 ajax/invoke 接口,这个接口再去调用_ZVING_METHOD参数对应的后台方法,这些后台方法所在的类**必须**继承com.zving.framework.UIFacade,我们称之为“UI方法”,后台方法返回的数据通过$S方法put到一个DataCollection中,后端框架会自动将这个DataCollection序列化为JSON字符串返回给前台。
- Server.sendRequest总是用POST方法发送数据
- Server.sendRequest发送的数据总是包含以下几个参数及对应的值 _ZVING_METHOD_ZVING_URL_ZVING_DATA_ZVING_DATA_FORMAT
- Server.sendRequest的参数dataObj被序列化为JSON格式字符串后设置为参数_ZVING_DATA的值, ajax/invoke 接口会将_ZVING_DATA的值反序列化为JSONObject对象
- Server.sendRequest可以跨域请求泽元后台方法,使用的是window.name跨域方案,这个跨域方案是兼容IE6/7/8的。

$.ajax()方法

使用方式参考jQuery手册 http://hemin.cn/jq/jQuery.ajax.html
见上一节提到的$.ajax与Server.sendRequest的区别,比外还要注意
- $.ajax()直接请求后台severlet,而不是通过ajax/invoke 接口去调用。这个后台方法所在的类**一般**继承com.zving.framework.UIFacade,并且有一个com.zving.framework.core.handler.ZAction类的实例作为参数传给这个后台方法。后台方法返回的数据不一定为JSON字符串,后端框架也没有对这个后台方法返回结果序列化为JSON字符串的操作。所以要返回JSON数据,需要显式地输出JSON字符串,如 zaction.writeJSON(JSON.parseJSONObject(jsonObjectForResult))

四、ZHTML标签调用后台方法

zhtml文件可视同为模板,只是泽元框架的模板实现比前端常用的模板引擎 Handlebars 功能更为强大,类似于Swig,可添加带有逻辑性的,功能复杂的自定义标签,下面介绍在模板中常用的z标签。

<z:init>

这个标签没有对应的前端JS组件,它通常用来为页面准备初始化数据。这个后台方法并不直接返回数据,而是将数据用$S方法put到一个DataCollection中,框架自动替换页面上的占位符为这个DataCollection中对应的值。
参考知识库文章 http://www.zving.com/c/2013-10-09/257303.shtml

<z:select>

这个标签最终会渲染为页面上的一个自定义下拉列表控件。<z:select>标签的 method 属性很常用,它指定了渲染列表所需要的数据的来源方法。这个后台方法返回的数据一般是由Mapx转成的DataTable————只有两列数据。
参考知识库文章
http://www.zving.com/c/2013-10-09/257300.shtml
http://www.zving.com/c/2013-10-09/257358.shtml

<z:radio>

这个标签最终会渲染为页面上的一组单选按钮。<z:radio>标签的 method 属性很常用,它指定了单选按钮组所需要的数据的来源方法。这个后台方法返回的数据一般是由Mapx转成的DataTable————只有两列数据。

参考知识库文章
http://www.zving.com/c/2013-10-09/257314.shtml

<z:checkbox>

这个标签最终会渲染为页面上的一组多选按钮。<z:checkbox>标签的 method 属性很常用,它指定了多选按钮组所需要的数据的来源方法。这个后台方法返回的数据一般是由Mapx转成的DataTable————只有两列数据。
参考知识库文章
http://www.zving.com/c/2013-10-09/257315.shtml

<z:list>

这个标签没有对应的前端JS组件,它通常用来循环输出数据。 <z:list>标签的 method 属性是必须的,它指定了数据的来源方法。这个后台方法返回的数据是一个DataTable
参考知识库文章
http://www.zving.com/c/2013-10-09/257313.shtml

<z:datalist>

这个标签最终会渲染为页面上的一个数据列表控件。数据列表控件可动态刷新数据,有分页功能。
<z:datalist>标签的 method 属性是必须的,它指定了渲染列表所需要的数据的来源方法。这个后台方法返回的数据是一个DataTable
> 注意:因为DataList翻页时会更新父元素的innerHTML,所以强烈建议datalist的父元素外包裹一个非表格元素(如DIV),否则可能引起邻近的控件自定义的属性及事件丢失。

参考知识库文章
http://www.zving.com/c/2013-10-09/257302.shtml
http://www.zving.com/c/2013-10-09/257351.shtml

<z:tree>

这个标签最终会渲染为页面上的一个树形控件。树形控件可动态刷新数据,有惰情加载子节点、级联选择功能。
<z:tree>标签的 method 属性是必须的,它指定了渲染树形控件所需要的数据的来源方法。 这个后台方法返回的数据是一个DataTable
参考知识库文章
http://www.zving.com/c/2013-10-09/257309.shtml
http://www.zving.com/c/2013-10-09/257361.shtml

<z:datagrid>

这个标签最终会渲染为页面上的一个数据表格控件。数据表格控件可动态刷新数据,有分页功能。
<z:datagrid>标签的 method 属性是必须的,它指定了渲染表格所需要的数据的来源方法。这个后台方法返回的数据是一个DataTable
参考知识库文章
http://www.zving.com/c/2013-10-09/257301.shtml
http://www.zving.com/c/2013-10-09/257344.shtml

五、自动映射

* JSON文件和URL映射

映射机制

框架启动时会自动扫描UI/_json目录下的json文件,将json文件名映射为对应的访问路径,例如Mock.User.add.json文件,此文件的url映射为/Mock/User/add
1. 新建工程mockweb,导入插件mockstudy,项目结构如下所示
image
2. 在_json目录下新建Mock.User.add.json文件(存在则不需要新建,下同),此文件的url映射为Mock/User/add,json文件内容不会修改。
3. json文件的格式如下,

{
	"GET": //提交方式:GET,PUT,POST,DELETE,*
	{
		"type": "datatable",//数据类型:datatable,map
		"rootText": "组织机构",//根结点显示名称
		"restful":true,//是否为restful:true,false
		"data": [] //数据
	}
}
  1. 下载(示例代码(http://pan.baidu.com/s/1nuW0yWL)))为本文档的前后台交互的示例代码,部署工程,配置tomcat的运行端口8080,应用名mockweb,输入地址
    http://localhost:8080/mockweb/mockstudy/index.zhtml
    运行结果
    image

    * Server.sendRequest()自动映射到JSON文件

  2. 在/UI/_json目录下新建Mock.User.add.json

    {
    "*": 
    {
    	"type": "map",
    	"data": 
    	{
    		"status": 1,
    		"message": "SendRequest添加成功"
    	}
    }
    }
    
  3. 在/UI/mockstudy/json目录下新建javascript.zhtml,编写js代码

    function sendRequest() {
    	var data = {
    		"Name" : "钱七",
    		"Gender" : "Male",
    		"BirthDate" : "2007-07-07"
    	};
    	Server.sendRequest("Mock.User.add", data, function(response) {
    		Dialog.alert(response.message);
    	});
    }
    
  4. 运行结果
    image
* $.ajax()自动映射到JSON文件
  1. 在/UI/_json目录下新建Mock.User.ajaxAdd.json

    {
    "POST": 
    {
    	"type": "map",
    	"data": 
    	{
    		"status": 1,
    		"message": "AJAX添加成功"
    	}
    }
    }
    
  2. 在/UI/mockstudy/json目录下javascript.zhtml,编写js代码
    ```
    function ajax() {
    $.ajax({
    url : “../../Mock/User/ajaxAdd”,
    type : “POST”,
    success : function(response) {
    Dialog.alert(response.message);
    }
    });

    }
    ```

  3. 运行结果
    image
* Restful映射到json文件
REST释义

REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性
REST简化开发,其架构遵循CRUD原则,该原则告诉我们对于资源(包括网络资源)只需要四种行为:创建,获取,更新和删除就可以完成相关的操作和处理。您可以通过统一资源标识符(Universal Resource Identifier,URI)来识别和定位资源,并且针对这些资源而执行的操作是通过 HTTP 规范定义的。其核心操作只有GET,PUT,POST,DELETE
1. 在/UI/_json目录下新建Restful.User.json,添加restful:true开启restful映射

{
	"GET": 
	{
		"type": "datatable",
		"restful": true,
		"data": 
		[
			{
				"ID": 1,
				"Name": "张三",
				"Gender": "Male",
				"BirthDate": "2003-03-03",
				"Memo": "张三,你听说过React吗?"
			},

			{
				"ID": 2,
				"Name": "李四",
				"Gender": "Female",
				"BirthDate": "2004-04-04",
				"Memo": "李四,你听说过Angular吗?"
			},

			{
				"ID": 3,
				"Name": "王五",
				"Gender": "Male",
				"BirthDate": "2005-05-05",
				"Memo": "王五,你听说过Vue吗?"
			}
		]
	}
}
  1. 在/UI/mockstudy/json目录下新建zhtml,编写js代码,包括
    初始数据(get)、新增(post)、修改(put)、删除(delete),括号中为提交方式

    Restful风格实现增删查改
获取用户列表

前端调用(提交方式“GET”)

$.ajax({
			url : "../../JavaRestful/User",
			type : "GET",
			success : function(response) {
				users = response.data;
				for (var i = 0; i < users.length; i++) {
					var dr = users[i];
					var html = "<tr>";
					html += "<td>" + dr.ID + "</td>";
					html += "<td>" + dr.Name + "</td>";
					html += "<td>" + dr.Gender + "</td>";
					html += "<td>" + dr.BirthDate + "</td>";
					html += "<td><button class='btn btn-primary' onclick='editUser(" + dr.ID + ")'>修改</button>";
					html += "<button class='btn btn-primary m-l-md' onclick='deleteUser(" + dr.ID + ")'>删除</button></td>";
					html += "</tr>";
					$("#userTable").append(html);
				}
			}
		});

运行结果
image

新增一个用户

前端调用(提交方式“POST”)

function addUser() {
		var diag = new Dialog();
		diag.width = 800;
		diag.height = 400;
		diag.title = "添加员工";
		diag.url = "restfulDialog.zhtml";
		diag.onOk = function() {
			var dc = $DW.Form.getData('form1');
			$.ajax({
				url : "../../JavaRestful/User",
				type : "POST",
				data : dc,
				success : function(response) {
					Dialog.alert(response.message, function() {
						window.location.reload();
					});
				}
			});
		};
		diag.show();
	}

运行结果
image

更新一个用户

前端调用(提交方式“PUT”)

//修改一个用户
	function editUser(id) {
		var diag = new Dialog();
		diag.width = 600;
		diag.height = 300;
		diag.title = "修改员工信息";
		diag.url = "restfulDialog.zhtml";
		var dr = null;
		for (var i = 0; i < users.length; i++) {
			if (users[i].ID == id) {
				dr = users[i];
			}
		}
		diag.onLoad = function() {
			for (k in dr) {
				$DW.$("#" + k).val(dr[k]);
			}
		};
		diag.onOk = function() {
			var dc = $DW.Form.getData('form1');
			$.ajax({
				url : "../../Restful/User/" + id,
				type : "PUT",
				data : dc,
				success : function(response) {
					Dialog.alert(response.message, function() {
						window.location.reload();
					});
				}
			});
		};
		diag.show();
	}

运行结果
image

删除一个用户(提交方式“DELETE”)

前端调用

function deleteUser(id) {
		$.ajax({
			url : "../../JavaRestful/User/" + id,
			type : "DELETE",
			success : function(response) {
				window.location.reload();
			}
		});
	}

运行结果
image

* 标签调用映射到JSON文件
<z:list>的使用

在/UI/_json目录下新建Mock.User.bindData.json,不开启Restful

{
	"GET": 
	{
		"type": "datatable",
		"data": 
		[
			{
				"ID": 1,
				"Name": "张三",
				"Gender": "Male",
				"BirthDate": "2003-03-03"
			},

			{
				"ID": 2,
				"Name": "李四",
				"Gender": "Female",
				"BirthDate": "2004-04-04"
			},

			{
				"ID": 3,
				"Name": "王五",
				"Gender": "Male",
				"BirthDate": "2005-05-05"
			}
		]
	},

	"POST": 
	{
		"type": "map",
		"data": 
		{
			"ID": 4,
			"Name": "赵六",
			"Gender": "Female",
			"BirthDate": "2006-06-06"
		}
	}
}
  1. 在/UI/mockstudy/json目录下新建list.zhtml,

    <table class="table table-reponsive">
    		<tr>
    			<th>ID</th>
    			<th>姓名</th>
    			<th>性别</th>
    			<th>出生日期</th>
    		</tr>
    		<z:list method="Mock.User.bindData">
    			<tr>
    				<td>${ID}</td>
    				<td>${Name}</td>
    				<td>${Gender}</td>
    				<td>${BirthDate}</td>
    			</tr>
    		</z:list>
    	</table>
    
  2. 运行结果
    image
<z:datagrid>的使用
  1. 在/UI/mockstudy/json目录下新建datagrid.zhtml,json映射文件仍使用Mock.User.bindData.json,html代码如下

    <z:datagrid id="dg1" method="Mock.User.bindData">
    		<table width="100%" cellpadding="2" cellspacing="0" class="z-datagrid">
    			<tr ztype="head" class="dataTableHead">
    				<td width="4%" ztype="RowNo"><z:lang id="Common.SN">序号</z:lang></td>
    				<td ztype="selector" field="ID">ID</td>
    				<td>姓名</td>
    				<td>性别</td>
    				<td>出生日期</td>
    			</tr>
    			<tr onDblClick="edit(this)" class1="dg-row-odd" class2="dg-row-even">
    				<td>&nbsp;</td>
    				<td>${ID}</td>
    				<td>${Name}</td>
    				<td>${Gender}</td>
    				<td>${BirthDate}</td>
    			</tr>
    		</table>
    	</z:datagrid>
    
  2. 运行结果
    image

    <z:datalist>的使用
  3. 在/UI/mockstudy/json目录下新建datalist.zhtml,json映射文件仍使用Mock.User.bindData.json,html代码如下

    <table class="table table-reponsive">
    		<tr>
    			<th width="25%">ID</th>
    			<th width="25%">姓名</th>
    			<th width="25%">性别</th>
    			<th width="25%">出生日期</th>
    		</tr>
    	</table>
    	<z:datalist method="Mock.User.bindData">
    		<table class="table table-reponsive">
    			<tr>
    				<td width="25%">${ID}</td>
    				<td width="25%">${Name}</td>
    				<td width="25%">${Gender}</td>
    				<td width="25%">${BirthDate}</td>
    			</tr>
    		</table>
    	</z:datalist>
    
  4. 运行结果
    image

    <z:tree>的使用
  5. 在/UI/_json目录下新建映射文件Mock.User.bindBranchData.json,rootText表示根节点名称
    ```
    {
    “GET”:
    {
    “type”: “datatable”,
    “rootText”: “组织机构”,
    “data”:
    [
    {
    “ID”: 1,
    “Name”: “泽元软件”,
    “ParentID”: 0,
    “Code”: “0001”
    },
        {
           "ID": 2,
           "Name": "北京公司",
           "ParentID": 1,
           "Code": "0002"
        },
    
        {
           "ID": 3,
           "Name": "长沙公司",
           "ParentID": 1,
           "Code": "0003"
        },
    
        {
           "ID": 4,
           "Name": "广州办事处",
           "ParentID": 1,
           "Code": "0004"
        },
    
        {
           "ID": 5,
           "Name": "上海办事处",
           "ParentID": 1,
           "Code": "0005"
        }
    ]
    

    }
    }
    ```

  6. 在/UI/mockstudy/json目录下新建tree.zhtml,标签使用的html代码

    <z:tree id="tree1" method="Mock.User.bindBranchData">
    		<p>${Name}</p>
    	</z:tree>
    
  7. 运行结果
    image
<z:select>、<z:radio>、 <z:checkbox>的使用

1.在/UI/mockstudy/json目录下新建select.zhtml,json映射文件仍使用之前的

<z:select id="select" method="Mock.User.bindData"></z:select>
<z:radio id="radio"  method="Mock.User.bindData"></z:radio>
<z:checkbox id="checkbox" method="Mock.User.bindBranchData"></z:checkbox>
  1. 运行结果
    image

    六、简单UI方法编写

    * 模拟数据的构造

    数据结构
    Datatable:数据结构,具有列对象(DataColumn),行对象(DataRow)。
    存储数据类比Excel,DataColumn为excel的列,DataRow为excel的行
  2. 在com.zving.mockstudy.ui包下新建JavaMockUI类,继承UIFacade,设置类的别名为“JavaMock”

    @Alias("JavaMock")
    public class JavaMockUI extends UIFacade {
    
  3. 模拟构造用户和机构数据
    ```
    /**
    • 获取用户数据
    • @return DataTable
      */
      public DataTable prepateUserData() {
      // 定义一个DataTable类型的数据结构
      DataTable dt = new DataTable();
      // 设置datatable列名
      dt.insertColumns(“ID”, “Name”, “Gender”, “BirthDate”);
      // 插入一行数据
      dt.insertRow(1, “赵三JAVA”, “Male”, “2006-06-06”);
      // 插入一行数据
      dt.insertRow(2, “钱四JAVA”, “Fale”, “2007-07-07”);
      // 插入一行数据
      dt.insertRow(3, “孙五JAVA”, “Male”, “2008-08-08”);
      return dt;
      }

    /**
    * 获取机构数据
    * @return DataTable
    */
    public DataTable prepateBranchData() {
    // 定义一个DataTable类型的数据结构
    DataTable dt = new DataTable();
    // 设置datatable列名
    dt.insertColumns(“ID”, “Name”, “ParentID”, “Code”);
    // 插入一行数据
    dt.insertRow(1, “泽元软件JAVA”, 0, “0001”);
    dt.insertRow(2, “北京公司JAVA”, 1, “0002”);
    dt.insertRow(3, “长沙公司JAVA”, 1, “0003”);
    dt.insertRow(4, “广州办事处JAVA”, 1, “0004”);
    dt.insertRow(5, “上海办事处JAVA”, 1, “0005”);
    return dt;
    }
    ```

    * 模拟数据的增删改查
  4. UI类下的方方法必须是public声明、@Priv注解、@Alias注解或者UI类有@Alias注解,前端才能正常访问。
    @Alias权限控制,@Alias(“User.bindList”)表示可以通过User.bindList访问
    @Priv权限控制,默认为需要登录,即@Priv(login=true)
    ```
    /**


###### <z:list>的使用 在/UI/mockstudy/java目录下创建list.zhtml,在<z:list>标签中使用上面的方法别名
ID 姓名 性别 出生日期

<z:list method=“JavaMock.User.bindList”>

${ID}
${Name}
${Gender}
${BirthDate}

</z:list>


运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8317.png) ###### <z:datalist>的使用 在JavaMockUI添加<z:datalist>标签的数据绑定方法bindDataList(DataListAction dla),

/**
* 获取用户列表(DataListAction)
* @param dla
* @return 没有返回值
* @describe
* 对应zhtml页面的<z:datalist>标签,写法<z:datalist method=‘JavaMock.User.bindDataList’></z:datalist>
* 完整访问别名:JavaMock.User.bindDataList
* @see #bindList
*/
@Alias(“User.bindDataList”)
@Priv(login = false)
public void bindDataList(DataListAction dla) {
// 绑定前端显示的数据
dla.bindData(prepateUserData());
}


在/UI/mockstudy/java目录下创建datalist.zhtml,在<z:datalist>标签中使用上面的方法别名
ID 姓名 性别 出生日期
    <z:datalist method="JavaMock.User.bindDataList">
       <table class="table table-reponsive">
         <tr>
          <td width="25%">${ID}</td>
          <td width="25%">${Name}</td>
          <td width="25%">${Gender}</td>
          <td width="25%">${BirthDate}</td>
         </tr>
       </table>
    </z:datalist>

运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8318.png) ###### <z:datagrid>的使用 在JavaMockUI添加<z:datagrid>标签的数据绑定方法bindDataGrid(DataGridAction dga),

/**
* 获取用户列表(DataGridAction)
* @param dga
* @return 没有返回值
* @describe
* 对应zhtml页面的<z:datagrid>标签,写法<z:datagrid method=‘JavaMock.User.bindDataList’></z:datagrid>
* 完整访问别名:JavaMock.User.bindDataList
* @see Priv和Alias bindList
*/
@Alias(“User.bindDataGrid”)
@Priv(login = false)
public void bindDataGrid(DataGridAction dga) {
// 绑定前端显示的数据
dga.bindData(prepateUserData());
}


在/UI/mockstudy/java目录下创建datagrid.zhtml,在<z:datagrid>标签中使用上面的方法别名

<z:datagrid id=“dg1” method=“JavaMock.User.bindDataGrid”>
















<z:lang id=“Common.SN”>序号</z:lang> ID 姓名 性别 出生日期
  ${ID} ${Name} ${Gender} ${BirthDate}

</z:datagrid>


运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8319.png) ###### <z:tree>的使用 在JavaMockUI添加<z:tree>标签的数据绑定方法bindBranchData(TreeAction ta),

/**
* 获取机构列表(TreeAction)
* @param ta
* @return 没有返回值
* @describe
* 对应zhtml页面的<z:tree>标签,写法<z:tree method=‘JavaMock.User.bindBranchData’></z:tree>
* 完整访问别名:JavaMock.User.bindBranchData
* @see #bindList
*/
@Alias(“User.bindBranchData”)
@Priv(login = false)
public void bindBranchData(TreeAction ta) {
// 设置根节点名称
ta.setRootText(“组织机构”);
//绑定数据(机构数据)
ta.bindData(prepateBranchData());
}



在/UI/mockstudy/java目录下创建tree.zhtml,在<z:tree>标签中使用上面的方法别名

<z:tree id=“tree1” method=“JavaMock.User.bindBranchData”>

${Name}


</z:tree>


运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8320.png) 在JavaMockUI添加<z:select/>,<z:radio/>标签的后台方法getData(),<z:checkbox />标签的后台方法

/**
* 获取用户信息
* @param 没有参数
* @return DataTable
* @describe
* 适用于标签<z:select/>,<z:radio/>,<z:checkbox />
* 对应zhtml写法<z:select method=‘JavaMock.User.bindBranchData’></z:select>,
* <z:radio method=‘JavaMock.User.getData’></z:radio>
* 完整访问别名:JavaMock.User.getData
* @param dla
* @see #bindList
*/
@Alias(“User.getData”)
@Priv(login = false)
public DataTable getData() {
//返回用户信息
return prepateUserData();
}

/**
 * 获取机构信息
 * @param 没有参数
 * @return DataTable
 * @describe
 * 适用于标签<z:select/>,<z:radio/>,<z:checkbox />
 * 对应zhtml写法<z:select method='JavaMock.User.bindBranchData'></z:select>,
 * <z:checkbox method='JavaMock.User.getBranchData'></z:checkbox>
 * 完整访问别名:JavaMock.User.getBranchData
 * @param dla
 * @see #bindList
 */
@Alias("User.getBranchData")
@Priv(login = false)
public DataTable getBranchData() {
    //返回机构信息
    return prepateBranchData();
}

###### <z:select><z:radio><z:checkbox>的使用 在/UI/mockstudy/java目录下创建select.zhtml,在<z:select><z:radio><z:checkbox>标签中使用上面的方法别名
    <div class="text-center m-b-lg">
       <z:radio id="radio" method="JavaMock.User.getData">
       </z:radio>
    </div>
    <div class="text-center m-b-lg">
       <z:checkbox id="checkbox" method="JavaMock.User.getBranchData">
       </z:checkbox>
    </div>

运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8321.png) ###### Server.sendRequest()的使用 在JavaMockUI添加Server.sendRequest()调用的add()方法

/**
* 添加用户
* @param 没有参数
* @return 没有返回值
* @describe
* 适用于js请求Server.sendRequest()
* 对应js写法,Server.sendRequest(“JavaMock.User.add”,{ID:1},function(response){//todo})
* 完整访问别名:JavaMock.User.add
* @param dla
* @see #bindList
*/
@Alias(“User.add”)
@Priv(login = false)
public void add() {
//操作成功的消息,失败为fail(“添加失败”)
success(“添加成功JAVA!”);
}



在/UI/mockstudy/java目录下创建javascript.zhtml,Server.sendRequest()调用后台方法添加用户的方法

function sendRequest() {
var data = {
“Name” : “钱七”,
“Gender” : “Male”,
“BirthDate” : “2007-07-07”
};
Server.sendRequest(“JavaMock.User.add”, data, function(response) {
Dialog.alert(response.message);
});
}

运行结果
![image](http://www.zving.com/upload/resources/image/2017/03/24/8322.png)

###### jQuery.ajax()调用UI方法
在JavaMockUI添加jQuery.ajax()调用的ajaxAdd(ZAction za)方法

/**
* 添加用户
* @param za
* @return 没有返回值
* @describe
* 适用于js请求Server.sendRequest()
* 对应js写法,Server.sendRequest(“JavaMock.User.ajaxAdd”,{ID:1},function(response){//todo})
* 完整访问别名:JavaMock.User.ajaxAdd
* @param dla
* @see #bindList
*/
@Alias(“User.ajaxAdd”)
@Priv(login = false)
public void ajaxAdd(ZAction za) {
//定义json对象
JSONObject jo = new JSONObject();
//添加提示信息
jo.put(“message”, “AJAX添加成功JAVA!”);
//输出Json格式信息
za.writeJSON(jo.toJSONString());
}


在UI/mockstudy/java下新建javascript.zhtml页面加入jQuery.ajax()调用后台方法添加用户的方法

function ajax() {
$.ajax({
url : “../../JavaMock/User/ajaxAdd”,
type : “POST”,
success : function(response) {
Dialog.alert(response.message);
}
});

}
运行结果
![image](http://www.zving.com/upload/resources/image/2017/03/24/8323.png)
###### Restful风格实现增删查改
在com.zving.mockstudy.ui下新建JavaRestfulUI.java,继承RestfulUI类

@Alias(“JavaRestful.User”)
public class JavaRestfulUI extends RestfulUI {

}
###### 获取用户列表
后台方法
/**
 * 获取用户列表
 * 提交方式为get时调用的方法
 */
@Override
public Object list() {
    return data;
}
前端调用

$.ajax({
url : “../../JavaRestful/User”,
type : “GET”,
success : function(response) {
users = response.data;
for (var i = 0; i < users.length; i++) {
var dr = users[i];
var html = “”;
html += “” + dr.ID + “”;
html += “” + dr.Name + “”;
html += “” + dr.Gender + “”;
html += “” + dr.BirthDate + “”;
html += “”;
html += “”;
html += “”;
$(“#userTable”).append(html);
}
}
});


运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8313.png) ###### 获取单个用户 后台方法 重写父类RestfulUI的get(id)
@Override
public Object get(String id) {
    return getDataRow(id);
}
前端调用,获取ID为2的用户

$.ajax({
url : “../../JavaRestful/User/2”,
type : “GET”,
success : function(response) {

}
})


运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8316.png) ###### 新增一个用户 后台代码,重写父类RestfulUI的新增逻辑,提交方式为method=post
/**
 * 提交方式method=post,新增一条记录
 */
@Override
public void create() {
    //插入一行空数据并获得实例
    DataRow dr = data.insertEmptyRow();
    //Current.getRequest():获取request对象;循环遍历对象
    for (Entry<String, Object> e : Current.getRequest().entrySet()) {
       //如果data包含指定的key,则设置指定的值
       if (data.containsColumn(e.getKey())) {
         dr.set(e.getKey(), e.getValue());
       }
    }
    //如果dr的第1列(id)为空,
    if (dr.get(0) == null) {
       long newID = 0;
       //遍历data对象,获得最大的ID并自增1
       for (int i = 0; i < data.getRowCount() - 1; i++) {
         //判断是否为数字
         if (NumberUtil.isNumber(data.getString(i, 0))) {
          //字符串转换为长整型
          long id = Long.parseLong(data.getString(i, 0));
          if (id > newID) {
              newID = id + 1;
          }
         }
       }
       //设置第1列的值(ID)
       dr.set(0, newID);
    }
    //返回操作成功信息
    success("Restful添加成功JAVA!");
}

前端调用代码

function addUser() {
var diag = new Dialog();
diag.width = 800;
diag.height = 400;
diag.title = “添加员工”;
diag.url = “restfulDialog.zhtml”;
diag.onOk = function() {
var dc = $DW.Form.getData(‘form1’);
$.ajax({
url : “../../JavaRestful/User”,
type : “POST”,
data : dc,
success : function(response) {
Dialog.alert(response.message, function() {
window.location.reload();
});
}
});
};
diag.show();
}


运行结果 ![image](http://www.zving.com/upload/resources/image/2017/03/24/8328.png) ###### 更新一个用户 后台代码,重写父类RestfulUI的update(String id)方法
/**
 * 更新指定id的一行记录
 * 别名为JavaRestful/User,method=put
 */
@Override
public void update(String id) {
    //获取对应的行对象
    DataRow dr = getDataRow(id);
    //dr不为空
    if (dr != null) {
       //循环Request对象,设置对应的值dr.set(key,value)
       for (Entry<String, Object> e : Request.entrySet()) {
         dr.set(e.getKey(), e.getValue());
       }
    }
    //返回操作成功信息
    success("Restful修改成功JAVA!");
}
前端调用

运行结果
![image](http://www.zving.com/upload/resources/image/2017/03/24/8314.png)

###### 删除一个用户
后台代码,重写父类Restful的delete(String id)
/**
 * 更新指定id的一行记录
 * 别名为JavaRestful/User,method=delete,
 */
@Override
public void delete(String id) {
    //获取对应的行对象
    DataRow dr = getDataRow(id);
    //不为空
    if (dr != null) {
       //删除该行
       data.deleteRow(dr);
    }
    //返回操作成功信息
    success("Restful删除成功JAVA!");
}
前端调用

function deleteUser(id) {
$.ajax({
url : “../../JavaRestful/User/” + id,
type : “DELETE”,
success : function(response) {
window.location.reload();
}
});
}
```

运行结果
image

hackIE