10
1

More than 1 year has passed since last update.

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正しいかどうかの軽いセキュリティチェックを設けます。
image.png

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
image.png
PUT:更新、url http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
戻り値なし、httpステータスは204
image.png

GET:取得
http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
戻り値は取得したデータ、httpステータスは200
image.png

DELETE:削除、http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
戻り値なし、httpステータスは204
image.png

エラー時、
例えば挿入キー重複、更新・削除データ存在なし、などの場合、
戻り値はエラー情報、httpステータスは500
image.png
image.png

テストツールの接続

image.png

ブラウザーからのテスト

ブラウザーからテストする場合、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送信です。
image.png
2回目はget送信です。
image.png

corsに関わる説明のリンクです。
https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34

環境準備

DBも利用するから以下の記事を参考してください。
https://qiita.com/changkejun/items/b273b3ae64c76e5b016a

今回のサンプルは以下のリンクからダウンロードできます。

10
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1