Backbone.Collection

backbone的Collection(集合),用来存储多个model,并且可以多这些model进行数组一样的操作,比如添加,修改,删除,排序,插入,根据索引取值,等等,数组有的方法,他基本上都有

源码注释

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>backbone</title>
<style type="text/css">
*{padding:0;margin:0;}
.wrap{width:960px; margin: 100px auto; padding: 20px 0;}
ul{ list-style: none;}
</style>
</head>
<body>
<div class="wrap">
<div id="a1"></div>
<div id="a2"></div>
<div id="a3"></div>
</div>
<script src="http://files.cnblogs.com/wtcsy/jquery.js"></script>
<script src="http://files.cnblogs.com/wtcsy/underscore.js"></script>
<script src="http://files.cnblogs.com/wtcsy/events.js"></script>
<script src="http://files.cnblogs.com/wtcsy/model.js"></script>
<script>
(function(){
// Backbone.Collection
// -------------------
var array = [];
var slice = array.slice;
// If models tend to represent a single row of data, a Backbone Collection is
// more analogous to a table full of data ... or a small slice or page of that
// table, or a collection of rows that belong together for a particular reason
// -- all of the messages in this particular folder, all of the documents
// belonging to this particular author, and so on. Collections maintain
// indexes of their models, both in order, and for lookup by `id`. // Create a new **Collection**, perhaps to contain a specific type of `model`.
// If a `comparator` is specified, the Collection will maintain
// its models in sort order, as they're added and removed.
var Collection = Backbone.Collection = function(models, options) {
options || (options = {});
//默认的model
if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator;
//重置collection里面的的一些属性
this._reset();
this.initialize.apply(this, arguments);
//如果传入的models有数据,可以进行设置
if (models)
this.reset(models, _.extend({silent: true}, options));
}; // Default options for `Collection#set`.
// 设置的参数 添加的参数 add
var setOptions = {add: true, remove: true, merge: true};
var addOptions = {add: true, remove: false}; _.extend(Collection.prototype, Backbone.Events, {
// The default model for a collection is just a **Backbone.Model**.
// This should be overridden in most cases.
model: Backbone.Model, // Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function(){}, // The JSON representation of a Collection is an array of the
// models' attributes.
toJSON: function(options) {
return this.map(function(model){ return model.toJSON(options); });
}, // Proxy `Backbone.sync` by default.
/*
sync: function() {
return Backbone.sync.apply(this, arguments);
},
*/ // **parse** converts a response into a list of models to be added to the
// collection. The default implementation is just to pass it through.
parse: function(resp, options) {
return resp;
}, // Add a model, or list of models to the set.
add: function(models, options) {
//其实就是调用set方法 只有add设置成true remove设置成false merge设置成false
return this.set(models, _.extend({merge: false}, options, addOptions));
}, // Update a collection by `set`-ing a new list of models, adding new ones,
// removing models that are no longer present, and merging models that
// already exist in the collection, as necessary. Similar to **Model#set**,
// the core operation for updating the data contained by the collection.
set: function(models, options) {
options = _.defaults({}, options, setOptions);
//parse 必须是一个函数 传入的后将models进行一次转换
if (options.parse) models = this.parse(models, options);
var singular = !_.isArray(models);
models = singular ? (models ? [models] : []) : models.slice();
var id, model, attrs, existing, sort;
var at = options.at;
// this.comparator 是排序的东西 如果是函数 sotrAttr为null 否则sotrAttr为true
var sortable = this.comparator && (at == null) && options.sort !== false;
var sortAttr = _.isString(this.comparator) ? this.comparator : null;
var toAdd = [], toRemove = [], modelMap = {};
var add = options.add, merge = options.merge, remove = options.remove;
var order = !sortable && add && remove ? [] : false;
var targetProto = this.model.prototype; // Turn bare objects into model references, and prevent invalid models
// from being added.
//对models进行一次遍历 找出要add的 要remove的
for (var i = 0, length = models.length; i < length; i++) {
attrs = models[i] || {};
//通过查找model的属性找出id 可以是方便后面用 id可以是model本身 也可以是model的cid 或者是model的id
if (this._isModel(attrs)) {
id = model = attrs;
} else if (targetProto.generateId) {
id = targetProto.generateId(attrs);
} else {
id = attrs[targetProto.idAttribute || Model.prototype.idAttribute];
} // If a duplicate is found, prevent it from being added and
// optionally merge it into the existing model.
// return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
// 看model是否在this.models里面存在 如果存在,并且设置了remove吧model放到modelMap中
// 如果设置了merge model重新设置他的属性 如果设置了排序 排序标识sotr设置成true,数据改变了 肯定要排序一次的
if (existing = this.get(id)) {
if (remove) modelMap[existing.cid] = true;
if (merge) {
attrs = attrs === model ? model.attributes : attrs;
if (options.parse) attrs = existing.parse(attrs, options);
existing.set(attrs, options);
if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
}
models[i] = existing; // If this is a new, valid model, push it to the `toAdd` list.
} else if (add) {
// 如果遍历的model不存在 变并且设置了add
//对这个model做一些操作_prepareModel 如果传入的attrs是backbone实例化的model则只设置model.collection指向this
//如果attrs只是数据 则实例化model并且model.collection指向this
// 然后把model放到 toAdd中 方便后面使用
//最后 以model的cid为key 存入this._byId中
model = models[i] = this._prepareModel(attrs, options);
if (!model) continue;
toAdd.push(model);
this._addReference(model, options);
} // Do not add multiple models with the same `id`.
model = existing || model;
if (!model) continue;
//order 如果是add或者是remove并且没有设置排序 并且model是新实例化的 添加到order里面去 后面会用到
if (order && (model.isNew() || !modelMap[model.id])) order.push(model);
modelMap[model.id] = true;
} // Remove nonexistent models if appropriate.
if (remove) {
// 做删除 先做一些准备 然后添加到toRemove里面去
for (var i = 0, length = this.length; i < length; i++) {
if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
}
if (toRemove.length) this.remove(toRemove, options);
} // See if sorting is needed, update `length` and splice in new models.
if (toAdd.length || (order && order.length)) {
//符合添加条件就记性添加
if (sortable) sort = true;
this.length += toAdd.length;
if (at != null) {
for (var i = 0, length = toAdd.length; i < length; i++) {
this.models.splice(at + i, 0, toAdd[i]);
}
} else {
if (order) this.models.length = 0;
var orderedModels = order || toAdd;
for (var i = 0, length = orderedModels.length; i < length; i++) {
this.models.push(orderedModels[i]);
}
}
} // Silently sort the collection if appropriate.
//符合排序条件 进行排序
if (sort) this.sort({silent: true}); // Unless silenced, it's time to fire all appropriate add/sort events.
if (!options.silent) {
//如果没有设置silent 触发每个model的add的回调
for (var i = 0, length = toAdd.length; i < length; i++) {
(model = toAdd[i]).trigger('add', model, this, options);
}
if (sort || (order && order.length)) this.trigger('sort', this, options);
} // Return the added (or merged) model (or models).
return singular ? models[0] : models;
}, // Remove a model, or a list of models from the set.
remove: function(models, options) {
// 删除model 删除this._byId对model的引用
//触发model本身的remove绑定的回调
var singular = !_.isArray(models);
models = singular ? [models] : _.clone(models);
options || (options = {});
for (var i = 0, length = models.length; i < length; i++) {
var model = models[i] = this.get(models[i]);
if (!model) continue;
delete this._byId[model.id];
delete this._byId[model.cid];
var index = this.indexOf(model);
this.models.splice(index, 1);
this.length--;
if (!options.silent) {
options.index = index;
model.trigger('remove', model, this, options);
}
this._removeReference(model, options);
}
return singular ? models[0] : models;
}, // Force the collection to re-sort itself. You don't need to call this under
// normal circumstances, as the set will maintain sort order as each item
// is added.
sort: function(options) {
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
options || (options = {}); // Run sort based on type of `comparator`.
if (_.isString(this.comparator) || this.comparator.length === 1) {
this.models = this.sortBy(this.comparator, this);
} else {
this.models.sort(_.bind(this.comparator, this));
} if (options.reverse) this.models = this.models.reverse(); if (!options.silent) this.trigger('sort', this, options);
return this;
},
// Get a model from the set by id.
get: function(obj) {
if (obj == null) return void 0;
return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
}, // Private method to reset all internal state. Called when the collection
// is first initialized or reset.
_reset: function() {
this.length = 0;
this.models = [];
this._byId = {};
}, // When you have more items than you want to add or remove individually,
// you can reset the entire set with a new list of models, without firing
// any granular `add` or `remove` events. Fires `reset` when finished.
// Useful for bulk operations and optimizations.
reset: function(models, options) {
options || (options = {});
for (var i = 0, length = this.models.length; i < length; i++) {
this._removeReference(this.models[i], options);
}
options.previousModels = this.models;
this._reset();
models = this.add(models, _.extend({silent: true}, options));
if (!options.silent) this.trigger('reset', this, options);
return models;
}, // Prepare a hash of attributes (or other model) to be added to this
// collection.
_prepareModel: function(attrs, options) {
if (this._isModel(attrs)) {
if (!attrs.collection) attrs.collection = this;
return attrs;
}
options = options ? _.clone(options) : {};
options.collection = this;
var model = new this.model(attrs, options);
if (!model.validationError) return model;
this.trigger('invalid', this, model.validationError, options);
return false;
},
// Method for checking whether an object should be considered a model for
// the purposes of adding to the collection.
_isModel: function (model) {
return model instanceof Backbone.Model;
}, // Internal method to create a model's ties to a collection.
_addReference: function(model, options) {
this._byId[model.cid] = model;
if (model.id != null) this._byId[model.id] = model;
model.on('all', this._onModelEvent, this);
}, // Internal method called every time a model in the set fires an event.
// Sets need to update their indexes when models change ids. All other
// events simply proxy through. "add" and "remove" events that originate
// in other collections are ignored.
_onModelEvent: function(event, model, collection, options) {
if ((event === 'add' || event === 'remove') && collection !== this) return;
if (event === 'destroy') this.remove(model, options);
if (event === 'change-id') {
if (collection != null) delete this._byId[collection];
if (model.id != null) this._byId[model.id] = model;
}
this.trigger.apply(this, arguments);
},
// Internal method to sever a model's ties to a collection.
_removeReference: function(model, options) {
if (this === model.collection) delete model.collection;
model.off('all', this._onModelEvent, this);
},
}); // Underscore methods that we want to implement on the Collection.
// 90% of the core usefulness of Backbone Collections is actually implemented
// right here:
var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
'lastIndexOf', 'isEmpty', 'chain', 'sample', 'partition']; // Mix in each Underscore method as a proxy to `Collection#models`.
_.each(methods, function(method) {
if (!_[method]) return;
Collection.prototype[method] = function() {
var args = slice.call(arguments);
args.unshift(this.models);
return _[method].apply(_, args);
};
}); // Underscore methods that take a property name as an argument.
var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy']; // Use attributes instead of properties.
_.each(attributeMethods, function(method) {
if (!_[method]) return;
Collection.prototype[method] = function(value, context) {
var iterator = _.isFunction(value) ? value : function(model) {
return model.get(value);
};
return _[method](this.models, iterator, context);
};
}); // Helper function to correctly set up the prototype chain, for subclasses.
// Similar to `goog.inherits`, but uses a hash of prototype properties and
// class properties to be extended.
//第一个参数是要扩展到原型上的对象, 第2个参数是静态方法扩展到构造函数上去的
var extend = function(protoProps, staticProps) {
var parent = this;
var child; // The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent's constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
} // Add static properties to the constructor function, if supplied.
//将静态方法和 parent上的静态方法一起扩展到child上面去
_.extend(child, parent, staticProps); // Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function.
//创建一个新的构造含糊Surrogate ;
//this.constructor = child的意思是 Surrogate实例化后的对象 让对象的构造函数指向child
// Surrogate的原型就是parent的原型
// 然后实例化给child的原型,
// 这里不是直接从new parent给child.prototype 而是创建一个新的构造函数,我也不知道为啥要这样
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate; // Add prototype properties (instance properties) to the subclass,
// if supplied.
// 把第一个参数上的属性扩展到child.prototype
if (protoProps) _.extend(child.prototype, protoProps); // Set a convenience property in case the parent's prototype is needed
// later.
// 拿一个属性引用父的原型, 以免以后要用到.
child.__super__ = parent.prototype; return child;
}; Backbone.Collection.extend = extend;
})(); </script>
</body>
</html>

Collection的一些基本属性

length collection里面包含moldel的个数

models 该属性引用一个数组,数组里面就是model了

_byId 该属性引用一个对象,value就是model,key是该model的cid(或者是id,如果给model设置了id,就取id当key,否则用cid当key),

model 默认是Backbone.Model,可以被覆盖,如果传入的参数是这样的{name:"xx",age:"oo"}的对象,被实例化的对象就是用model这个基类来实例化的

Collection被实例化的过程以及 _reset,reset的方法

实例化的过程就是设置默认model,默认的model的作用是如果实例化后的colletion添加model的时候,如果传入的参数是object,则会用默认model实例化

设置comparator,

重置属性,

调用初始化方法initialize,

如果传入了值,重置值

_reset 

                this.length = 0;
this.models = [];
this._byId = {};

就是将一些属性设置成初始化的值

reset  collection.reset([models], [options])

                reset: function(models, options) {
options || (options = {});
for (var i = 0, length = this.models.length; i < length; i++) {
this._removeReference(this.models[i], options);
}
options.previousModels = this.models;
this._reset();
models = this.add(models, _.extend({silent: true}, options));
if (!options.silent) this.trigger('reset', this, options);
return models;
},
_removeReference: function(model, options) {
if (this === model.collection) delete model.collection;
model.off('all', this._onModelEvent, this);
},

它会遍历this.models里面的东西,然后执行this._removeReference,this._removeReference会把model对象的属性collection给删除掉(model在加入this.models里面的时候会加上collection这个属性,所以删除的时候要这个属性也干掉),然后触发model的all监听的回调(如果model绑定了all)

用previousModels保存之前的this.models

如果传入的参数中有对象,要添加到this.models里面去,所以在调用this.add方法

silent表示是否触发事件,没有设置就触发reset监听的回调

一些例子

var c = new Backbone.Collection
c.add({a:1})
var m = c.models[0];
alert(m.constructor === Backbone.Model) //true
//可以看到默认的model是Backbone.Model var newModel = Backbone.Model.extend({});
var newC = new Backbone.Collection(null,{model:newModel});
newC.add({a:1})
var m = newC.models[0];
alert(m.constructor === newModel) //true
alert(m.constructor === Backbone.Model)//false
//可以看到默认的Backbone.Model变成了新的newModel了
var c = new Backbone.Collection({a:1})
console.log(c.models)
//如果初始化的时候传一些数据进去,会自动变成model存在models里面的 var cc = new Backbone.Collection([{a:1},{b:1},{c:1}])
console.log(cc.models.length)
//传入的数据也可以是一个数组

Collection的set ,add,remove,sort方法(set算是里面最重要的东西了)

set

首先会对传入的models进行一次转换,变成数组,方便进行下面的遍历

然后遍历传入的models,第一步对每个单独的model查看它是否由Backbone.Model实例化而来,如果是直接把id=model,然后通过该Collection上的modle的原型上的方法查看,看能否找到id

当查找完id后,判断该id是否已经存在了,如果存在,则看参数中是否传入options.remove,如果存在放入modelMap中,在看参数中是否有options.merge,如果有则直接molde.set来改变model的值

如果id不存在,而且传入的参数中有options.add,先对遍历的model做一些操作操作如下,如果attrs是真实的model,则把attrs.collection设置成当前的这个Collection,如果attrs不是model,则用当前的Collection.model实例化一个model,把attrs当参数传进去,然后将完成的model放入toAdd数组里面,然后看该model是否设置id属性,设置了id属性则this._byId通过model.id来引用model,没有设置id属性,则通过model.cid来引用model,然后给model绑定一个"on"的监听回调事件

然后看此次操作不是排序并且是添加或者删除,则吧model加到order数组中

操作完对models的遍历后,我们可能拿到这样几个东西modelMap,toAdd,order

如果参数传入的参数中options.remove为真,则遍历modelMap,进行删除,这个modelMap是通过已存在的model来得到的

如果toAdd,order里面有数据则进行添加..

然后再options里面是否设置了排序属性sort,如果设置了,则进行排序

set是给collection重新设置models,是重新设置,之前的models会全部清掉

                var c = new Backbone.Collection();
c.set([{a:1},{b:1},{c:1}]);
console.log(c.models) //有3个
c.set({d:1});
console.log(c.models) //只有1个了

add

add 很简单的就是设置set方法 把options参数里面的remove,merge设置成false,add设置成true

                var c = new Backbone.Collection();
c.add([{a:1},new Backbone.Model(),new (Backbone.Model.extend({name:"newModel"}))()])
console.log(c.models)
//存入moldes里面的model可以由不同的Model构建出来,

remove  collection.remove(models, [options])

首先将传入的models进行遍历,删除collection里面的_byId对象的属性,然后从collection的models里面删除对应的项,触发model的remove事件

var c = new Backbone.Collection;
var m = new Backbone.Model;
m.on("remove",function(){
alert("你删除我了")
})
c.add(m);
alert(c.models.length);
c.remove(m);
alert(c.models.length);

comparator  sort

comparator如果是一个function,则是规定models按什么样子的规则排序的函数

如果是一个字符窜,则按models里面有的有的属性进行排序

sort就是调用排序了,除了用comparator,还可以用reverse直接对models进行倒叙

comparator是函数

var c = new Backbone.Collection([
{name:"a1",age:18,level:"一般"},
{name:"a2",age:16,level:"很差"},
{name:"a3",age:28,level:"很好"},
{name:"a4",age:11,level:"较好"},
],{
comparator : function(a,b){
return a.attributes.age-b.attributes.age
}
})
c.sort();
console.log(c.models);
//这个可以按age排序
//用法和数组的sort一模一样的
//修改comparator可以自定义排序 很好 较好 一般 很差
c.comparator = function(a,b){
var obj = {
"很好" : 5,
"较好" : 4,
"一般" : 3,
"很差" : 2
}
return obj[b.attributes.level] - obj[a.attributes.level]
}
c.sort();
console.log(c.models);

comparator是字符串

var c = new Backbone.Collection([
{name:"a1",age:18,level:"一般"},
{name:"a2",age:16,level:"很差"},
{name:"a3",age:28,level:"很好"},
{name:"a4",age:11,level:"较好"},
],{
comparator : "age"
})
c.sort();
console.log(c.models);
//按age来排序
c.sort({reverse:true});
console.log(c.models);
//进行倒序

Backbone.Collection扩展了很多数据的方法

['forEach', 'each', 'map', 'collect', 'reduce', 'foldl','inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select','reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke','max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest','tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle','lastIndexOf', 'isEmpty', 'chain', 'sample', 'partition'];

还扩展了一些underscore的方法

['groupBy', 'countBy', 'sortBy', 'indexBy']

backbone.Collection源码笔记的更多相关文章

  1. Backbone Events 源码笔记

    用了backbone一段时间了,做一些笔记和总结,看的源码是1.12 backbone有events,model,collection,histoty,router,view这些模块,其中events ...

  2. Backbone Collection 源码简谈

    一切由一个例子引发: var Man=Backbone.Model.extend({ initilize:function(){ this.bind('change:name',function(){ ...

  3. backbone.Model 源码笔记

    backbone.Model backbone的model(模型),用来存储数据,交互数据,数据验证,在view里面可以直接监听model来达到model一改变,就通知视图. 这个里面的代码是从bac ...

  4. springmvc源码笔记-RequestMappingHandlerMapping

    下图是springmvc的执行流程 图片来源:https://www.jianshu.com/p/8a20c547e245 DispatcherServlet根据url定位到Controller和方法 ...

  5. Zepto源码笔记(一)

    最近在研究Zepto的源码,这是第一篇分析,欢迎大家继续关注,第一次写源码笔记,希望大家多指点指点,第一篇文章由于首次分析原因不会有太多干货,希望后面的文章能成为各位大大心目中的干货. Zepto是一 ...

  6. redis源码笔记(一) —— 从redis的启动到command的分发

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载联系作者并保留声明头部与原文链接https://luzeshu.com/blog/redis1 本博客同步在http://www.cnblog ...

  7. AsyncTask源码笔记

    AsyncTask源码笔记 AsyncTask在注释中建议只用来做短时间的异步操作,也就是只有几秒的操作:如果是长时间的操作,建议还是使用java.util.concurrent包中的工具类,例如Ex ...

  8. Java Arrays 源码 笔记

    Arrays.java是Java中用来操作数组的类.使用这个工具类可以减少平常很多的工作量.了解其实现,可以避免一些错误的用法. 它提供的操作包括: 排序 sort 查找 binarySearch() ...

  9. Tomcat8源码笔记(八)明白Tomcat怎么部署webapps下项目

    以前没想过这么个问题:Tomcat怎么处理webapps下项目,并且我访问浏览器ip: port/项目名/请求路径,以SSM为例,Tomcat怎么就能将请求找到项目呢,项目还是个文件夹类型的? Tom ...

随机推荐

  1. java中string与byte[]的转换

    1.string 转 byte[] byte[] midbytes=isoString.getBytes("UTF8"); //为UTF8编码 byte[] isoret = sr ...

  2. ThinkSNS插件的使用方法

    1.插件包放到/addons/plugin/ 目录下. 2.自定义一个插件钩子:修改/apps/public/Tpl/default/Index/index.html,约在65行左右,添加下面钩子.{ ...

  3. Oracle数据库备份与恢复的常用方法

    Oracle数据库有三种常用的备份方法,分别是导出/导入(EXP/IMP).热备份和冷备份.导出/导入备份是一种逻辑备份,相对于导出/导入来说,热备份.冷备份是一种物理备份. 导出/导入(Export ...

  4. Redis_字典

    阅读本文之前要了解的两件事情,第一,Redis是一种Key-Value数据库,第二,字典是一种保存键值对的抽象数据结构.所以不难猜出字典在Redis中应用一定很广泛,实际上,Redis数据库的底层实现 ...

  5. JS的注意点

    JS的跨域访问问题. http://www.cnblogs.com/rush/archive/2012/05/15/2502264.html JS能操作的范围:HTTP协议的内容.但是不能直接访问re ...

  6. ajax开发框架和XMLhttpRequest、responseText、responseXml和JSON的应用

    1 AJAX开发框架 2 A 初始化XMLHttpRequest对象 3 B指定响应处理函数 4 C发出HTTP请求 5 D处理服务器返回的信息 6 数据格式提要 6 优点 6 缺点 7 解析 JSO ...

  7. IPC——共享内存

    Linux进程间通信——使用共享内存 下面将讲解进程间通信的另一种方式,使用共享内存.   一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的 ...

  8. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 8.全局防护盲点的总结下篇

    0x01 背景 现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义.但仅仅使用这样的防护是存在很多盲点的,接上篇http://www ...

  9. SQL VS NoSQL 如何选择数据库

    在前一篇文章中我们主要的讨论了SQL与NoSQL数据库之间的主要的差别.接下来,我们将会利用上一篇中的知识来确定在特定的场景中如何确定比较好的选择. 首先我们先来总结一下: SQL数据库: ​使用表存 ...

  10. myecplise 打开报错 Errors occurred during the build. Errors running builder 'DeploymentBuilder' on project 'myf'. Java.lang.NullPointerException

    Errors occurred during the build. Errors running builder 'DeploymentBuilder' on project 'myf'.Java.l ...