webapi 数据库放在哪里合适_vs创建webapi 数据库在哪里 - CSDN
精华内容
参与话题
  • 找了好多天都没找到小程序批量上传图片的方法,然后我现在的逻辑是: 取到上传图片的集合,循环调用小程序wx.UploadFile方法,依次上传 ...小程序前端每次把上传返回的MD5入一个集合中。或者以逗号分隔的字符...

    找了好久都没找到合适的小程序批量上传图片的方法,最终还是只能循环上传,就自己扣了一个:
    思路:

    1. 调用小程序上传图片接口后(API参考小程序开发文档,很详细),取到上传图片的集合,循环调用小程序wx.UploadFile方法,依次上传
    2. 后端取到文件之后生成唯一MD5码(相同的文件生成的MD5码是唯一的),然后取前两位后两位创建文件夹,保存图片前判断下图片是否存在。(这样一个完全相同的图片就不会被重复被保存在服务器上了)
    3. 把每次上传后端API接口返回的MD5和文件后缀名,以逗号分隔拼成字符串。所有的文件上传完成之后,请求APi接口,批量保存在数据库TB_File表中;
    4. 以后调用时通过生成MD5的逻辑截取路径取图片,我这里取的前两位后两位

    Api代码:

    [HttpPost]
            public IHttpActionResult SaveImages2()
            {
                HttpPostedFile file = HttpContext.Current.Request.Files["file"];//接收
                string ext = Path.GetExtension(file.FileName);//文件后缀名
                Stream s = file.InputStream;//文件流
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(s);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                string md5Res = sb.ToString();//上面的代码是为了生成文件唯一的MD5码
                string path = md5Res .Substring(0, 2);
                string path1=md5Res .Substring(md5Res .Length - 2, 2)//取MD5的前两位和后两位生成文件夹,把图片存在后两位的文件夹内
                string fileSaveLocation = $"E:\\CoolSchoolImages\\{path}\\{path1}\\{md5Res }.jpg";.//文件最终保存路径
                if (!File.Exists(fileSaveLocation))//判断文件是否存在
                {//若不存在
                    Directory.CreateDirectory($"E:\\CoolSchoolImages\\{path}\\{path1}");//这个方法创建文件夹的时候如果文件夹存在的话就不会创建了,所以不管文件有没有都调用一下,省得写那么多判断
                    file.SaveAs(fileSaveLocation);保存文件
                }
                return Ok(md5Res +ext);返回MD5码,用于后面保存在数据库
            }
    

    小程序部分代码
    这里的imgUrls是选择的图片数组,后面把返回的文件名加逗号拼接成了字符串,用于后面保存到数据库
    在这里插入图片描述

    展开全文
  • 在你开始使用数据库之前,确保你已经安装了合适数据库访问库。比如对于MySQL数据库,使用mysql-connector客户端来连接。下载Mysql数据并安装:从下面的连接里下载到Mysql数据库,它的版本是mysql-5.5.59-winx64....
    在你开始使用数据库之前,确保你已经安装了合适的数据库访问库。比如对于MySQL数据库,使用mysql-connector客户端来连接。
    下载Mysql数据并安装:
    从下面的连接里下载到Mysql数据库,它的版本是mysql-5.5.59-winx64.msi,这个适合Windows 64位版本,如果是linux你自己下载相应的版本。

    https://dev.mysql.com/downloads/mysql/


    然后再下载数据库的python客户端工具mysql-connector-python-8.0.6-rc-py3.6-windows-x86-64bit.msi:
    https://dev.mysql.com/downloads/connector/python/

    然后安装这两个工具,如果不熟悉,可以学习我的课程:

    在VC2015里学会使用MySQL数据库
    http://edu.csdn.net/course/detail/2672

    配置数据库完成之后,就可以在服务器管理器看到如下图:


    然后可以mysql数据库管理工具来创建数据库和创建表等,还可以插入数据:


    在这个工具里就可以运行下面的SQL语句:

    -- 配置MySQL连接为utf-8
    SET NAMES 'utf8';
    SET CHARSET 'utf8';
    
    -- 创建数据库
    CREATE DATABASE IF NOT EXISTS forum DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
    USE forum;
    
    -- 创建表users
    CREATE TABLE IF NOT EXISTS users
    (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT,
        email VARCHAR(100) NOT NULL,
        name VARCHAR(100) NOT NULL,
        password TEXT NOT NULL,
        picture TEXT NOT NULL,
        description TEXT,
        time TIMESTAMP DEFAULT NOW(),
        PRIMARY KEY(id),
        UNIQUE KEY(email),
        UNIQUE KEY(name)
    );
    
    -- 创建表posts
    CREATE TABLE IF NOT EXISTS posts
    (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT,
        title TEXT NOT NULL,
        content TEXT NOT NULL,
        time TIMESTAMP DEFAULT NOW(),
        user_id INT UNSIGNED,
        PRIMARY KEY(id),
        FOREIGN KEY(user_id) REFERENCES users(id)
    );
    
    -- 创建表comments
    CREATE TABLE IF NOT EXISTS comments
    (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT,
        content TEXT NOT NULL,
        time TIMESTAMP DEFAULT NOW(),
        user_id INT UNSIGNED,
        parent_id INT UNSIGNED,
        quote_id INT UNSIGNED,
        PRIMARY KEY(id),
        FOREIGN KEY(user_id) REFERENCES users(id),
        FOREIGN KEY(parent_id) REFERENCES posts(id),
        FOREIGN KEY(quote_id) REFERENCES comments(id)
    );
    
    -- 设置时区为北京时间
    -- 1.以下命令仅在当前会话期间有效
    /*SET time_zone = '+8:00';*/
    -- 2.以下命令则全局有效
    SET GLOBAL time_zone = '+8:00';

    运行这段SQL语句之后,就会创建一个论坛的数据库,但是为了简单地测试,我在这个数据库添加了自己的测试表:

    CREATE TABLE IF NOT EXISTS mintest
    (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT,
        email VARCHAR(100) NOT NULL,
        NAME VARCHAR(100) NOT NULL,    
        TIME TIMESTAMP DEFAULT NOW(),
        PRIMARY KEY(id),
        UNIQUE KEY(email),
        UNIQUE KEY(NAME)
    );

    这个表非常简单,只有四个字段,接着在这个表里插入几条数据,以便WEB可以查询到数据:

    INSERT INTO `forum`.`mintest` (`email`, `NAME`) VALUES ('90732041@qq.com', 'caimouse1'); 

    这时候,在这个表里就有几条数据,至于几条数据,就看你自己的操作了,如下:


    接着下来,就是创建WEB程序了,把数据库里的数据显示到页面。

    首先你需要创建一个数据库对象:
    db = web.database(dbn='mysql', host='127.0.0.1', port=3308,
                      db='forum', user='root', pw='12345678')
    根据需要修改这里 -- 尤其是username 、 password 、 dbname -- 。 MySQL用户还需要把 dbn 定义改为 mysql。)
    这就是所有你需要做的 -- web.py将会自动处理与数据库的连接和断开。
    然后把URL列表改回来,只保留 /:
    '/', 'index',
    像这样编辑并替换 index.html 的全部内容:
    $def with (mintests)
    <ul>
    $for test in mintests:
        <li id="t$test.id">$test.email</li>
        <li id="t$test.id">$test.NAME</li>
    </ul>

    这个模板就是把数据库的结果显示到页面里。完整的代码如下:

    #python 3.6    
    #蔡军生     
    #http://blog.csdn.net/caimouse/article/details/51749579    
    #
    import web
    
    urls = (
        '/', 'index'
    )
    
    
    app = web.application(urls, globals())
    render = web.template.render('templates/')
    db = web.database(dbn='mysql', host='127.0.0.1', port=3308,
                      db='forum', user='root', pw='12345678')
    
    class index:
        def GET(self):
           email = db.select('mintest')
           return render.index(email)        
        
    
    if __name__ == "__main__":
        app.run()

    运行这个程序,结果输出如下:


    到这里就实现使用WEBPY显示数据库的过程,其实是比较简单的。不过,记得更最新版本的WEB.PY项目:

    https://github.com/9073204qq/webpy

    否则执行MYSQL数据库的查询时,就会出错,因为原来的代码里有一个BUG。

    TensorFlow API攻略
    http://edu.csdn.net/course/detail/4495
    TensorFlow入门基本教程
    http://edu.csdn.net/course/detail/4369

    比特币源码入门教程

    https://edu.csdn.net/course/detail/6998

    深入浅出Matplotlib
    https://edu.csdn.net/course/detail/6859

    深入浅出Numpy
    http://edu.csdn.net/course/detail/6149 

    Python游戏开发入门


    展开全文
  • [HTML5点滴]客户端存储那些事

    千次阅读 2019-03-07 20:19:15
    客户端存储 译者:文蔺 ...客户端存储介绍本文是关于客户端存储(client-side storage)的。这是一个通用术语,包含几个独立但相关的 APIWeb Storage、Web SQL Database、Indexed Database 和 File Access。

    客户端存储

    译者:文蔺
    原文:http://www.html5rocks.com/en/tutorials/offline/storage/

    客户端存储

    介绍

    本文是关于客户端存储(client-side storage)的。这是一个通用术语,包含几个独立但相关的 API: Web Storage、Web SQL Database、Indexed Database 和 File Access。每种技术都提供了在用户硬盘上 —— 而非通常存储数据的服务器 —— 存储数据的独特方式。这么做主要基于以下两点理由:(a)使 web app 离线可用; (b)改善性能。对于客户端存储使用情况的详细阐述,请看 HTML5Rocks 上的文章 《“离线”: 这是什么意思?我为何要关心?》。

    这些 API 有着类似的作用范围和规则。因此,在去看细节之前,我们先了解他们的共同之处吧。

    共同特点

    基于客户端的存储

    实际上,“客户端时间存储”的意思是,数据传给了浏览器的存储 API,它将数据存在本地设备中的一块区域,该区域同样也是它存储其他用户特定信息如个人偏好、缓存的地方。除了存储数据,这些 API 可以用来检索数据,且在某些情况下还能执行搜索和批处理操作。

    置于沙盒中的

    所有这四个存储 API 都将数据绑到一个单独的“源”(origin)上。例如,若 http://abc.example.com 保存了一些数据,那以后浏览器就只会允许 http://abc.example.com 获取这些数据。当我们谈论“源”(origin)的时候,这意味着域(domain)必须完全相同,所以 http://example.comhttp://def.example.com 都不行。端口(port)也必须匹配,因此 http://abc.example.com:123 也是不能访问到 http://abc.example.com (端口默认为80)存储的数据。同样,协议也必须一样(像http vs https 等等)。

    空间限制(Quotas)

    你能想象,如果任何网站都被允许往毫不知情的硬盘里填充以千兆字节计的数据,该有多混乱。因此,浏览器对存储容量施加了限制。若你的应用试图超出限制,浏览器通常会显示一个对话框,让用户确认增加。您可能以为浏览器对单个源(origin)可使用的所有存储都加以同一单独的限制,但多数存储机制都是单独加以限制的。若 Quota API 被采纳,这种情况可能会改变。但就现在来说,把浏览器当作一个二维矩阵,其维度分别是“源”(origin)和“存储”(storage)。例如, “http://abc.example.com” 可能会允许最多存 5MB 的 Web Storage, 25MB 的 Web SQL 数据库,但因用户拒绝访问被禁止使用 Indexed DataBase。 Quota API 将问题放到一起来看,让您查询还有多少可用空间,有多少空间正在使用。

    有些情况下,用户也能先看到有多少存储将被使用,例如,当用户在 Chrome 应用商店中安装一个应用时,他们将被提示预先接受其权限,其中包括存储限制。(而该应用的)manifest 中的可能有个值是 “unlimited_storage” (无限制存储)。

    数据库处理(Transactions)

    两个 “数据库” 的存储格式支持数据处理。目的和通常的关系型数据库使用数据处理是一样的:保证数据库完整。数据库处理(Transactions)防止 “竞争条件”(race conditions) —— 这种情况是:当两个操作序列在同一时间被应用到数据库中, 导致操作结果都无法被预测,而数据库也处于可疑的准确性(dubious accuracy)状态。

    同步和异步模式(Synchronous and Asynchronous Modes)

    多数存储格式都支持同步和异步模式。同步模式是阻塞的,意味着下一行 js 代码执行之前,存储操作会被完整执行。异步模式会使得后面的 js 代码在数据库操作完成之前执行。存储操作会背景环境中执行,当操作完成的时候,应用会以回调函数被调用这种形式接收通知,这个函数须在调用的时候被指定。

    应当尽量避免使用同步模式,它虽然看起来比较简单,但操作完成时它会阻塞页面渲染,在某些情况下甚至会冻结整个浏览器。你可能注意到网站乃至是应用出现这种情况,点击一个按钮,结果所有东西都用不了,当你还在想是不是崩溃了?结果一切又突然恢复正常了。

    某些 API 没有异步模式,如 “localStorage”, 使用这些API时,应当仔细做好性能监测,并随时准备切换到一个异步API,如果它造成了问题。

    API 概述及比较

    Web Storage

    Web Storage 是一个叫做 localStorage 的持久对象。可以使用 localStorage.foo = "bar" 保存值,之后可以使用 localStorage.foo 获取到 —— 甚至是浏览器关闭之后重新打开。还可以使用一个叫做 sessionStorage 的对象,工作方式一样,只是当窗口关闭之后会被清除掉。

    Web Storage 是 NoSQL 键值对储存(NoSQL key-value store)的一种.

    Web Storage 的优点
    1. 数年以来,被所有现代浏览器支持, iOS 和 Android 系统下也支持(IE 从 IE8 开始支持 )。
    2. 简单的API签名。
    3. 同步 API,调用简单。
    4. 语义事件可保持其他标签和窗口同步。
    Web Storage 的弱点
    1. 使用同步 API(这是得到最广泛支持的模式)存储大量的或者复杂的数据时性能差。
    2. 缺少索引导致检索大量的或复杂的数据时性能差。(搜索操作需要手动遍历所有项。)
    3. 存储或读取大量的或复杂的数据结构时性能差,因为需要手动序序列化成字符串或将字符串反序列化。主要的浏览器实现只支持字符串(尽管规范没这么说的)。
    4. 需要保证数据的持续性和完整性,因为数据是有效非结构化(effectively unstructured)的。

    Web SQL Database

    Web SQL Database 是一个结构化的数据库,具备典型 SQL驱动的关系数据库(SQL-powered relational database)的所有功能和复杂度。Indexed Database 在两者之间。Web SQL Database 有自由形式的密钥值对,有点像 Web Storage,但也有能力从这些值来索引字段,所以搜索速度要快得多。

    Web SQL Database 的优点
    1. 被主要的移动浏览器(Android Browser, Mobile Safari, Opera Mobile)以及一些 PC 浏览器(Chrome, Safari, Opera) 支持。
    2. 作为异步 API, 总体而言性能很好。数据库交互不会锁定用户界面。(同步API也可用于 WebWorkers。)
    3. 良好的搜索性能,因为数据可以根据搜索键进行索引。
    4. 强大,因为它支持事务性数据库模型(transactional database model)
    5. 刚性的数据结构更容易保持数据的完整性。
    Web SQL Database 的弱点
    1. 过时,不会被 IE 或 Firefox 支持,在某些阶段可能会被从其他浏览器淘汰。
    2. 学习曲线陡峭,要求掌握关系数据库和SQL的知识。
    3. 对象-关系阻抗失配(object-relational impedance mismatch).
    4. 降低敏捷性,因为数据库模式必须预先定义,与表中的所有记录必须匹配相同的结构。

    Indexed Database (IndexedDB)

    到目前为止,我们已经看到,Web Storage 和 Web SQL Database 都有各种的优势和弱点。 Indexed Database 产生于这两个早期 API 的经验,可以看作是一种结合两者优点而不招致其劣势得到尝试。

    Indexed Database 是一个 “对象存储” (object stores) 的集合,可以直接把对象放进去。这个存储有点像 SQL 表,但在这种情况下,对象的结构没有约束,所以不需要预先定义什么。所以这和 Web Storage 有点像,拥有多个数据库、每个数据库又有多个存储(store)的特点。但不像 Web Storage那样, 还拥有重要的性能优势: 异步接口,可以在存储上创建索引,以提高搜索速度。

    IndexedDB 的优点
    1. 作为异步API总体表现良好。数据库交互不会锁定用户界面。(同步 API 也可用于 WebWorkers。)
    2. 良好的搜索性能,因为数据可以根据搜索键进行索引。
    3. 支持版本控制。
    4. 强大,因为它支持事务性数据库模型(transactional database model)
    5. 因为数据模型简单,学习曲线也相当简单。
    6. 良好的浏览器支持: Chrome, Firefox, mobile FF, IE10.
    IndexedDB 的弱点
    1. 非常复杂的API,导致大量的嵌套回调。

    FileSystem

    上面的 API 都是适用于文本和结构化数据,但涉及到大文件和二进制内容时,我们需要一些其他的东西。幸运的是,我们现在有了文件系统 API 标准(FileSystem API standard)。它给每个域一个完整的层次化的文件系统,至少在 Chrome 下面,这些都是用户的硬盘上的真正的文件。就单个文件的读写而言, API 建立在现有的 File API之上。

    FileSystem(文件系统) API 的有点
    1. 可以存储大量的内容和二进制文件,很适合图像,音频,视频,PDF,等。
    2. 作为异步 API, 性能良好。
    FileSystem API 的弱点
    1. 很早的标准,只有 Chrome 和 Opera 支持。
    2. 没有事务(transaction)支持。
    3. 没有内建的搜索/索引支持。

    来看代码

    本部分比较不同的 API 如何解决同一个问题。这个例子是一个 “地理情绪”(geo-mood) 签到系统,在那里你可以记录你在时间和地点的情绪。接口可让你在数据库类型之间切换。当然,在现实情况中,这可能显得有点作(contrived),数据库类型肯定比其他的更有意义,文件系统 API 根本不适用于这种应用!但为了演示的目的,如果我们能看到使用不同方式达到同样的结果,这还是有帮助的。还得注意,为了保值可读性,一些代码片段是经过重构的。

    现在可以来试试我们的“地理情绪”(geo-mood)应用。

    为了让 Demo 更有意思,我们将数据存储单独拿出来,使用标准的面向对象的设计技术(standard object-oriented design techniques)。 UI 逻辑只知道有一个 store;它无需知道 store 是如何实现的,因为每个 store 的方法是一样的。因此 UI 层代码可以称为 store.setup()store.count() 等等。实际上,我们的 store 有四种实现,每种对应一种存储类型。应用启动的时候,检查 URL 并实例化对应的 store。

    为了保持 API 的一致性,所有的方法都是异步的,即它们将结果返回给调用方。Web Storage 的实现甚至也是这样的,其底层实现是本地的。

    在下面的演示中,我们将跳过 UI 和定位逻辑,聚焦于存储技术。

    建立 Store

    localStorage,我们做个简单的检验看存储是否存在。如果不存在,则新建一个数组,并将其存储在 localStorage 的 checkins(签到) 键下面。首先,我们使用 JSON 对象将结构序列化为字符串,因为大多数浏览器只支持字符串存储。

    if  (!localStorage.checkins) localStorage.checkins = JSON.stringify([]);
    

    Web SQL Database,数据库结构如果不存在的话,我们需要先创建。幸运的是,如果数据库不存在,openDatabase 方法会自动创建数据库;同样,使用 SQL 句 “if not exists” 可以确保新的 checkins 表 如果已经存在的话不会被重写。我们需要预先定义好数据结构,也就是, checkins 表每列的名称和类型。每一行数据代表一次签到。

    this.db = openDatabase('geomood', '1.0', 'Geo-Mood Checkins', 8192);
    this.db.transaction(function(tx) {
        tx.executeSql(
            "create table if not exists "
                + "checkins(id integer primary key asc, time integer, latitude float,"
                + "longitude float, mood string)",
             [], function() {
                console.log("siucc"); 
            }
        );
    });
    

    Indexed Database 启动需要一些工作,因为它需要启用一个数据库版本系统。当我们连接数据库的时候要明确我们需要那个版本,如果当前数据库使用的是之前的版本或者还尚未被创建,会触发 onupgradeneeded 事件,当升级完成后 onsuccess 事件会被触发。如果无需升级,onsuccess 事件马上就会触发。

    另外一件事就是创建 “mood” 索引,以便之后能很快地查询到匹配的情绪。

    var db;
    var version = 1;
    window.indexedStore = {};
    window.indexedStore.setup = function(handler) { // attempt to open the database
        var request = indexedDB.open("geomood", version);  // upgrade/create the database if needed
        request.onupgradeneeded =  function(event)  {
            var db = request.result;
            if  (event.oldVersion <  1)  { // Version 1 is the first version of the database.
                var checkinsStore = db.createObjectStore("checkins",  { keyPath:  "time"  });
                checkinsStore.createIndex("moodIndex",  "mood",  { unique:  false  });
            }
            if  (event.oldVersion <  2)  {
                // In future versions we'd upgrade our database here. 
                // This will never run here, because we're version 1.
            }
            db = request.result;
        };
        request.onsuccess =  function(ev)  {  // assign the database for access outside
            db = request.result; handler();
            db.onerror =  function(ev)  {
                console.log("db error", arguments);
            };
        };
    };
    

    最后,启动 FileSystem。我们会把每种签到 JSON 编码后放在单独的文件中,它们都在 “checkins/” 目录下面。同样这并非 FileSystem API 最合适的用途,但对演示来说还挺好。

    启动在整个文件系统中拿到一个控制手柄(handle),用来检查 “checkins/” 目录。如果目录不存在,使用 getDirectory 创建。

    setup:  function(handler)  {
        requestFileSystem(
            window.PERSISTENT,
            1024*1024,
            function(fs)  {
                fs.root.getDirectory(
                    "checkins",
                    {},  // no "create" option, so this is a read op
                    function(dir)  {
                        checkinsDir = dir;
                        handler();
                    }, 
                    function()  {
                        fs.root.getDirectory( "checkins",  {create:  true},  function(dir)  { checkinsDir = dir;
                            handler();
                        }, onError );
                    }
                );
            },
            function(e)  {
                console.log("error "+e.code+"initialising - see http://goo.gl/YW0TI");
            }  
        );
    }
    

    保存一次签到 (Check-in)

    使用 localStorage,我们只需要拿出 check-in 数组,在尾部添加一个,然后重新保存就行。我们还需要使用 JSON 对象的方法将其以字符串的方式存起来。

    var checkins = JSON.parse(localStorage["checkins"]);
    checkins.push(checkin);
    localStorage["checkins"] = JSON.stringify(checkins);
    

    使用 Web SQL Database,所有的事情都在 transaction 中进行。我们要在 checkins 表 创建新的一行,这是一个简单的 SQL 调用,我们使用 “?” 语法,而不是把所有的签到数据都放到 “insert” 命令中,这样更整洁,也更安全。真正的数据——我们要保存的四个值——被放到第二行。“?” 元素会被这些值(checkin.timecheckin.latitude等等)替换掉。接下来的两个参数是操作完成之后被调用的函数,分别在成功和失败后调用。在这个应用中,我们对所有操作使用相同的通用错误处理程序。这样,成功回调函数就是我们传给搜索函数的句柄——确保句柄在成功的时候被调用,以便操作完成之后 UI 能接到通知(比如,更新目前为止的签到数量)。

    store.db.transaction(function(tx) {
        tx.executeSql(
            "insert into checkins " + "(time, latitude, longitude, mood) values (?,?,?,?);", 
            [checkin.time, checkin.latitude, checkin.longitude, checkin.mood],
            handler, 
            store.onError
        ); 
    });
    

    一旦存储建立起来,将其存储到 IndexedDB 中就像 Web Storage 差不多简单,还有异步工作的优点。

    var transaction = db.transaction("checkins",  'readwrite'); 
    transaction.objectStore("checkins").put(checkin); 
    transaction.oncomplete = handler;
    

    使用 FileSystem API,新建文件并拿到相应的句柄,可以用 FileWriter API 进行填充。

    fs.root.getFile(
        "checkins/" + checkin.time,
        { create: true, exclusive: true }, 
        function(file) {
            file.createWriter(function(writer) {
                writer.onerror = fileStore.onError;
                var bb = new WebKitBlobBuilder;
                bb.append(JSON.stringify(checkin));
                writer.write(bb.getBlob("text/plain"));
                handler(); }, fileStore.onError);
        },
        fileStore.onError
    );
    

    搜索匹配项

    接下来的函数找到所有匹配特定情绪的签到,例如,用户能看到他们在最近何时何地过得很开心。使用 localStorage, 我们必须手动遍历每次签到并将其与搜索的情绪对比,建立一个匹配列表。比较好的实践是返回存储数据的克隆,而不是实际的对象,因为搜索应该是一个只读的操作;所以我们将每个匹配的签到对象传递给通用的 clone() 方法进行操作。

    var allCheckins = JSON.parse(localStorage["checkins"]);
    var matchingCheckins = [];
    allCheckins.forEach(function(checkin) {
        if (checkin.mood == moodQuery) {
            matchingCheckins.push(clone(checkin));
        } 
    });
    handler(matchingCheckins);
    

    使用 Web SQL Database,我们执行一次查询,只返回我们需要的行。但我们仍需要手动遍历来累计签到数据,因为数据库 API 返回的是数据库行,而不是一个数组。(对大的结果集来说这是好事,但就现在而言这增加了我们需要的工作!)

    var matchingCheckins = [];
    store.db.transaction(function(tx) {
        tx.executeSql(
            "select * from checkins where mood=?",
            [moodQuery],
            function(tx, results) {
                for (var i = 0; i < results.rows.length; i++) {
                    matchingCheckins.push(clone(results.rows.item(i)));
                }
                handler(matchingCheckins); 
            },
            store.onError
        );
    });
    

    当然,在 IndexedDB 解决方案使用索引,我们先前在 “mood” 表中创建的索引,称为“moodindex”。我们用一个指针遍历每次签到以匹配查询。注意这个指针模式也可以用于整个存储;因此,使用索引就像我们在商店里的一个窗口前,只能看到匹配的对象(类似于在传统数据库中的“视图”)。

    var store = db.transaction("checkins", 'readonly').objectStore("checkins");
    var request = moodQuery ? store.index("moodIndex").openCursor(new IDBKeyRange.only(moodQuery)) : store.openCursor();
    request.onsuccess = function(ev) {
        var cursor = request.result;
        if (cursor) {
            handler(cursor.value);
            cursor["continue"]();
        } 
    };
    

    与许多传统的文件系统一样,FileSystem API 没有索引,所以搜索算法(如 Unix中的 “grep” 命令)必须遍历每个文件。我们从 “checkins/” 目录中拿到 Reader API ,通过 readentries() 。对于每个文件,再使用一个 reader,使用 readastext() 方法检查其内容。这些操作都是异步的,我们需要使用 readnext() 将调用连在一起。

    checkinsDir.createReader().readEntries(function(files) {
        var reader, fileCount = 0,
            checkins = [];
        var readNextFile = function() {
            reader = new FileReader();
            if (fileCount == files.length) return;
            reader.onload = function(e) {
                var checkin = JSON.parse(this.result);
                if (moodQuery == checkin.mood || !moodQuery) handler(checkin);
                readNextFile();
            };
    
            files[fileCount++].file(function(file) {
                reader.readAsText(file);
            });
        };
        readNextFile();
    });
    

    匹配计数

    最后,我们需要给所有签到计数。

    对localStorage,我们简单的反序列化签到数组,读取其长度。

    handler(JSON.parse(localStorage["checkins"]).length);
    

    对 Web SQL Database,可以检索数据库中的每一行(select * from checkins),看结果集的长度。但如果我们知道我们在 SQL 中,有更容易和更快的方式 —— 我们可以执行一个特殊的 select 语句来检索计数。它将返回一行,其中一列包含计数。

    store.db.transaction(function(tx) {
        tx.executeSql("select count(*) from checkins;", [], function(tx, results) {
            handler(results.rows.item(0)["count(*)"]);
        }, store.onError);
    });
    

    不幸的是, IndexedDB 不提供任何计算方法,所以我们只能自己遍历。

    var count = 0;
    var request = db.transaction(["checkins"], 'readonly').objectStore("checkins").openCursor();
    request.onsuccess = function(ev) {
        var cursor = request.result;
        cursor ? ++count && cursor["continue"]() : handler(count);
    };
    

    对于文件系统, directory reader 的 readentries() 方法提供一个文件列表,所以我们返回该列表的长度就好。

    checkinsDir.createReader().readEntries(function(files)  {
        handler(files.length);
    });
    

    总结

    本文从较高层次的角度,讲述了现代客户端存储技术
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    展开全文
  • 几种开源规则引擎(BRE)的比较

    万次阅读 2007-06-18 09:37:00
    1 产品构成比较1. JBoss RulesJBoos Rules产品主要包括以下几个部分:1. The Rule Engine2. The Rule Language3.... The Java Rule Engine API6. Deployment and TestingRule Engine引擎的构成

     1 产品构成比较
    1. JBoss Rules
    JBoos Rules产品主要包括以下几个部分:
    1. The Rule Engine
    2. The Rule Language
    3. Decision Tables
    4. The Rule Workbench (IDE)
    5. The Java Rule Engine API
    6. Deployment and Testing

    Rule Engine引擎的构成分为两部分,Authoring and Runtime
    Authoring Components如下图所示:

    Runtime Components结构如下图所示
     

    2. OpenResults
    模块组成如下:
      

    3. OpenLexicon
    OpenLexicon的模块如下图所示:

    2 关键产品特性比较
    2.1 规则表示法
    2.1.1 JBoss Rules

    JBoss Rules有三种规则的表示法
    1. The Rule Language
    2. Domain Specific Languages
    3. Decision Tables
    还有XML格式的
    XML Rule Language
    2.1.2 OpenRules
    OpenRules只有Decision Table形式
    2.1.3 OpenLexicon
    OpenLexicon不是代码生成(code-generator)的软件,通过Web界面配置规则,并保存在数据库中。
    2.2 规则算法和方法
    2.2.1 JBoss Rules
    JBoss Rules的规则采用RETE算法--ReteOO(Rete algorithm for Object Oriented systems),并且实现了问题域(problem domain)的Domain Specific Languages(DSL)
    2.2.2 OpenRules
    JBoss采用Rete算法
    2.2.3 OpenLexicon

    2.3 规则开发
    2.3.1 JBoss Rules
    JBoss提供以下工具实现规则的开发
    1. Rule IDE
    2. spreadsheets (that is Excel, OpenOffice)
    3. XML
    这些工具完全集成在Eclipse中
    2.3.2 OpenRules
    OpenRules采用Excel,OpenOffice等工具开发规则,并提供Eclipse plugin创建和管理项目,但是并不提供Rule IDE.
    2.3.3 OpenLexicon
    OpenLexicon提供Web Based Wizard,可以发布规则为WebService,同时Eclipse plugin创建WSDL和数据类型(XSD's)。
    2.4 规则知识库
    2.4.1 JBoss Rules

    JBoss Rules的规则知识库是文本方式/XML和Excel(Decision Tables)方式的,不支持把知识库放在数据库中。
    2.4.2 OpenRules
    规则知识库是Excel(Decision Tables)方式的,不支持把知识库放在数据库中
    2.4.3 OpenLexicon
    规则知识库保存在数据库中,并支持MySQL, Oracle, MS Sql Server, TimesTen等。
    2.5 Web化支持程度
    2.5.1 JBoss Rules
    不支持Web编辑,提供Rule IDE, Excel等工具
    2.5.2 OpenRules
    不支持Web编辑,提供Excel等工具
    2.5.3 OpenLexcicon
    支持Web编辑
    2.6 产品易用性
    2.6.1 JBoos Rules
    JBoss Rules提供的Rule IDE,可以方便地编辑DRL和DSL文件。
    使用Excel或者OpenOffice等工具编辑Decision Table
    2.6.2 OpenRules
    OpenRules使用 Excel或者OpenOffice等工具编辑Decision Table,尽管OpenRules声称所提供的工具非常方便,可以面向非开发人员,但仍然需要有一定的技术基础。
    2.6.3 OpenLexicon
    OpenLexicon提供基于Web-Form的Wizard。尽管OpenLexicon声称提供面向非开发人员的工具,但是仍然需要有一定的技术基础,如数据库等。
    2.7 体系架构支持
    2.7.1 JBoss Rules

    JBoss Rules可以通过XML,支持Java, python or groovy
    JBoss Rules是纯J2EE架构,并借助与JBoss AS, Hibernatre, BMP等其他框架,开发强大的系统。
    2.7.2 OpenRules
    OpenRules支持J2EE架构,并声称在以下平台通过测试:IBM WebSphere,BEA WebLogic,和Apache Tomcat.

    2.7.3 OpenLexicon
    OpenLexicon默认支持Tomcat,MySQL,对其他平台的支持需要配置。
    2.8 支持的标准
    2.8.1 JBoss Rules
    Java Rules Engine API
    JSR-94
    2.8.2 OpenRules
    Java Rules Engine API
    JSR-94
    2.8.3 OpenLexicon
    不支持公开的标准
    3 关于二次开发
    3.1 中文规则

    以上三种软件都不支持中文表达的规则表示,在这个层面上难度是一样的
    3.2 基于Web的规则定制界面
    OpenLexicon本身就是基于Web界面的,但是目前这个软件提供的界面并不适合非技术人员使用,可以让非开发人员使用。
    OpenRules只提供了Excel方式的规则编辑,但同时也提供了用Excel支持的Web Form,也就是说使用Excel制作一个Web Form,生成WEB页面中。Excel是非常容易使用的工具,但是嵌入WEB页面中会使Excel失去优势。
    JBoss Rules提供Excel方式的Decision Table, 与OpenRules类似,不适合将Excel放入Web页面中。但JBoss Rules提供的Drl和Dsl文件的IDE工具可以做为Java Applet嵌人WEB页面。
    综上所述,如果开发面向没有技术背景的用户使用的Web页面,这三个软件都需要有一定的开发工作量,相比较而言OpenLexicon是最容易的,JBoss次之,OpenRules最差
    3.3 软件适用范围
    OpenRules提供Decision Tables快速地加入应用软件,JBoss Rules对于专家系统来说是非常好的,如果开发业务事物中的UseCase,客户或者合作伙伴集成的软件,则OpenLexicon比较合适。

    3.4 软件的成熟度
    在这三个软件中OpenRules是最成熟的,使用范围也最广,OpenRules次之,OpenLexicon是比较新的软件,其前景还不知道。

     

    展开全文
  • 什么是服务端开发

    千次阅读 2014-10-16 10:07:25
    根据具体用途分为两种:Web页面开发和API接口开发。Web页面开发也完全可以看成是API接口开发,只是它的两个主要部分,页面和ajax请求,一个是返回html,另外一个可以返回html,也可以返回其他格式的而已。API接口...
  • Autosqli——一个sqlmapapiweb管理应用

    千次阅读 2017-06-26 16:59:33
    Autosqli——一个sqlmapapiweb管理应用
  • Javaweb经典三层架构的演变

    千次阅读 2018-01-09 17:20:01
    Model1第一代时期,服务器端只有JSP页面,所有的操作都在JSP页面中,连访问数据库API也在JSP页面中完成。也就是说,所有的东西都耦合在一起,对后期的维护和扩展极为不利。 ②JSP Model1第二代 JSP Model1第...
  • 作者:Rachel Appel   管理数据是应用开发中非常关键的一个环节。无论是游戏,新闻,旅游还是关于时尚的应用,都总是与数据密不可分。Win8应用经常需要管理一些存储在不同位置且格式多种多样的散乱数据。...
  • 数据库连接技术整理

    千次阅读 2017-02-09 16:00:51
    ODBC(Open Database Connectivity,开放数据库互连)是微软公司开放服务结构(WOSA,Windows Open Services Architecture)中有关数据库的一个组成部分,它建立了一组规范,并提供了一组对数据库访问的标准API...
  • 数据库连接池原理

    千次阅读 2015-11-20 15:38:24
    一、使用数据库连接池的意义1、Java应用程序访问数据库的基本原理 在Java语言中,JDBC(Java DataBa
  • Flask是什么?

    万次阅读 2018-04-23 10:35:43
    “微”(micro) 并不意味着你要把整个web应用到一个python文件里(虽然确实可以),也不意味着Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心功能的简单而易于扩展。Flask 不会替你做出太多.....
  • 一、概述 Nova(OpenStack Compute Service)是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源,同时管理虚拟机生命周期。 Nova 在整个 OpenStack 架构中的位置如下图: 在上图中可以看到,...
  • Struts原理与实践(三)

    万次阅读 2004-10-18 22:29:00
    一、JDBC的工作原理 Struts在本质上是java程序,要在Struts应用程序中访问数据库,首先,必须搞清楚Java Database Connectivity API(JDBC)的工作原理。正如其名字揭示的,JDBC库提供了一个底层API,用来支持独立于...
  • python flask api接口开发编程

    万次阅读 多人点赞 2016-10-10 19:48:46
    使用 Python 和 Flask 设计 RESTful API 近些年来 REST (REpresentational State Transfer) 已经变成了 web services 和 web APIs 的标配。 在本文中我将向你展示如何简单地使用 Python 和 Flask 框架来创建一...
  • Django REST framework 理解

    千次阅读 2018-07-03 23:46:37
    Web应用模式1 .前后端不分离:在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与厚度那的耦合度很高.这种应用模式比较合适纯网页应用,但是...
  • struts中的JDBC

    千次阅读 2006-05-28 14:38:00
    Struts在本质上是java程序,要在Struts应用程序中访问数据库,首先,必须搞清楚Java Database Connectivity API(JDBC)的工作原理。正如其名字揭示的,JDBC库提供了一个底层API,用来支持独立于任何特定SQL实现的基本...
  • JavaEE的13个核心规范

    千次阅读 2018-12-26 19:02:51
    · JavaEE的13个规范其实就是JavaEE的13个API文档,是一种比较抽象的标准。 1、JDBC(Java Database Connectivity)  JDBC 为访问不同的数据库提供了一种统一的方法,类似的API还有微软的ODBC。JDBC包含众多接口...
  • MVC概述

    千次阅读 2018-08-13 14:49:29
    1 MVC设计模式 MVC设计模式   MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。 ...MVC模式最早为Trygve ...
  • JavaEE体系架构概述

    千次阅读 2014-06-29 21:14:27
    闲的蛋痛,复习下。 1.java web应用的缺陷 2.什么是企业级应用 3.javaee体系平台核心思想 4.ejb组件和容器 5.pojo与轻量级框架 javaweb应用的缺陷
  • 微服务企业数据访问模式

    千次阅读 2017-04-13 13:15:30
    本文将介绍在使整体式应用程序演化为微服务架构时要考虑的重要数据库主题。其中将介绍一些可能遇到的挑战,以及可用来解决这些挑战的模式。还将通过一个示例,展示将 Java 应用程序从整体式模式转变为微服务的必要...
1 2 3 4 5 ... 20
收藏数 32,606
精华内容 13,042
关键字:

webapi 数据库放在哪里合适