窗边的扁豆


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

JavaScript的浏览器对象

发表于 2017-07-10 | 分类于 javascript

JavaScript的浏览器对象

[TOC]

常见的内置对象

  • window对象

    window对象不但充当全局作用域,而且表示浏览器窗口。

    window对象有innerWidth和innerHeight属性,可以获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。

  • navigator

    navigator对象表示浏览器的信息,最常用的属性包括:

    • navigator.appName:浏览器名称;
    • navigator.appVersion:浏览器版本;
    • navigator.language:浏览器设置的语言;
    • navigator.platform:操作系统类型;
    • navigator.userAgent:浏览器设定的User-Agent字符串。
  • localtion

    location对象表示当前页面的URL信息。例如,一个完整的URL:

    1
    2
    3
    4
    5
    6
    location.protocol; // 'http'
    location.host; // 'www.example.com'
    location.port; // '8080'
    location.pathname; // '/path/index.html'
    location.search; // '?a=1&b=2'
    location.hash; // 'TOP'

    要加载一个新页面,可以调用location.assign()。如果要重新加载当前页面,调用location.reload()方法非常方便。

  • document对象(重要,常用)

    document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点。

    document对象还有一个cookie属性,可以获取当前页面的Cookie。

####Document的基本操作

  • 查找节点

    要想进行dom操作,首先应该拿到dom对象。常用的方法如下:

    1
    2
    3
    4
    document.getElementById();
    document.getElementsByTagName();
    document.getElementsByClassName();
    document.getElementById(); //最常用,由于id可以唯一定位。

    如果想要通过父节点再查找子节点,可以通过:

    1
    2
    3
    4
    5
    6
    7
    8
    // 返回ID为'test'的节点:
    var test = document.getElementById('test');
    // 获取节点test下的所有直属子节点:
    var cs = test.children;
    // 获取节点test下第一个、最后一个子节点:
    var first = test.firstElementChild;
    var last = test.lastElementChild;
  • 更新节点

    1. 通过修改innerHTML属性,可以更改节点内部的结构(即支持加入html标签)

      1
      2
      3
      4
      5
      6
      var p = document.getElementById('p-id');
      // 设置文本为abc:
      p.innerHTML = 'ABC'; // <p id="p-id">ABC</p>
      // 设置HTML:
      p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
      // <p>...</p>的内部结构已修改。注意如果原来有标签的会直接替换。
    2. 通过修改innerText或者textContent,只能修改内容。无法添加标签

      1
      2
      3
      4
      5
      6
      // 获取<p id="p-id">...</p>
      var p = document.getElementById('p-id');
      // 设置文本:
      p.innerText = '<script>alert("Hi")</script>';
      // HTML被自动编码,无法设置一个<script>节点:
      // <p id="p-id">&lt;script&gt;alert("Hi")&lt;/script&gt;</p>
    3. 修改节点的样式。(因为CSS允许font-size这样的名称,但它并非JavaScript有效的属性名,所以需要在JavaScript中改写为驼峰式命名fontSize:)

      1
      2
      3
      4
      5
      6
      // 获取<p id="p-id">...</p>
      var p = document.getElementById('p-id');
      // 设置CSS:
      p.style.color = '#ff0000';
      p.style.fontSize = '20px';
      p.style.paddingTop = '2em';s
  • 插入节点

    1. 使用appendChild,把一个子节点添加到父节点的最后一个子节点。

      1
      2
      3
      4
      5
      6
      7
      <!-- HTML结构 -->
      <p id="js">JavaScript</p>
      <div id="list">
      <p id="java">Java</p>
      <p id="python">Python</p>
      <p id="scheme">Scheme</p>
      </div>
      1
      2
      3
      4
      var
      js = document.getElementById('js'),
      list = document.getElementById('list');
      list.appendChild(js);

      因为我们插入的js节点已经存在于当前的文档树,因此这个节点首先会从原先的位置删除,再插入到新的位置。假如我们需要创建一个新的dom对象:

      1
      2
      3
      4
      5
      var list = document.getElementById('list'),
      haskell = document.createElement('p');
      haskell.id = 'haskell';
      haskell.innerText = 'Haskell';
      list.appendChild(haskell);

      将某节点插入到指定节点之前:

      1
      2
      3
      4
      5
      6
      7
      var
      list = document.getElementById('list'),
      ref = document.getElementById('python'),
      haskell = document.createElement('p');
      haskell.id = 'haskell';
      haskell.innerText = 'Haskell';
      list.insertBefore(haskell, ref);
  • 删除子节点

    要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉:

    1
    2
    3
    4
    5
    6
    7
    // 拿到待删除节点:
    var self = document.getElementById('to-be-removed');
    // 拿到父节点:
    var parent = self.parentElement;
    // 删除:
    var removed = parent.removeChild(self);
    removed === self; // true

    删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。

    ​

表单操作

  • 获取表单的值

    对于普通输入框,可以直接表单值:

    1
    2
    3
    // <input type="text" id="email">
    var input = document.getElementById('email');
    input.value; // '用户输入的值'

    对于单选框和复选框,value属性返回的永远是HTML预设的值,而我们需要获得的实际是用户是否“勾上了”选项,所以应该用checked判断:

    1
    2
    3
    4
    5
    6
    7
    8
    // <label><input type="radio" name="weekday" id="monday" value="1"> Monday</label>
    // <label><input type="radio" name="weekday" id="tuesday" value="2"> Tuesday</label>
    var mon = document.getElementById('monday');
    var tue = document.getElementById('tuesday');
    mon.value; // '1'
    tue.value; // '2'
    mon.checked; // true或者false
    tue.checked; // true或者false
  • 设置表单的值:

    对于普通输入框:

    1
    2
    3
    // <input type="text" id="email">
    var input = document.getElementById('email');
    input.value = 'test@example.com'; // 文本框的内容已更新

    对于单选框和复选框,设置checked为true或false:

    1
    2
    3
    // <label><input type="radio" name="weekday" id="monday" value="1"> Monday</label>
    var mon = document.getElementById('monday');
    mon.check=true;
  • 提交表单

    1. 通过获取表单dom,然后直接提交。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <!-- HTML -->
      <form id="test-form">
      <input type="text" name="test">
      <button type="button" onclick="doSubmitForm()">Submit</button>
      </form>
      <script>
      function doSubmitForm() {
      var form = document.getElementById('test-form');
      // 可以在此修改form的input...
      // 提交form:
      form.submit();
      }
      </script>

      这样破坏了正常的表单提交。推荐提交方法如():

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <!-- HTML -->
      <form id="test-form" onsubmit="return checkForm()">
      <input type="text" name="test">
      <button type="submit">Submit</button>
      </form>
      <script>
      function checkForm() {
      var form = document.getElementById('test-form');
      // 可以在此修改form的input...
      // 继续下一步:
      return true;
      }
      </script>

      return true来告诉浏览器继续提交,如果return false,浏览器将不会继续提交form。

      出于安全考虑,很多时候我们会对用户数据进行md5加密。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      <!-- HTML -->
      <form id="login-form" method="post" onsubmit="return checkForm()">
      <input type="text" id="username" name="username">
      <input type="password" id="input-password">
      <input type="hidden" id="md5-password" name="password">
      <button type="submit">Submit</button>
      </form>
      <script>
      function checkForm() {
      //通过隐藏的输入框传输,防止密码框突然变得很多。
      var input_pwd = document.getElementById('input-password');
      var md5_pwd = document.getElementById('md5-password');
      // 把用户输入的明文变为MD5:
      md5_pwd.value = toMD5(input_pwd.value);
      // 继续下一步:
      return true;
      }
      </script>

    ​

文件操作

  • 传统的html中,js只能获取上传文件的路径名:

    1
    2
    3
    4
    5
    6
    var f = document.getElementById('test-file-upload');
    var filename = f.value; // 'C:\study\test.png'
    if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) {
    alert('Can only upload image file.');
    return false;
    }

    在h5中提供了读取上传文件的对象:

    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
    var
    fileInput = document.getElementById('test-image-file'),
    //显示文件信息的组件
    info = document.getElementById('test-file-info'),
    //如果是图片,预览图片的组件
    preview = document.getElementById('test-image-preview');
    // 监听change事件:
    fileInput.addEventListener('change', function () {
    // 清除背景图片:
    preview.style.backgroundImage = '';
    // 检查文件是否选择:
    if (!fileInput.value) {
    info.innerHTML = '没有选择文件';
    return;
    }
    // 获取File引用:
    var file = fileInput.files[0];
    // 获取File信息:
    info.innerHTML = '文件: ' + file.name + '<br>' +
    '大小: ' + file.size + '<br>' +
    '修改: ' + file.lastModifiedDate;
    if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
    alert('不是有效的图片文件!');
    return;
    }
    // 读取文件:
    var reader = new FileReader();
    //设置回调函数
    reader.onload = function(e) {
    var
    data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'
    preview.style.backgroundImage = 'url(' + data + ')';
    };
    // 以DataURL的形式读取文件:
    reader.readAsDataURL(file);
    });
  • JavaScript的一个重要的特性就是单线程执行模式。

    在JavaScript中,浏览器的JavaScript执行引擎在执行JavaScript代码时,总是以单线程模式执行,也就是说,任何时候,JavaScript代码都不可能同时有多于1个线程在执行。所以执行多任务实际上都是异步调用。所以上面我们在

    1
    reader.readAsDataURL(file);

    之前先设置了回调函数。

    1
    2
    3
    4
    5
    reader.onload = function(e) {
    var
    data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'
    preview.style.backgroundImage = 'url(' + data + ')';
    };

    ​

    ​

JavaScript的函数

发表于 2017-07-10 | 分类于 JavaScript

JavaScript的函数

[TOC]

函数的定义

  1. 普通函数定义

    1
    2
    3
    4
    5
    6
    7
    function abs(x) {
    if (x >= 0) {
    return x;
    } else {
    return -x;
    }
    }
  2. 指定变量的函数定义

    1
    2
    3
    4
    5
    6
    7
    var abs = function (x) {
    if (x >= 0) {
    return x;
    } else {
    return -x;
    }
    }; //此种方法末尾需要添加;

Arguments关键字

  • 该关键字只在函数内部齐作用,永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array。利用arguments,你可以获得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值以及参数的数量

    1
    2
    3
    4
    5
    6
    7
    function foo(x) {
    alert(x); // 10
    for (var i=0; i<arguments.length; i++) {
    alert(arguments[i]); // 10, 20, 30
    }
    }
    foo(10, 20, 30);

Rest参数

  • 在ES6中定义了一种方便获取可变参数的方式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
    }
    foo(1, 2, 3, 4, 5);
    // 结果:
    // a = 1
    // b = 2
    // Array [ 3, 4, 5 ]
    • rest参数只能写在最后,前面用…标识,从运行结果可知,传入的参数先绑定a、b,多余的参数以数组形式交给变量rest,所以,不再需要arguments我们就获取了全部参数。
    • 如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)。

变量 的作用域

  • 在JavaScript中,用var申明的变量实际上是有作用域的。(该作用域只包括函数,不包括快作用域)

    只有在作用域内部才可以使用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    'use strict';
    function foo() {
    var temp =100;
    for (var i=0; i<100; i++) {
    //
    }
    i += 100; // 仍然可以引用变量i,因为var的局部只局限于函数内部。
    }
    temp=temp+2; // ReferenceError! 无法在函数体外引用变量x

    在es6之后,要想在块级作用域定义局部变量可以使用let关键字。

    1
    2
    3
    4
    5
    6
    7
    function foo() {
    var temp =100;
    for (let i=0; i<100; i++) {
    //
    }
    i += 100; // SyntaxError
    }

    并且在es6之后,可以通过const关键字定义常量

    1
    2
    3
    const PI = 3.14;
    PI = 3; // 某些浏览器不报错,但是无效果!
    PI; // 3.14

装饰器

  • 通过js的装饰起可以动态改变函数的行为,增加我们需要的功能。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var count = 0;
    var oldParseInt = parseInt; // 保存原函数
    window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // 调用原函数
    };
    // 测试:
    parseInt('10');
    parseInt('20');
    parseInt('30');
    count; // 3

    这样我们每次调用parseInt()的时候都可以计数一次。

高阶函数

  • 神马叫高阶函数?

    JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

  • Map函数

    由于map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果。相当于对Array中的每个值都进行一次我们指定的函数操作。

    1
    2
    3
    4
    5
    function pow(x) {
    return x * x;
    }
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
  • Reduce函数

    Array的reduce()把一个函数作用在这个Array的[x1, x2, x3…]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

    1
    2
    3
    4
    var arr = [1, 3, 5, 7, 9];
    arr.reduce(function (x, y) {
    return x + y;
    }); // 将array中的数据进行了累加操作
  • Filter函数

    通过Filter我们可以过滤我们需要的数组元素。和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。

    1
    2
    3
    4
    5
    var arr = [1, 2, 4, 5, 6, 9, 10, 15];
    var r = arr.filter(function (x) {
    return x % 2 !== 0;
    });
    r; // 删除数组中的偶数,返回结果为[1, 5, 9, 15]

    去除数组中的重复元素:

    1
    2
    3
    4
    5
    r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index;
    });
    //这里的回调函数第一个参数代表数组中的某个元素,第二个代表下标,第三个代表数组本身。
    //去除重复元素依靠的是indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,因此被filter滤掉了。
  • 排序函数

    常规定,对于两个元素x和y,如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1。

    所以自定义排序函数(sort会直接对数组内容进行修改):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var arr = [10, 20, 1, 2];
    arr.sort(function (x, y) {
    if (x < y) {
    return -1;
    }
    if (x > y) {
    return 1;
    }
    return 0;
    }); // [1, 2, 10, 20]

函数的闭包

  • 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

    举个栗子:正常的求和函数

    1
    2
    3
    4
    5
    6
    function sum(arr) {
    return arr.reduce(function (x, y) {
    return x + y;
    });
    }
    sum([1, 2, 3, 4, 5]); // 15

    使用闭包的求和函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function lazy_sum(arr) {
    var sum = function () {
    return arr.reduce(function (x, y) {
    return x + y;
    });
    }
    return sum;
    }
    var f1 = lazy_sum([1, 2, 3, 4, 5]); // function sum()这里并不会立即执行函数
    f1(); // 15 调用函数的时候才会真正的执行计算。
    var f2 = lazy_sum([1, 2, 3, 4, 5]);
    f1 === f2; // false每次返回的都是不同的函数。

    我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为闭包(Closure)。

    匿名函数会有这种功能其主要原因是因为我们创建的匿名函数并没有执行,如果想要创建匿名函数并执行,可以使用以下语法:

    1
    (function (x) { return x * x }) (3);

箭头函数

  • 在ES6中新增了一种匿名函数标准,可以使用箭头语法。

    1
    2
    3
    4
    5
    x => x * x
    //作用相当于
    function (x) {
    return x * x;
    }

    如果包涵多个表示式:

    1
    2
    3
    4
    5
    6
    7
    8
    x => {
    if (x > 0) {
    return x * x;
    }
    else {
    return - x * x;
    }
    }

    包涵多个参数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 两个参数:
    (x, y) => x * x + y * y
    // 无参数:
    () => 3.14
    // 可变参数:
    (x, y, ...rest) => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
    sum += rest[i];
    }
    return sum;
    }

    ​

JavaScript的对象

发表于 2017-07-09 | 分类于 javascript

JavaScript的面向对象

[TOC]

与Java的区别

  • JavaScript的面向对象编程和大多数其他语言如Java、C#的面向对象编程都不太一样。

    JavaScript不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var Student = {
    name: 'Robot',
    height: 1.2,
    run: function () {
    console.log(this.name + ' is running...');
    }
    };
    var xiaoming = {
    name: '小明'
    };
    xiaoming.__proto__ = Student;
    xiaoming.name; // '小明'
    xiaoming.run(); // 小明 is running...继承而来的方法
  • JavaScript的原型链和Java的Class区别就在,它没有“Class”的概念,所有对象都是实例,所谓继承关系不过是把一个对象的原型指向另一个对象而已。

创建对象

  • JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。

    当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined。

  • 构造函数

    除了直接用{ ... }创建一个对象外,JavaScript还可以用一种构造函数的方法来创建对象。它的用法是,先定义一个构造函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function Student(name) {
    this.name = name;
    this.hello = function () {
    alert('Hello, ' + this.name + '!');
    }
    }
    //通过new修饰后即可将其变成一个对象,如果不写new,这就是一个普通函数,它返回undefined。但是,如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this,也就是说,不需要在最后写return this;。
    var xiaoming = new Student('小明');
    xiaoming.name; // '小明'
    xiaoming.hello(); // Hello, 小明!

    通过new创建的对象都指向同一个原型:

    1
    2
    3
    xiaoming ↘
    xiaohong -→ Student.prototype ----> Object.prototype ----> null
    xiaojun ↗

    ​

    通过class创建和继承对象

  • 在es6之后,通过引入了class关键字简化了对象的创建以及对象的继承。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Student {
    //构造函数
    constructor(name) {
    this.name = name;
    }
    //定义在原型对象上的函数hello(),没有关键字function
    hello() {
    alert('Hello, ' + this.name + '!');
    }
    }
  • 对象的继承(和java简直超级像有木有)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class PrimaryStudent extends Student {
    constructor(name, grade) {
    super(name); // 记得用super调用父类的构造方法!
    this.grade = grade;
    }
    myGrade() {
    alert('I am at grade ' + this.grade);
    }
    }
    ​
    

JQuery的事件处理

发表于 2017-07-07 | 分类于 jquery

JQuery的事件处理

[TOC]

基本事件处理

  • 浏览器在接收到用户的鼠标或键盘输入后,会自动在对应的DOM节点上触发相应的事件。如果该节点已经绑定了对应的JavaScript处理函数,该函数就会自动调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 获取超链接的jQuery对象:
    var a = $('#hello');
    //绑定指定的事件
    a.on('click', function () {
    alert('Hello!');
    });
    //或者
    a.click(function () {
    alert('Hello!');
    });
  • 常见的鼠标事件

    1. click: 鼠标单击时触发;
    2. dblclick:鼠标双击时触发;
    3. mouseenter:鼠标进入时触发;
    4. mouseleave:鼠标移出时触发;
    5. mousemove:鼠标在DOM内部移动时触发;
    6. hover:鼠标进入和退出时触发两个函数,相当于mouseenter加上mouseleave。
  • 常见的其他事件

    1. focus:当DOM获得焦点时触发;
    2. blur:当DOM失去焦点时触发;
    3. change:当、或的内容改变时触发;
    4. submit:当提交时触发;
    5. ready:当页面被载入并且DOM树完成初始化后触发。

    ready仅作用于document对象。由于ready事件在DOM完成初始化后触发,且只触发一次,所以非常适合用来写其他的初始化代码。

    1
    2
    3
    4
    5
    6
    7
    8
    $(document).on('ready', function () {
    ///初始化操作
    });
    });
    //或者
    $(function () {
    // init...
    });
  • 动画事件

    1. 显示隐藏动画

      1
      2
      3
      4
      var div = $('#test-show-hide');
      div.hide(3000); // 在3秒钟内逐渐消失
      div.show(3000); // 在3秒钟内逐渐显示
      div.toggle(); //根据当前状态决定是show()还是hide()。
    2. 自定义动画

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      var div = $('#test-animate');
      //在3s内变化到制定的css样式
      div.animate({
      opacity: 0.25,
      width: '256px',
      height: '256px'
      }, 3000, function () {
      //动画结束的回调函数
      console.log('动画已结束');
      // 恢复至初始状态:
      $(this).css('opacity', '1.0').css('width', '128px').css('height', '128px');
      });

      ​

    ​

Redis入门

发表于 2017-06-20 | 分类于 Redis

Redis入门

[TOC]

简介

​ Redis是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的Web应用程序。其主要特点有:

  • Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。(内存数据库)
  • 与其它键值数据存储相比,Redis有一组相对丰富的数据类型。
  • Redis可以将数据复制到任意数量的从机中。

​ 为啥我们要用redis,希望下面的优点能说服你:

  • 异常快 - Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作。
  • 支持丰富的数据类型 - Redis支持开发人员常用的大多数数据类型,例如列表,集合,排序集和散列等等。这使得Redis很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。
  • 操作具有原子性 - 所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。
  • 多实用工具 - Redis是一个多实用工具,可用于多种用例,如:缓存,消息队列(Redis本地支持发布/订阅),应用程序中的任何短期数据,例如,web应用程序中的会话,网页命中计数等。

安装

  1. 从官网下载最新stable(稳定)版。放到linux服务器上。

  2. 按照如下命令安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    tar -zvxf redis-3.2.8.tar.gz #解压安装包
    cd redis-3.2.8
    make /#编译c源码(需要先安装gcc编译器)
    make PREFIX=/usr/local/redis install #安装到指定目录下,一般Linux的软件习惯装载/usr/local下面
    cp redis.conf /usr/local/redis/ #复制解压目录下的配置文件到redis安装目录
    bin/redis-server redis.conf #启动redis服务并指定配置文件
    ./redis-cli #新开一个窗口并启动客户端
  3. 如果是远程主机连接的话

    1
    redis-cli -h host -p port -a password

    将redis启动为后台服务(设置redis.conf并修改daemonize的值)

    1
    daemonize yes #设置为后天进程,默认为no

    ​

    ​

基本数据类型的操作

  • 字符串操作(详细操作可以参考官方文档或者教程)

    Redis字符串命令用于管理Redis中的字符串值。以下是使用Redis字符串命令的基本语法:

    1
    2
    3
    4
    5
    6
    SET mykey "redis" #设置key-value对
    ex:
    SET key value # 此命令设置指定键的值。
    GET key # 获取指定键的值。
    GETRANGE key start end # 获取存储在键上的字符串的子字符串。
    GETSET key value # 设置键的字符串值并返回其旧值。

    ​

  • List操作(可以存在相同元素,如果需要不能存在相同元素则可以使用Set操作)

    在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    lpush list1 "forever" #向list1中加入
    lpush list1 "cll" #向list1中加入
    lpush list1 "wifi" #向list1中加入
    LLEN key #获取列表的长度
    LPOP key #删除并获取列表中的第一个元素
    LPUSH key value1 [value2] #将一个或多个值添加到列表
    LPUSHX key value #仅当列表存在时,才向列表添加值
    LRANGE key start stop #从列表中获取一系列元素
    LREM key count value #从列表中删除元素
  • Hash操作

    Redis Hashes是字符串字段和字符串值之间的映射。 因此,它们是表示对象的完美数据类型。在Redis中,每个哈希(散列)可以存储多达4亿个键-值对。

    1
    2
    3
    4
    5
    hset map1 name zs #向map1的hash表中加入key-value
    HDEL key field2 [field2] #删除一个或多个哈希字段。
    HEXISTS key field #判断是否存在散列字段。
    HGET key field #获取存储在指定键的哈希字段的值。
    HGETALL key #获取存储在指定键的哈希中的所有字段和值
  • Set操作

    Redis集合是唯一字符串的无序集合。 唯一值表示集合中不允许键中有重复的数据。在Redis中设置添加,删除和测试成员的存在(恒定时间O(1),而不考虑集合中包含的元素数量)。列表的最大长度为2^32 - 1个元素

    1
    2
    3
    4
    5
    6
    7
    8
    SADD myset "redis" #添加到set
    SMEMBERS "myset" #获取myset所有元素
    SCARD key #获取集合中的成员数
    SDIFF key1 [key2] # 减去多个集合
    SDIFFSTORE destination key1 [key2] # 减去多个集并将结果集存储在键中
    SINTER key1 [key2] # 相交多个集合
    SINTERSTORE destination key1 [key2] # 交叉多个集合并将结果集存储在键中
    SISMEMBER key member # 判断确定给定值是否是集合的成员

基于URL的权限管理

发表于 2017-06-18 | 分类于 权限管理

基于url的权限管理

[TOC]

神马是权限管理

​ 只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
​ 权限管理包括用户认证和授权两部分。

  • 用户认证

    用户认证,用户去访问系统,系统要验证用户身份的合法性。最常用的用户身份验证的方法:1、用户名密码方式、2、指纹打卡机、3、基于证书验证方法。。系统验证用户身份合法,用户方可访问系统的资源。

这里写图片描述

  • 用户授权

    用户授权,简单理解为访问控制,在用户认证通过后,系统对用户访问资源进行控制,用户具有资源的访问权限方可访问。

    这里写图片描述

    ​

常用权限模型

​ 模型数据:

​ 主体(账号、密码)
​ 资源(资源名称、访问地址)
​ 权限(权限名称、资源id)
​ 角色(角色名称)
​ 角色和权限关系(角色id、权限id)
​ 主体和角色关系(主体id、角色id)

这里写图片描述

通常情况下我们将权限和资源合并到一张表中,简化开发。如上图。

权限控制

  1. 基于角色的权限控制。

    通过判定用户是否是某个角色而进行权限操作。基于角色的访问控制是不利于系统维护(可扩展性不强)。

  2. 基于资源的权限控制

    通过判定用户是否对某资源拥有操作权进行权限控制。建议使用基于资源的访问控制实现权限管理。

    ​

123
forever_zs

forever_zs

26 日志
15 分类
39 标签
GitHub Twitter 微博 豆瓣 知乎
© 2017 forever_zs
由 Hexo 强力驱动
主题 - NexT.Pisces