Rest APIを言われると大抵どう接続するかどう利用するかの話です。今回サービスを作ってみましょう。
Restイベント
efwのrestイベントはwebイベントと同じくtomcat/WEB-INF/efw/eventフォルダに格納します。相違点は書き方が違うことです。
https://github.com/efwGrp/efw4.X/blob/master/help/api_restevent.md
テストのイメージ
jspからサーバに送信します。jsイベントからRestAPIのイベントに転送して、RestAPIをDB処理して結果を戻します。token正しいかどうかの軽いセキュリティチェックを設けます。
JSP
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="efw" uri="efw" %>
<!DOCTYPE HTML>
<HTML>
<HEAD>
<title>Rest API Server and Client Test</title>
<efw:Client lang="jp"/>
</HEAD>
<BODY>
<button onclick="Efw('helloRestAPI_submit',{mode:'0'})">初期化(テーブル作成)</button><br><br>
ID:<input type="text" id="customerId">
Name:<input type="text" id="customerName"><br>
token:<input type="text" id="token" value="1234567890">※httpヘッダからセキュリティ情報送信のテスト<br>
<button onclick="Efw('helloRestAPI_submit',{mode:'1'})">顧客追加</button>
<button onclick="Efw('helloRestAPI_submit',{mode:'2'})">顧客変更</button>
<button onclick="Efw('helloRestAPI_submit',{mode:'3'})">顧客削除</button>
<button onclick="Efw('helloRestAPI_submit',{mode:'4'})">顧客取得</button><br><br>
<textarea style="width:800px;height:300px;">
</textarea><br><br>
<button onclick="Efw('helloRestAPI_submit',{mode:'9'})">終了(テーブル削除)</button><br><br>
</BODY>
</HTML>
jsイベント
var helloRestAPI_submit={};
helloRestAPI_submit.paramsFormat={
mode:null,
"#customerId":null,
"#customerName":null,
"#token":null,
};
helloRestAPI_submit.fire=function(params){
if (params.mode=="0"){
db.change("helloRestAPI","createTbl",{});
return new Result().alert("テーブルを作成しました。");
}else if (params.mode=="9"){
db.change("helloRestAPI","dropTbl",{});
return new Result().alert("テーブルを削除しました。");
}
var url="http://localhost:8080/helloworld/efwRestAPI/customer";
try{
var ret=null;
if (params.mode=="1"){//新規追加の場合
ret=rest.post(url,
{id:params["#customerId"],nm:params["#customerName"]},
{token:params["#token"]});
}else if (params.mode=="2"){//更新の場合
ret=rest.put(url+"/"+params["#customerId"],
{nm:params["#customerName"]},
{token:params["#token"]});
}else if (params.mode=="3"){//削除の場合
ret=rest.delete(url+"/"+params["#customerId"],{token:params["#token"]});
}else if (params.mode=="4"){//取得の場合
ret=rest.get(url+"/"+params["#customerId"],{token:params["#token"]});
}
return new Result()
.runat("body")
.withdata({
"textarea":rest.getStatus()+"\n"+JSON.stringify(ret),
});
}catch(e){//失敗の場合
return new Result()
.runat("body")
.withdata({
"textarea":rest.getStatus()+"\n"+e.getMessage(),
});
}
}
restAPIイベント
var customer={};
customer.POST=function(keys,params){//新規作成
var token=Packages.efw.framework.getRequest().getHeader("token");
if("1234567890"!=token){throw new Error("セキュリティエラー");}
db.change("helloRestAPI","insertRow",{"id":params.id,"name":params.nm});
return {url:"efwRestAPI/customer/"+params.id}
};
customer.PUT=function(keys,params){//更新
var token=Packages.efw.framework.getRequest().getHeader("token");
if("1234567890"!=token){throw new Error("セキュリティエラー");}
var rt=db.change("helloRestAPI","updateRow",{"id":keys[0],"name":params.nm});
if (rt==0) throw new Error("更新対象のデータは存在しません。");
return null;
};
customer.DELETE=function(keys){//削除
var token=Packages.efw.framework.getRequest().getHeader("token");
if("1234567890"!=token){throw new Error("セキュリティエラー");}
var rt=db.change("helloRestAPI","deleteRow",{"id":keys[0]});
if (rt==0) throw new Error("削除対象のデータは存在しません。");
return null;
};
customer.GET=function(keys){//取得
var token=Packages.efw.framework.getRequest().getHeader("token");
if("1234567890"!=token){throw new Error("セキュリティエラー");}
return db.select("helloRestAPI","selectRow",{"id":keys[0]}).getSingle();
};
sql
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqls>
<sqls>
<sql id="createTbl">
CREATE TABLE tbl_customer(
id character varying(10) NOT NULL,
name character varying(20),
CONSTRAINT tbl_customer_pkey PRIMARY KEY (id)
)
</sql>
<sql id="dropTbl">
DROP TABLE tbl_customer;
</sql>
<sql id="selectRow">
SELECT
id,
name
FROM tbl_customer
WHERE
id=:id;
</sql>
<sql id="insertRow">
INSERT INTO tbl_customer(
id,
name
)VALUES (
:id,
:name
);
</sql>
<sql id="updateRow">
UPDATE tbl_customer
SET
name=:name
WHERE id=:id;
</sql>
<sql id="deleteRow">
DELETE FROM tbl_customer
WHERE id=:id;
</sql>
</sqls>
説明
POST:挿入、url http://localhost:8080/helloworld/efwRestAPI/customer
戻り値は挿入データのURL、httpステータスは200
PUT:更新、url http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
戻り値なし、httpステータスは204
GET:取得
http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
戻り値は取得したデータ、httpステータスは200
DELETE:削除、http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
戻り値なし、httpステータスは204
エラー時、
例えば挿入キー重複、更新・削除データ存在なし、などの場合、
戻り値はエラー情報、httpステータスは500
テストツールの接続
ブラウザーからのテスト
ブラウザーからテストする場合、cors対応の実装がいけるかどうかの目的です。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="efw" uri="efw" %>
<!DOCTYPE HTML>
<HTML>
<HEAD>
<title>Rest API Server and Client Test</title>
<efw:Client lang="jp"/>
</HEAD>
<BODY>
ID:<input type="text" id="customerId">
Name:<input type="text" id="customerName"><br>
token:<input type="text" id="token" value="1234567890">※httpヘッダからセキュリティ情報送信のテスト<br>
<script>
function browserTest(samedomain){
var domain=samedomain?"localhost":"127.0.0.1";
var url="http://"+domain+":8080/helloworld/efwRestAPI/customer/"+$("#customerId").val();
$.ajax({
url:url,
xhrFields: { withCredentials: true },
headers:{ token:$("#token").val()},
type: "GET",
cache: false,
async: true,
dataType: "json",// send or get data by json type
contentType: "application/json;charset=UTF-8",
success:function(result){
window.alert(JSON.stringify(result));
},
error:function(errorResponse){
window.alert(JSON.stringify(errorResponse));
}
})
}
</script>
<button onclick="browserTest(true)">ブラウザーテスト</button>
<button onclick="browserTest(false)">別ドメインテスト</button>
</BODY>
</HTML>
2つのボタンは、それぞれlocalhostと127.0.0.1から送信します。そして、refererと比較すると必ず1本はcorsと判断されます。
1回目はoptions送信です。
2回目はget送信です。
corsに関わる説明のリンクです。
https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34
環境準備
DBも利用するから以下の記事を参考してください。
https://qiita.com/changkejun/items/b273b3ae64c76e5b016a
今回のサンプルは以下のリンクからダウンロードできます。