* Express(Nodejs)でWebAPI作成 [#hefe13a8]
#setlinebreak(on);

#contents
-- 関連
--- [[Spring BootでWebAPI作成]]
--- [[EC2上のExpressのパフォーマンス検証]]

** インストールからアプリケーション作成まで [#v3bc94af]
#html(<div style="padding-left:10px;">)

*** expressインストール(グローバル) [#s8e7d590]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
npm install -g express
}}
#html(</div>)

*** expressコマンドを使用できるようにする(グローバル) [#jba5058a]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
npm install -g express-generator
}}
#html(</div>)

*** 環境変数の設定(グローバルインストールした場合) [#zd6bb844]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
export NODE_PATH=/usr/local/lib/node_modules
}}
#html(</div>)

*** アプリケーション作成&必要なモジュールのインストール [#z1034d29]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
express sample
cd sample && npm install
}}
#html(</div>)

#html(</div>)

** 起動確認 [#t1c4f213]
#html(<div style="padding-left:10px;">)

*** 起動確認用の sample.js 作成 [#qdba62bc]
#html(<div style="padding-left:10px;">)
sample.js
#code(mycode2){{
var express = require('express');
var app = express();
app.get('/', function(req, res){
    res.send("Hello World!!\n");
});
app.listen(3000);
}}
#html(</div>)

*** サンプル起動 [#d8740cd5]
#html(<div style="padding-left:10px;">)
#code(myterm2){{
node sample.js
}}
#html(</div>)

*** サンプル確認 [#o8a33e21]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
curl -v http://localhost:3000
}}
#html(</div>)


#html(</div>)

ここからは、実際にDBからデータを取得するAPIを作成する。

** テスト用DBの準備(MySQL) [#c6efc2a0]
#html(<div style="padding-left:10px;">)
#include(テスト用DBの準備(MySQL),notitle);

*** MySQLモジュールのインストール [#jf8ebb54]
#html(<div style="padding-left:10px;">)
package.json を編集
#code(mycode2 linenums:8){{
  "dependencies": {
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.15.5",
    "jade": "~1.11.0",
    "morgan": "~1.9.0",
    "mysql": "*",   // 追加
}}

インストール
#code(myterm2){{
npm install
}}

#html(</div>)

*** app.js を編集 [#ac8077d7]
#html(<div style="padding-left:10px;">)
app.js
#code(mycode2 linenums){{
var express = require('express');
.
.
// ## ここから追加 ##
var mysql   = require("mysql");

var pool = mysql.createPool({
  connectionLimit : 10, 
  host: process.env.NODE_DB_HOST || 'localhost',
  port: process.env.NODE_DB_PORT || '3306',
  user: process.env.NODE_DB_USER || 'example_user',
  password: process.env.NODE_DB_PASS || 'example_pass',
  database: process.env.NODE_DB_NAME || 'example_db'
});

pool.on('connection', function (connection) {
  console.log("新しいコネクションプールが作成されました");
});
pool.on('acquire', function (connection) {
  console.log("コネクションプールから接続が獲得されました");
});
pool.on('release', function () {
  console.log("コネクションプールが戻されました");
});
pool.on('enqueue', function () {
  console.log("エンキュー");
});

global.pool = pool;
// ## ここまで ##

var index = require('./routes/index');
var users = require('./routes/users');
var books = require('./routes/books');  // 追加
.
.
app.use('/', index);
app.use('/users', users);
app.use('/book', books);                // 追加
}}
#html(</div>)

*** routes/books.js を作成 [#ked0fb03]
#html(<div style="padding-left:10px;">)

#code(mycode2 linenums){{
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  var data = [];
  pool.query('select * from books', function(err, rows, fields) {
    if (err) throw err;
    res.json(rows);
  });
});

router.get('/:id', function(req, res, next) {
  const id = req.params.id;
  pool.query('select * from books where id = ?', id, function(err, rows, fields) {
    res.json(rows);
  }); 
});

module.exports = router;
}}
#html(</div>)

*** トランザクションを張る場合 [#w1cdd426]
#html(<div style="padding-left:10px;">)

トランザクションを張る場合は以下のように明示的に beginTransaction する必要がある。
※常にトランザクションを張る場合は、pool あたりをラップすれば、上記のコードと殆ど変わらないコード量にはできそう。

#code(mycode2){{
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  pool.getConnection(function(err, connection) {
    if (err) throw err; 
      connection.beginTransaction(function(err) {
        connection.query('insert into xxxxx ... ', function(err, rows, fields) {
          if (err) {
            return connection.rollback(function() {
              connection.release();
              throw err;
            });
          }
          connection.commit(function(err) {
            connection.release();
          });
          res.json({"result":"true"});
        });
      }); 
  }); 
});
}}
#html(</div>)

*** 起動 [#t9d61408]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
DEBUG=sample:* npm start
}}
#html(</div>)


#html(</div>)

** 開発メモ [#pceae8e0]
#html(<div style="padding-left:10px;">)

*** 変更したときにオートリロードする [#u931613a]
#html(<div style="padding-left:10px;">)
#code(myterm2 nolinenums){{
npm install -g node-dev
cd myapp
node-dev bin/www
}}
#html(</div>)


#html(</div>)


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS