• Nodejs+mySql实现长地址转短地址


    一、开发原因

      之前公司用一些在线的转短地址网站,但出来的的地址输入没规则,输入太麻烦了,而且扫码还需要安装一个扫码的软件,在一个就是不能转换本地代理的地址(例:http://192.168.1.200:8080),心累。正好公司有个闲置的电脑做服务器,想着干嘛不搞个本地的转短地址工具,这样可以随意设置,想咋弄就咋弄。

      注:这个插件没有部署到服务器上,只是在本地搭建了一个可运行环境,在局域网内可以随意访问。不过只要部署到服务器,再给个域名,就完全可以用,童鞋们可以自行补全。

    二、开发环境

    1. 系统环境:macOS, Version 10.13.1
    2. nodejs (v9.2.0)  后台语言
    3. mysql (v5.7.17)  数据库
    4. MySQLWorkbench (v6.3.10)  数据库可视化工具
    5. Chrome Extension  Chrome插件

    三、分析开发流程

    1. 获取长链接地址
    2. 把地址传给后台
    3. 查找数据库里面是否存在改地址
    4. 生成短地址
    5. 返回短地址数据

    四、开发流程

     4.1 分析数据库、搭建数据库

       数据库至少需要三个字段(id、长地址、短地址),三个字段一目了然就不做介绍了。装好mySql后大神可以直接用命令行建数据库,我这里用的一个可视化工具(MySQLWorkbench)建的数据库。对于数据库最重要的一点是要设置字符集格式,因为地址中会出现一些类似xxx=xxx&xxx=xxx这样的数据,这样在做比较的时候就会报错。可以添加如下代码解决: 

    1 SET collation_connection = 'utf8_general_ci';
    2 ALTER DATABASE url CHARACTER SET utf8 COLLATE utf8_general_ci;
    3 ALTER TABLE url.shortUrl CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

     4.2 搭建后台程序框架

        后台框架很简单,主要两个文件就搞定,结构如下:

        app.js文件用来开本地服务,以及处理传进来的信息(长地址)。mysqlPool.js用来操作数据库。

    app.js:

     1 var http = require('http');
     2 var url = require('url');
     3 var UrlInfo = require('./routes/mysqlPool');
     4 
     5 var serve = http.createServer(function(req, res){
     6    // 过滤favicon.ico请求
     7     if(req.url !== '/favicon.ico'){
     8         var obj = url.parse(req.url, true);
     9         var pathname = obj.pathname;
    10         // 分割地址信息
    11         var nameArr = pathname.toString().split('/');
    12         
    13         if(nameArr[1] === ''){
    14             res.end();
    15         }else if(nameArr[1] === 'insert'){  // 表示插入操作
    16             var firstChart = obj.search.indexOf('=');
    17             //获取需要存储的长地址
    18             var longAddress = obj.search.substring(firstChart+1, obj.search.length);
    19             // 根据长地址查询数据库是否存在此条信息。
    20             UrlInfo.getUrlInfoByLongAddress(longAddress, function(err, reuslt){
    21                 if(err){
    22                     // 这里对数据库的字符集设置有要求,如果设置不对则会报错,具体设置参考上面数据库搭建
    23                     console.log(err);
    24                 }else{
    25                     // 如果存在这条信息,则返回短地址
    26                     if(reuslt.length > 0){
    27                         var longUrl = reuslt[0].longAddress;
    28                         var shortUrl = reuslt[0].shortAddress;
    29                         var data = {
    30                             'longAddress': longUrl,
    31                             'shortAddress': shortUrl
    32                         };
    33                         res.write(JSON.stringify(data));
    34                         res.end();
    35                     }else{
    36                         // 查询最大的id值
    37                         UrlInfo.getMaxId(function(err, reuslt){
    38                             var maxID = reuslt[0]['max(id)'];
    39                             // 如果id号大于或等于99则清空数据库,保证短地址最短,这个值看需求设置
    40                             if(maxID >= 99){
    41                                 UrlInfo.deleteAllData(function(err, reuslt){
    42                                     if(reuslt){
    43                                         maxID = 0;
    44                                         UrlInfo.insertInfo(maxID + 1, longAddress, function(err, reuslt, backData){
    45                                             if(reuslt){
    46                                                 var data = {
    47                                                     'longAddress': backData.longAddress,
    48                                                     'shortAddress': backData.shortAddress
    49                                                 };
    50                                                 res.write(JSON.stringify(data));
    51                                             }
    52                                             res.end();
    53                                         });
    54                                     }else{
    55                                         res.end();
    56                                     }
    57                                 });
    58                             }else{
    59                                 // 插入新信息并返回短地址
    60                                 UrlInfo.insertInfo(maxID + 1, longAddress, function(err, reuslt, backData){
    61                                     if(reuslt){
    62                                         var data = {
    63                                             'longAddress': backData.longAddress,
    64                                             'shortAddress': backData.shortAddress
    65                                         };
    66                                         res.write(JSON.stringify(data));
    67                                         res.end(); 
    68                                     }else{
    69                                         res.end(); 
    70                                     }
    71                                 });
    72                             }
    73                         });
    74                     }
    75                 }
    76             });
    77         }else{  // 表示请求操作
    78             UrlInfo.getUrlInfoById(nameArr[1], function(err, reuslt){
    79                 // 如果请求格式错误则跳到百度去(免费打了个广告)
    80                 if(err){
    81                     res.writeHead(302, {
    82                         'Location': 'http://www.baidu.com'
    83                     });
    84                 }else{
    85                     // 根据id获取到对应的短地址
    86                     var longUrl = reuslt[0].longAddress;
    87                     // 重定向操作,实现短地址跳转到长地址
    88                     res.writeHead(302, {
    89                         'Location': longUrl
    90                     });
    91                 }
    92                 res.end();
    93             });
    94         }
    95     }
    96 }).listen(3000);

    mysqlPool.js:

      1 var mysql = require('mysql');
      2 
      3 var ipConfig = 'http://192.168.1.200:3000/';
      4 
      5 //创建一个连接池
      6 var pool = mysql.createPool({
      7     host: '127.0.0.1',
      8     user: 'root',
      9     password: '1234',
     10     database: 'url',
     11     port: '3306'
     12 });
     13 
     14 pool.on('connection', function(connection) {  
     15     connection.query('SET SESSION auto_increment_increment=1'); 
     16 });  
     17 
     18 
     19 module.exports = {
     20     // 这里对错误用try,catch抓取,防止错误导致服务器关闭,当然这些错误都没处理,要想完整一些可以自行处理
     21     // 这里每个方法都有一个数据库链接操作,可以提炼公共的方法来简化代码
     22     getUrlInfoById: function(id, callback){
     23         pool.getConnection(function(err, connection){
     24             connection.query("USE url", function(err){
     25                 if (err) {
     26                     console.log("USE Error: " + err.message);
     27                     return;
     28                  }
     29                  console.log('USE succeed');
     30             });
     31 
     32             connection.query("select * from shorturl where id=?", [id], function(err, result){
     33                 try{
     34                     connection.release();
     35                     callback(err, result);
     36                 }catch(errInfo){
     37                     console.log("select User_Sql Error: " + errInfo.message);
     38                     callback(errInfo, result);
     39                 }
     40             });
     41         });
     42     },
     43     getUrlInfoByLongAddress: function(longAddress, callback){
     44         pool.getConnection(function(err, connection){
     45             connection.query("USE url", function(err){
     46                 if (err) {
     47                     console.log("USE Error: " + err.message);
     48                     return;
     49                  }
     50                  console.log('USE succeed');
     51             });
     52             
     53             connection.query("select * from shorturl where longAddress=?", [longAddress], function(err, result){
     54                 try{
     55                     connection.release();
     56                     callback(err, result);
     57                 }catch(errInfo){
     58                     console.log("select User_Sql Error: " + errInfo.message);
     59                     callback(errInfo, result);
     60                 }
     61             });
     62         });
     63     },
     64     getMaxId: function(callback){
     65         pool.getConnection(function(err, connection){
     66             connection.query("USE url", function(err){
     67                 if (err) {
     68                     console.log("USE Error: " + err.message);
     69                     return;
     70                  }
     71                  console.log('USE succeed');
     72             });
     73 
     74             connection.query("select max(id) from shorturl", function(err, result){
     75                 try{
     76                     connection.release();
     77                     callback(err, result);
     78                 }catch(errInfo){
     79                     console.log("select User_Sql Error: " + errInfo.message);
     80                     callback(errInfo, result);
     81                 }
     82             });
     83         });
     84     },
     85     insertInfo: function(id, longAddress, callback){
     86         pool.getConnection(function(err, connection){
     87             connection.query("USE url", function(err){
     88                 if (err) {
     89                     console.log("USE Error: " + err.message);
     90                     return;
     91                  }
     92                  console.log('USE succeed');
     93             });
     94 
     95             connection.query("insert into shorturl(id,longAddress,shortAddress) values(?,?,?)", [id, longAddress, ipConfig + id], function(err, result){
     96                 try{
     97                     connection.release();
     98                     callback(err, result, {
     99                         'longAddress': longAddress,
    100                         'shortAddress': ipConfig + id
    101                     });
    102                 }catch(errInfo){
    103                     console.log("select User_Sql Error: " + errInfo.message);
    104                     callback(errInfo, result, {
    105                         'longAddress': longAddress,
    106                         'shortAddress': ipConfig + id
    107                     });
    108                 }
    109             });
    110         });
    111     },
    112     deleteAllData: function(callback){
    113         pool.getConnection(function(err, connection){
    114             connection.query("USE url", function(err){
    115                 if (err) {
    116                     console.log("USE Error: " + err.message);
    117                     return;
    118                  }
    119                  console.log('USE succeed');
    120             });
    121 
    122             connection.query("delete from shorturl where 1=1", function(err, result){
    123                 try{
    124                     connection.release();
    125                     callback(err, result);
    126                 }catch(errInfo){
    127                     console.log("select User_Sql Error: " + errInfo.message);
    128                     callback(errInfo, result);
    129                 }
    130             });
    131         });
    132     },
    133 };

        这里数据库操作很简洁,因为使用人数比较少,所以就没有做什么数据库回滚、死锁等操作,如果面向人群比较多,这些并发性还是要考虑的。这里就随意啦~~~

        到这里整个工具基本上完成了,但是要获取到需要转换的长地址总不能Ctrl+C、Ctrl+V吧。这样非人性化的工具,咱码农可拿不出手的。所以用Chrome插件工具就可以完美完成这个任务。

     4.3 Chrome插件开发

        这里插件的具体配置、开发我就不啰嗦了,官方文档分分钟搞定。我就贴一下配置文件和主要实现代码吧。

    目录结构:

    manifest.json:(Chrome插件配置文件)

     1 {
     2     "name": "Link",
     3     "version": "0.1",
     4     "manifest_version": 2,
     5     "description": "long to short",
     6     "icons": {
     7         "100": "image/icon.png"
     8     },
     9     "browser_action": {
    10         "default_icon": "image/icon.png",
    11         "default_popup": "popup.html"
    12     },
    13     "background": {
    14         "scripts": ["bjs/jquery-2.0.3.min.js", "bjs/background.js"]
    15     },
    16     "permissions": [
    17         "tabs"
    18     ],
    19     "content_scripts": [{
    20         "matches": ["<all_urls>"],
    21         "js": ["bjs/jquery-2.0.3.min.js"],
    22         "all_frames": true,
    23         "match_about_blank": true,
    24         "run_at": "document_start"
    25     }]
    26 }

    popup.js:

     1 $(function () {
     2     getCurrentTab(function(tabs){
     3         if(tabs){
     4             // 设置服务器的ip地址
     5             var joinIP = 'http://192.168.1.200:3000/insert?longAddress=';
     6             // ajax访问服务器
     7             $.getJSON(joinIP + tabs.url, function (data) {
     8                 $('.long-url').html(tabs.url);
     9                 $('.short-url').html(data.shortAddress);
    10                 $('.loading-box').hide();
    11                 console.log(data);
    12             });
    13         }else{
    14             console.log('no tab');
    15         }
    16     });
    17     // 获取到当前网站信息
    18     function getCurrentTab(callback) {
    19         chrome.tabs.query({
    20             active: true,
    21             currentWindow: true
    22         }, function (tabs) {
    23             if (callback) callback(tabs.length ? tabs[0] : null);
    24         });
    25     }
    26 })

    五、启动方式

    1. 添加Chrome插件到Chrome浏览器
    2. 在命令行定位到项目工程文件
    3. 运行node app命令开启本地服务
    4. 找一个地址,点击那个插件生成短地址测试
    5. 完成

    六、结果截图

        亲测有效~~~

    七、迁移到Windows服务器

    1. 系统环境:win7系统(32位)------ 一脸懵逼的吐槽公司这台闲置的电脑,这配置~~~
    2. nodejs (v8.11.2)  后台语言 ------ 直接下载msi文件点击安装
    3. mysql (v8.....忘记了)  数据库 ------ 下载msi文件跟着步骤安装
    4. MySQLWorkbench (v6.3.10)  数据库可视化工具
    5. 再次吐槽一下这台电脑,.Net Framework版本低的不要不要的,mySql软件需要的环境都要升级,折腾一下午终于搞定,至于配置方式可以百度解决
    6. Windows有个好处就是可以设置开机运行脚本,这样每次启动就可以自动开启服务了,不需要每次手动去开。
    7. 新建一个txt文件,里面输入node C:urlapp(因为我把工程文件就放在了c盘下面),如果路径不同可以自行调整
    8. 保存txt文件,然后把文件后缀改成bat,然后添加到开机启动项里面,这里推荐一篇关于设置启动项的文章:http://blog.51cto.com/10676568/1974842
    9. 重启电脑测试~~~
  • 相关阅读:
    Python 内存泄露 内存回收机制
    decimal 格式化
    iis 6 配置PHP
    按照 in (....) 里面的顺序进行排序
    设计模式之 访问者模式
    与数据库的列信息有关
    win32 IFolderView2::GetCurrentFolderFlags的使用
    MySQL防止重复插入相同记录 insert if not exists
    c++扩展Python(未验证)
    c++ 获取桌面图标的坐标与名称
  • 原文地址:https://www.cnblogs.com/lawliet-qiu/p/9123185.html
Copyright © 2020-2023  润新知