- 一.概述
- 二.REST Server的实现
- 2.1 REST API设计
- 2.2 数据库设计
- 2.3 用MyBatis实现的DAO层
- 2.4 用Jersey实现的REST API
- 2.5 用Spring AOP实现的日志功能
- 三.前端的实现
- 3.1 显示User列表
- 3.2 显示User详细信息
- 3.3 修改User信息
- 3.4 增加User
- 3.5 删除User
- 3.6 添加validate
3.1 显示User列表
界面如下:
1.html文件
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 <html> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6 <script src="./js/jquery.js"></script> 7 <script src="./js/underscore.js"></script> 8 <script src="./js/backbone.js"></script> 9 <script src="./js/mvc1.js"></script><!-- 引入js文件 --> 10 <script type="text/template" id="user-item-template"><!-- html模板 --> 11 <span>(<%= id %>)</span><a href="#"><%= username %></a> 12 </script> 13 <link rel="stylesheet" type="text/css" href="./css/default.css" /> 14 <title>MVC 1</title> 15 </head> 16 <body> 17 <div id="main"> 18 <div id="left"> 19 <h3></h3> 20 <ul id="user-list"></ul> 21 </div> 22 <div id="right"></div> 23 </div> 24 </body> 25 </html>
mvc1.js文件
1 $(document).ready(function() { //注释一 2 3 //定义User 4 var User = Backbone.Model.extend({ 5 }); 6 7 //定义UserList,是User的集合 8 var UserList = Backbone.Collection.extend({ 9 model : User, 10 url : "/backbone-sample/rest/user", //注释二 11 /*****重载fetch**** 12 fetch : function() { 13 var self = this; 14 $.ajax({ 15 url: self.url, 16 cache:false, 17 type: 'GET', 18 async: true, 19 dataType: 'json', 20 timeout: 300000, 21 success: function( data, textStatus ) { 22 self.reset(data.user); 23 }, 24 }); 25 } 26 *************/ 27 }); 28 29 //定义UserItemView,用来显示用户列表中的一个条目 30 var UserItemView = Backbone.View.extend({ 31 tagName : "li", 32 userItemTemplate : _.template($("#user-item-template").html()), //绑定模板 33 render : function() { 34 this.$el.html(this.userItemTemplate(this.model.toJSON())); 35 return this; 36 }, 37 }); 38 39 //定义UserListView,用来显示用户列表 40 var UserListView = Backbone.View.extend({ 41 el : $("#main"), 42 initialize : function() { 43 this.userList = new UserList(); 44 this.userList.bind('reset', this.addAll, this); 45 this.userList.bind('all', this.render, this); //注释三 46 this.userList.fetch({silent: true, success:function(collection, response){ //注释四 47 if(response != null){ 48 collection.reset(response.user); 49 }else{ 50 userListView.render(); 51 } 52 }}); 53 }, 54 render : function() { 55 this.$("#left h3").html("Total Number:"+this.userList.length); 56 }, 57 addOne : function(user) { 58 var view = new UserItemView({model : user}); 59 this.$("#user-list").append(view.render().el); 60 }, 61 addAll : function() { 62 this.userList.each(this.addOne); 63 }, 64 }); 65 66 var userListView = new UserListView();//注释五 67 });
注释一:
一开始列表内容显示不出来,找了半天没找到原因,后来才发现是忘记加document.ready了。
注释二:
Model 里面各有一个 url() 方法,和一个 urlRoot 属性;Collection 里面有一个 url() 方法,它们的关系如下:
model.url() 返回模型资源在服务器上位置的相对 URL,默认的的实现是:如果模型包含在某个集合中,则生成 URL 的形式为:"/[collection.url]/[id]"; 如果模型不是集合的一部分,则 URL 形式为:"/[urlRoot]/id"。当然可以自己重载这个方法。
例如:一个 id 为101的模型,存储在url为 "/documents/7/notes" 的 Colletion 中, 那么该模型的 URL 为:"/documents/7/notes/101"。
一般 GET、PUT、DELETE 是对某个特定模型的操作,会用 model.url() 得到带有 id 的模型 URL;而 POST 操作是不知道模型id的,因此会用 collection.url() 得到集合的 URL。
在本例中,User 包含在 UserList 中,因此需要指定 UserList 的 url。
注释三:
官网上对于bind方法的解释:object.bind(event, callback, [context])
绑定 callback 函数到 object 对象。 当事件触发时执行回调函数 callback 。如果一个页面中有大量不同的事件,按照惯例使用冒号指定命名空间:"poll:start"或"change:selection"。当 callback 执行时提供第三个可选参数,可以为 this 指定上下文: model.bind(‘change’, this.render, this)
。绑定到特殊事件 "all" 的回调函数会在任意事件发生时被触发,其第一个参数为事件的名称。
注意到第三个参数,指定了第二个参数中this所代表的对象,例如:如果把this.userList.bind('add', this.addOne, this)
的this去掉,那么实际执行的时候,this.addOne中的this会是userList,实际上应该是userListView,于是就会出错。
还有一点,在Todos这个例子中,所有的事件都是使用on来绑定事件的,也就是this.userList.on('add', this.addOne, this)
,我试了一下,二者没有什么区别。查了一下源码,on是定义在Backbone.Events中的一个函数,暂时还没能理解为什么二者是等价的。
on: function(events, callback, context) {…} // Bind one or more space separated events, `events`, to a `callback` function. Passing `"all"` will bind the callback to all events fired.
注释四:
官网上对于Collection的fetch函数的解释如下:collection.fetch([options])
从服务器拉取集合的默认模型,成功接收数据后会重置(reset)集合。options 支持 success 和 error 回调函数,回调函数接收 (collection, response) 作为参数。 可以委托 Backbone.sync 在随后处理个性化需求。处理 fetch 请求的服务器应当返回模型的 JSON 数组。
也就是调用 UserList 的 fetch() 方法时,会自动对 model.url() 的地址发出GET请求,然后将接收到的 JSON 数组作为参数来调用 reset() 方法自动设置UserList里面的User数组。
在我Server端,返回的Userlist格式如下:
{"user":[{"id":"63","username":"Andy0011","password":"123123","email":"111111@1.com","phone":""},…]}
注意到最外面会有一个 "user",这样的格式不能被默认的fetch函数使用来给集合设值,因此需要自己重载fetch函数。
有两个方法来实现:
第一个方法是在调用fetch函数的时候使用success回调函数,如注释四 fetch() 中的代码块所示。
注意到有一个 silent: true,这是因为 fetch() 是异步的,当运行完之后自动触发 reset 事件来给 userList 赋值,但是这个时候服务器端的JSON还没有返回来,所以会报错。加上 silent: true 之后,就不会自动触发reset事件了,而是在success回调函数中使用 response.user 作为参数手动调用reset函数来给userList赋值。当然如果数据库里面是空的就会返回空,因此需要判断一下,区分处理。
第二个方法更加灵活了,是在var UserList = Backbone.Collection.extend({ })这个里面重载fetch函数,如11-26行注释中的代码块所示。
这是一个典型的jQuery ajax调用,将请求设置为同步是为了解决上面那个silent: true的问题。
注释五:
需要初始化一个 UserListView 类型的对象,页面显示的流程是:
调用 UserListView 的 initialize() 方法(42行),在其中将2个方法绑定到了 userList 的事件上(44-45行),并调用了 userList 的 fetch() 放来从Server 获取数据并给其赋值(46行),在赋值的时候调用了 userList 的 reset() 方法(48行),这时候会触发已绑定的 "reset" 事件,并调用 UserListView 的 addAll() 方法显示列表内容,同时也会触发 "all" 事件,并调用UserListView 的 render() 方法在列表头部现实列表长度。在 addAll() 方法中为userList中的每一个元素调用 addOne() 方法(57行),在 addOne() 方法中会创建一个 UserItemView 并用它显示列表的一个条目(61行)。