§ Fox2.0 前端框架(SPA)


§ 1 介绍

Fox框架是一个单页Web应用(single page web application,SPA)应用框架,也就是只有一张Web页面的应用。单页应用程序(S PA) 是加载单个HTML页面并在用户与应用程序交互时动态更新该页面的Web应用程序。 Fox框架提倡CMD标准,JS/HMTML/CSS都要求按模块规范编写,并提供HTML、CSS和JS加载,路由跳转,另外还通过插件的形态提供了UI组件,ajax服务访问,web socket,文件上传下载、外设访问等扩展功能。。

§ 2 工程结构

下面将会展示Fox前端框架的整体、前端和后端(可选)的结构,让大家有一个整体的认识。

§ 2.1 整体工程结构

整体工程结构.png-434.7kB

如上图所示,工程主要分为前端页面和后端服务目录。前端页面目录主要是放置HTML、CSS、JS和相关的图片等用于web展示的资源文件。而后端服务主要是放置后台渠道访问服务、访问数据库服务等。

§ 2.2 前端工程结构

前端工程结构-spa.png-188.7kB

上图展示的目录结构如下

  • custom目录:放置项目专属的js库、自定义组件等
  • pages目录:放置web page,每个page由html/css/js文件组成
  • libs目录:放置公共js库、组件库等
  • theme目录:放置主题css/font、图片等

§ 2.3 后端工程结构(可选)

后端工程结构.png-481.6kB

上图展示的目录结构如下

  • filter目录:过滤器,用于截访问服务的请求,例如报文解析、权限检验、输入数据校验等
  • example目录:示例的服务目录,service用于服务逻辑处理
  • 配置文件目录:服务配置,用于定义服务的访问路径

§ 3 前端开发指南

本节主要介绍Fox前端开发的入门基础

§ 3.1 页面开发

Fox前端框架中最小的单位为page,每个page由html/css/js三个文件组成。可参考例子工程中例子,如下

html

    <fox-sub-page id="interview_01">
        <fox-content-padded>
            <fox-input-group :label="'基本信息'">
                <fox-text :autofocus="true" v-on:focus="my_focus" v-verify="['require']" v-bind:placeholder="'请输入中文姓名'" v-model="name" :inner-tip="'必输'">中文信息</fox-text>
                <fox-select :autofocus="false" :value-type="'text'" :placeholder="'请输入证件类型'" v-model="certificateType" :datasource="m_dataSource.certificateType">证件类型</fox-select>
                <fox-number :placeholder="'请输入证件号码'" v-model="certificateNo" >证件号码</fox-number>
                <fox-text :placeholder="'请输入借款用途'" v-model="useType" >借款用途</fox-text>
                <fox-text :placeholder="'请输入申请金额(大写)'" :unit="'万元'">申请金额(大写)</fox-text>
                <fox-money :decimal-length="4" :auto-padding="false" :placeholder="'请输入申请金额(小写)'" :unit="'万元'">申请金额(小写)</fox-money>
                <fox-datetime :placeholder="'请输入申请日期'" :options='{"type":"date"}'>申请日期</fox-datetime>
                <fox-select :value-type="'json'" :placeholder="'请输入合同类型'" v-model="relType" :datasource="m_dataSource.relationShip">合同类型</fox-select>
                <fox-select v-model="classData" :options="selectLayer"  :datasource="classList">班级</fox-select>
            </fox-input-group>
            <fox-button @tap="test">测试</fox-button>
        </fox-content-padded>
    </fox-sub-page>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

js

    /**
     * Created by jiangcheng on 2017/10/24.
     */
    define(["./custom/js/app.data.interview.js"],function (require, exports) {
    
        //page加载完成后调用ready方法
        exports.ready = function (code, data, cite) {
    
            var vmData={
                //数据源
                m_dataSource:my_dataSource,
    
                classList:[{"text":"二年级","value":"201903251734451"},{"children":[{"text":"一班","value":"201903251734450"},{"text":"三班","value":"201903251734452"},{"text":"二班","value":"201903251734451"}],"text":"一年级","value":"201903251734450"}]
    
    
                ,selectLayer:{
                    layer: 2
                }
            }
            if(cite.isBack){
                //获取保存的业务数据
                var tempData=fox.bus.get("step_00","step_01","data");
                //同步数据
                fox.custom.setData(vmData,tempData);
            }else{
                //数据
                var tempData={
    
                    name:"黄飞鸿",
    
                    certificateType:"身份证",
    
                    certificateNo:"330881198802170219",
    
                    useType:"购房",
    
                    relType:"",
    
                    classData:""
    
    
                };
    
                //同步数据
                fox.custom.setData(tempData,vmData);
            }
    
    
            //创建vue model
            var vm=fox.custom.vue({
                el:cite.el,
    
                //数据
                data:vmData,
    
                //方法
                methods:{
    
                    my_focus:function(){
                        // alert("my-focus")
                    },
    
                    test:function(){
                        console.info(JSON.stringify(this.relType));
                    }
                },
    
                mounted:function(){
                   
                }
            });
        };
    
        //消息处理
        exports.onmessage = function (type, message, cite) {
    
        };
    
        //page销毁时触发destroy方法
        exports.destroy = function (id, cite) {
    
        }
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

CSS

    #interview_00{}
1

§ 3.2 自定义组件开发

每个项目都有自己特殊的需求,这是无法在公共组件中提供的,所以我们也提供了自定义组件的扩展机制。自定义组件在custom/templates/my/components.js文件中扩展,建议每个自定义组件的前缀为“my-”,如my-button,my-text等

widget

    /**
     * Created by jiangcheng on 2017/10/2.
     */
    
    /**
     * hello
     */
    (function(vue, $, name) {
        //注册组件
        Vue.component(name, {
            //模板
            template: '\
                   <label>{{text}}</label>\
                 ',
            data:{
                text:"hello world!"
            }
    
        })
    
    })(Vue, $, "my-hello");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

§ 3.3 主题扩展

theme目录下面用于主题扩展,每个项目对css样式都由特殊需求,可以通过css进行重新定制。

§ 3.4 开发规范

HTML规范 html规范.png-631kB

每个html page的最外层元素都有一个div,并且这个根div的有一个唯一的ID

CSS规范 css规范.png-555kB

CSS文件中定义的所有css都应该指定其生效范围,避免产生css污染的风险。其规则为使用对应html的根div的唯一id作为其限制范围。

JS规范 js规范.png-257.1kB

js模块三个生命周期 1.ready为页面加载完成后调用 2.destroy为页面销毁时加载 3.onmessage为页面间消息处理函数

§ 4 后端开发指南(可选)

这节将会展示如何开发service和过滤器,当然由于前端框架是前后端分离的,所以没规定必须使用fox server作为项目的后端应用服务。

§ 4.1 服务开发

每个服务由两部分组成:java文件和xml配置文件。java文件用于逻辑处理,而xml文件用于配置服务的访问路径和该服务的过滤器。如下

§ 4.1.1 普通服务开发

java

    package service.example;
    
    import java.io.BufferedInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    import service.common.bean.JsonRequest;
    import service.common.bean.JsonResponse;
    import cn.com.bankit.phoenix.resource.ResourceManager;
    import cn.com.bankit.phoenix.session.Session;
    import cn.com.bankit.phoenix.session.SessionManager;
    import cn.com.bankit.phoenix.trade.Service;
    
    /**
     * demo service
     * 
     * @author 江成
     * 
     */
    public class DemoService extends Service<JsonRequest, JsonResponse> {
    
    	/**
    	 * 构造函数
    	 */
    	public DemoService() {
    		super();
    	}
    
    	/**
    	 * execute
    	 */
    	public JsonResponse execute(JsonRequest request) throws Exception {
    		String s=request.getData().toJSONString();
    		System.out.println("收到数据:"+s);
    		//定义返回数据
    		JsonResponse response=new JsonResponse();
    		//获取名称
    		String name=(String)request.get("name");
    		if("江成".equals(name)){
    			response.put("rp", "100 (哇,人品爆棚了good!!!)");
    		}else{
    			int rp=name.hashCode()%100;
    			StringBuilder sb=new StringBuilder();
    			sb.append(rp);
    			if(rp>=80){
    				sb.append(" (人品不错哦)");
    			}else if(rp>=60){
    				sb.append(" (人品一般般嘛)");
    			}else if(rp>30){
    				sb.append(" (人品真差)");
    			}else{
    				sb.append(" (人品那么差,兄弟你从前世就开始做坏事了)");
    			}
    			
    			response.put("rp", sb.toString());
    		}
    		response.put("time", System.currentTimeMillis());
    		//response.put("test", getData());
    		System.out.println("返回数据:"+response.getData().toJSONString());
    		return response;
    	}
    	
    	/**
    	 * execute
    	 */
    	public JsonResponse login(JsonRequest request) throws Exception {
    		//-------------------------------------------------
    		 //登陆成功后获取session,如果之前没有session会创建一个新的session
    		 Session session = SessionManager.getInstance()
    					.getSessionFromCurrentThread(true);
    		 //设置session登录状态为TRUE
    		 session.login(true);
    		//定义返回数据
    	    JsonResponse response=new JsonResponse();
    	    response.put("rsp","success");
    	    return response;
    	}
    	
    	/**
    	 * 获取测试数据
    	 * @return
    	 * @throws Exception
    	 */
    	@SuppressWarnings("unused")
    	private String getData() throws Exception{
    		ResourceManager resourceManager=ResourceManager.getInstance();
    		String workspaceRoot=resourceManager.getWorkspaceRoot();
    		String projectName=resourceManager.getProjectName(this.getClass());
    		String path=workspaceRoot+"/"+projectName+"/resource/para/dataSource/test.txt";
    		ByteArrayOutputStream byteOut=new ByteArrayOutputStream();
    		InputStream in = new BufferedInputStream(new FileInputStream(new File(path)));
    		try{
    			int len=-1;
    			byte[] buffer=new byte[1024];
    			
    			while((len=in.read(buffer))!=-1){
    				byteOut.write(buffer,0,len);
    			}
    		}finally{
    		    in.close();
    		}
    		return byteOut.toString();
    	}
    	
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

服务一般继承Servie或BaseService,逻辑方法中入参为JsonRequest,出参为JsonResponse。当然对于非json格式交互数据的情况,如文件上传、文件下载服务,则需要使用HttpMessage作为入参和出参了

配置文件

    <!--继承的名字是文件名,继承的文件必须为abstract为true的文件-->
    <package name="demo" namespace="demo" extends="filter-auth.xml,filter-base.xml,filter-verify.xml">
    	<!-- demo测试 -->
    	<service name="demoService" class="service.example.DemoService"
    			method="execute">
    	  <property name="verify" type="map">
    	  	  <item key="name">require</item>
    	  </property>
    	</service>
    	<!-- web socket测试 -->
    	<service name="webSocket" class="service.example.WebSocketService"
    			method="execute">
    	</service>
    </package>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

上面配置文件中定义了服务的访问路径、过滤器链路和对应的服务实现文件和方法。访问路径有三部分组成:package-name/namespace/name,如上面的访问路径如下 demo/demo/demoService。访问该服务需要通过filter-auth.xml,filter-base.xml,filter-verify.xml三个配置文件中定义的过滤器,而该服务对应的实现类为service.example.DemoService,而对应方法为execute。

§ 4.1.2 文件上传服务开发

java

    package service.example;
    
    import java.io.BufferedOutputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.RandomAccessFile;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    import cn.com.bankit.phoenix.communication.http.FileItem;
    import cn.com.bankit.phoenix.communication.http.HttpMessage;
    import cn.com.bankit.phoenix.resource.ResourceManager;
    import cn.com.bankit.phoenix.trade.Service;
    
    /**
     * 文件上传服务
     * 
     * @author 江成
     *
     */
    public class UploadService extends Service<HttpMessage,HttpMessage>{
    
    	/**
    	 * 执行
    	 */
    	@SuppressWarnings("unchecked")
    	public HttpMessage uploadFile(HttpMessage request) throws Exception {
    		System.out.println("-------------------> start");
    		Map<String,Object> map=(Map<String,Object>)request.getContent();
    		
    		//文件item 
    		List<FileItem> fileItems  = new ArrayList<FileItem>();
    		//路径
    		String path = null;
    	
    		for(String key:map.keySet()){
    			//获取item
    			Object item=map.get(key);
    			
    			if(item instanceof FileItem){
    				System.out.println("0----> fileItem");
    			    fileItems.add((FileItem)item);
    			}else if(item instanceof String[]){
    				String name=key;
    				Object value=map.get(name);
    				System.out.println("1----> name:"+name+" ,values:"+Arrays.toString((String[])value));
    			}else{
    				String name=key;
    				Object value=map.get(name);
    				System.out.println("2----> name:"+name+" ,value:"+value);
    				if("path".equals(key)){
    					path=(String)value;
    				}
    			}
    		}
    		
    		for(int i=0,size=fileItems.size();i<size;i++){
    			FileItem fileItem=fileItems.get(i);
    			InputStream in=null;
    			OutputStream out =null;
    			
    			String fileName = (String)map.get(("fileName-"+i));
    			try{
    				in=fileItem.getInputStream();
    				ResourceManager resMg=ResourceManager.getInstance();
    				String installRoot=resMg.getInstallRoot();
    				StringBuilder sb=new StringBuilder();
    				sb.append(installRoot);
    				sb.append("/");
    				sb.append(path);
    				sb.append("/");
    				sb.append(fileName);
    				System.out.println("------------>写入文件路径 path="+sb.toString());
    				
    				File file=new File(sb.toString());
    				File parent = file.getParentFile();
    				if(!parent.isDirectory()){
    					parent.mkdirs();
    				}
    				//写入数据
    				out=new BufferedOutputStream(new FileOutputStream(file));
    			    int len=-1;
    			    byte[] buffer=new byte[1024];
    			    while((len=in.read(buffer))!=-1){
    			    	out.write(buffer,0,len);
    			    }
    			    out.flush();
    			}catch(Exception e){
    				e.printStackTrace();
    			}finally{
    				if(in!=null){
    					try{
    						in.close();
    					}catch(Exception e){
    						//do nothing
    					}
    				}
    				
    				if(out!=null){
    					try{
    						out.close();
    					}catch(IOException e){
    						//do nothing
    					}
    				}
    			}	
    		}
    		
    		System.out.println("-------------------> end");
    	    HttpMessage response=new HttpMessage();
    	    response.setContent("上传成功");
    		return response;
    	}
    	
    	
    	/**
    	 * 上传大文件
    	 */
    	@SuppressWarnings("unchecked")
    	public HttpMessage uploadBigFile(HttpMessage request) throws Exception {
    		System.out.println("-------------------> start big");
    		Map<String,Object> map=(Map<String,Object>)request.getContent();
    		//记录文件名
    		String fileName=(String)map.get("fileName");
    		//记录片段开始位置
    		long start=Long.parseLong(map.get("start").toString());
    		//当前索引
    		int index=Integer.parseInt(map.get("index").toString());
    		//切片数量
    		int count=Integer.parseInt(map.get("count").toString());
    		//获取片段数据
    		FileItem fileItem=(FileItem)map.get("data");
    		
    		//定义byte数据流
    		ByteArrayOutputStream byteOut=new ByteArrayOutputStream();
    		//定义输入流
    		InputStream in=null;
    		try{
    			//获取输入流
    			in=fileItem.getInputStream();
    			if(in==null){
    				 HttpMessage response=new HttpMessage();
    				 response.setContent("上传数据无效");
    				 return response;
    			}
    			
    			int len=0;
    			byte[] buffer=new byte[1024];
    			while((len=in.read(buffer))!=-1){
    				byteOut.write(buffer, 0, len);
    			}
    		}finally{
    			if(in!=null){
    				//关闭输入流
    				try{
    					in.close();
    				}catch(Exception e){
    					//do nothing
    				}
    			}
    		}
    		
    		//获取文件路径
    		ResourceManager resMg=ResourceManager.getInstance();
    		String installRoot=resMg.getInstallRoot();
    		StringBuilder sb=new StringBuilder();
    		sb.append(installRoot);
    		sb.append("/upload/");
    		sb.append(fileName);
    		String filePath=sb.toString();
    		
    		//定义临时文件名
    		String tmpFilePath=filePath+".tmp";
    		File tempFile = new File(tmpFilePath);
    		File parent = tempFile.getParentFile();
    		if(!parent.isDirectory()){
    			parent.mkdirs();
    		}
    		
    		//定义文件访问器
    		RandomAccessFile randomFile=null;
    		try{
    			//创建文件访问器
    			randomFile=new RandomAccessFile(tmpFilePath, "rw");
    			randomFile.seek(start);
    			randomFile.write(byteOut.toByteArray());
    		}finally{
    			//关闭文件访问器
    			if(randomFile!=null){
    				try{
    					randomFile.close();
    				}catch(Exception e){
    					//do nothing
    				}
    			}
    		}
    		//传输完成,修改为正常的文件名称
    		if(index==count){
    			File file=new File(tmpFilePath);
    			file.renameTo(new File(filePath));
    			System.out.println("写入文件:"+filePath);
    		}
    		System.out.println("写入片段 fileName:"+fileName+", index:"+map.get("index")+", count:"+map.get("count")+", start:"+start+", end:"+map.get("end"));
    	    HttpMessage response=new HttpMessage();
    	    response.setContent("上传成功");
    	    System.out.println("-------------------> end big");
    		return response;
    	}
    
    
    	@Override
    	public HttpMessage execute(HttpMessage arg0) throws Exception {
    		return null;
    	}
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

配置文件

    <!--继承的名字是文件名,继承的文件必须为abstract为true的文件-->
    <package name="demo" namespace="file" extends="filter-auth.xml">
    	<!--直接文件上传 -->
    	<service name="upload" class="service.example.UploadService"
    		method="uploadFile">
    	</service>
    	<!--直接文件上传 -->
    	<service name="uploadBig" class="service.example.UploadService"
    		method="uploadBigFile">
    	</service>
    	<!--直接文件下载 -->
    	<service name="download" class="service.example.DownloadService"
    		method="downloadFile">
    	</service>
    </package>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

上面文件上传服务中,由于数据为流,所以必须使用HttpMessage作为参数

§ 4.1.3 文件下载服务开发

java

    package service.example;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.Map;
    
    import cn.com.bankit.phoenix.communication.http.HttpMessage;
    import cn.com.bankit.phoenix.resource.ResourceManager;
    
    /**
     * 下载服务
     * @author 江成
     *
     */
    public class DownloadService {
    
    	/**
    	 * 构造函数
    	 */
    	public DownloadService() {
    		super();
    	}
    	
    	/**
    	 * 执行
    	 */
    	public HttpMessage downloadFile(HttpMessage httpMessage) throws Exception {
    		// 获取请求参数
    		@SuppressWarnings("unchecked")
    		Map<String, Object> reqMap = (Map<String, Object>) httpMessage
    				.getContent();
    		String path = (String) reqMap.get("path");
    	
    		ResourceManager resMg=ResourceManager.getInstance();
    		String installRoot=resMg.getInstallRoot();
    		StringBuilder sb=new StringBuilder();
    		sb.append(installRoot);
    		sb.append("/");
    		sb.append(path);
    		System.out.println("------------>读取文件路径 path="+sb.toString());
    		
    		File file=new File(sb.toString());
    		InputStream in = new BufferedInputStream(new FileInputStream(file));
    	    
    	    HttpMessage respMsg = new HttpMessage();
    		respMsg.setHeader("Content-Type", "application/octet-stream");
    		respMsg.setContent(in);
    		return respMsg;
    	}
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

配置文件

    <!--继承的名字是文件名,继承的文件必须为abstract为true的文件-->
    <package name="demo" namespace="file" extends="filter-auth.xml">
    	<!--直接文件上传 -->
    	<service name="upload" class="service.example.UploadService"
    		method="uploadFile">
    	</service>
    	<!--直接文件上传 -->
    	<service name="uploadBig" class="service.example.UploadService"
    		method="uploadBigFile">
    	</service>
    	<!--直接文件下载 -->
    	<service name="download" class="service.example.DownloadService"
    		method="downloadFile">
    	</service>
    </package>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

上面文件下载服务中,由于数据为流,所以必须使用HttpMessage作为参数

###4.2 过滤器开发 过滤器同样由java和配置文件两部分组成,下面就用一个权限过滤器为例子,给大家展示过滤器如何开发。

java

    package service.common.filter;
    
    import both.common.util.LoggerUtil;
    import cn.com.bankit.phoenix.communication.http.HttpMessage;
    import cn.com.bankit.phoenix.session.Session;
    import cn.com.bankit.phoenix.session.SessionManager;
    import cn.com.bankit.phoenix.trade.filter.Event;
    import cn.com.bankit.phoenix.trade.filter.Filter;
    
    /**
     * 消息解析过滤器
     * 
     * @author 江成
     * 
     */
    public class AuthFilter extends Filter {
    
    	/**
    	 * 构造函数
    	 */
    	public AuthFilter() {
    		super();
    	}
    
    	/**
    	 * before
    	 */
    	public void before(Event e) throws Exception {
    		//获取session manager
    		SessionManager sessionManager = SessionManager.getInstance();
    		//获取session
    		Session session = sessionManager.getSessionFromCurrentThread(false);
    		
    		//由于是集群部署,session不可能在每台服务器都存在,所以如果内存中
    		//session不存在,那旧必须在HTTP message中获取sessionId,去数据库
    		//中校验,并还原
    		if(session == null){
    			// 获取入参
    			Object inBean = e.getInBean();
    			if (inBean instanceof HttpMessage) {
    				HttpMessage httpSession = (HttpMessage)inBean;
    				String id = httpSession.getHeader("sessionId");
    				if(id!=null){
    				   //------读取数据库的登陆信息,检查session是否有效--------
    				   //检查代码写在这里
    				   //------------------------------------------------------
    					
    				   //使用指定的ID创建session	
    				   session = sessionManager.getSession(id, true);
    				   //绑定session到当前线程
    				   sessionManager.bindSessionToCurrentThread(session);
    				   //设置session的登陆状态
    				   session.login(true);
    				   
    				   //-------还原session信息----------
    				   session.setData("admin", "江成");
    				   //-------------------------------
    					
    				}else{
    					LoggerUtil.error("无法校验session-1");
    					// 抛出异常
    					throw new Exception("unlogin");
    				}
    			}else{
    				LoggerUtil.error("无法校验session-2");
    				// 抛出异常
    				throw new Exception("unlogin");
    			}
    		}else{
    			// 获取登录状态
    			Boolean loginStatus = session.isLogin();
    			if (!Boolean.TRUE.equals(loginStatus)) {
    				LoggerUtil.error("用户尚未登录");
    				// 抛出异常
    				throw new Exception("unlogin");
    			}
    		}
    		
    	}
    
    	/**
    	 * after
    	 */
    	public void after(Event e) throws Exception {
    		// do nothing
    	}
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

配置文件

    <package name="filter-auth" abstract="true">
    	<!-- 权限 filter -->
    	<filter name="AuthFilter"  class="service.common.filter.AuthFilter" scope="singleton">
        </filter>
    </package>
1
2
3
4
5

§ 5 单页面(SPA)支持

本节将会展示对SPA应用的支持

§ 5.1 路由表

在Fox前端框架中,所有开发的page都必须把页面注册到路由表中,路由表目录在custom/route-tables下,并且必须把路由文件在custom/main.js中引用

路由表

    /**
     * Created by 江成 on 2017/03/05.
     */
    define(function(require){
        //定义路由表
        var routeTable={
            //frame
            frame: {
                html: "pages/phone/example/frame/frame.html",
                css: "pages/phone/example/frame/frame.css",
                js: "pages/phone/example/frame/frame.js"
            }
            ,components: {
                html: "pages/phone/example/components/components.html",
                js: "pages/phone/example/components/components.js",
                css: "pages/phone/example/components/components.css"
            }
            ,devices: {
                html: "pages/phone/example/device/devices/devices.html",
                js: "pages/phone/example/device/devices/devices.js",
                css: "pages/phone/example/device/devices/devices.css"
            }
        };
        //注册路由表
        fox.router.addRouteTable(routeTable);
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

规则为路由id:html/css/js路径

main.js中引用

    //路由表
        var route_tables = [
            './custom/route-tables/phone/route.silk.pure.js'
            ,'./custom/route-tables/phone/route.silk.js'
            ,'./custom/route-tables/phone/route.silk.device.js'
            ,'./custom/route-tables/phone/route.silk.tutorial.js'
            ,'./custom/route-tables/phone/route.silk.scene.js'
            //拾光校园
            ,'./custom/route-tables/phone/route.school.js'
            //客户信息采集
            ,'./custom/route-tables/phone/route.interview.js'
            //融联创金融
            ,'./custom/route-tables/phone/route.finance.js'
            //统一门户
            ,'./custom/route-tables/phone/route.unified_portal.js'
        ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

§ 5.2 路由跳转

Fox前端框架提供了路由跳转的功能,目前路由具备两种,一为内容替换、二为窗口打开。

§ 5.2.1 to/back

router.to

     //定义传递参数
    let param = {};
    //页面跳转 参数列表为(id,data,rootId),id:页面为唯一标志,在route table中注册;                     //data:父亲页面要传递到子页面的数据;rootId:目标页面要嵌入的div的id
    fox.router.to("step_2", param);
1
2
3
4

router.back

     fox.router.back();
1

§ 5.2.2 append/remove

router.append

     //定义传递参数
    let param = {};
    //页面跳转 参数列表为(id,data),id:页面为唯一标志,在route table中注册;                     //data:父亲页面要传递到子页面的数据
    fox.router.append("step_2", param);
1
2
3
4

router.remove

      fox.router.remove();
1

router.remove 所有窗口

     fox.router.remove({all:true});
1
最后更新于: 7/5/2022, 5:29:52 PM