郵便番号APIを利用して、郵便番号から住所を検索するアプリを作成してみよう。
作るもの
郵便番号を入れるフォームがあるので、調べたい郵便番号を入れて送信ボタンをおす。
結果が表示される
一つの郵便番号に複数の住所が割り振られている場合がある。
989-2351
をいれると20件の住所が表示される。
作成
WebAPI
まずは大前提となるWebAPIを確認する。
zipcloudさんが提供してくれている郵便番号APIを利用させていただく。
これはリクエストパラメーターに調べたい郵便番号を含めると、その結果をJSONデータでレスポンスしてくれるサービスだ。以下のURLを入力してサンプルレスポンスを確認してもらいたい。
https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
今回はこのAPIを使ってアプリを作成していく。
作成
- エクリプス新規動的Webプロジェクトよりzipappを作成
- 新規クラスからAddressクラスを以下のように作成する。パッケージはmodelとする。
package model;
import java.io.Serializable;
public class Address implements Serializable{
private String zipcode;
private String prefcode;
private String address1;
private String address2;
private String address3;
private String kana1;
private String kana2;
private String kana3;
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getPrefcode() {
return prefcode;
}
public void setPrefcode(String prefcode) {
this.prefcode = prefcode;
}
public String getAddress1() {
return address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getAddress3() {
return address3;
}
public void setAddress3(String address3) {
this.address3 = address3;
}
public String getKana1() {
return kana1;
}
public void setKana1(String kana1) {
this.kana1 = kana1;
}
public String getKana2() {
return kana2;
}
public void setKana2(String kana2) {
this.kana2 = kana2;
}
public String getKana3() {
return kana3;
}
public void setKana3(String kana3) {
this.kana3 = kana3;
}
}
ポイント
返却されるjsonデータのキーの名前と合わせてフィールド名を設定しておくと後で楽にパースすることができる。スコープに詰めるのでjavabeansの書式を守ること。
- https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.2
- 上記のURLにアクセスしてgson-2.8.2.jarをダウンロード
ダウンロードしたgson-2.8.2.jarファイルを以下のlibフォルダに配置する。
webapp/WEB-INF/lib/
- modelパッケージの中に以下のように一般クラスとしてAddressParser.javaを作成する。
package model;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
public class AddressParser {
public List<Address> getList(String urlString){
List<Address> list = new ArrayList<>();
JsonReader reader=null;
HttpURLConnection con = null;
try {
URL url = new URL(urlString);
con=(HttpURLConnection)url.openConnection();
con.setRequestMethod("GET");
InputStream is = con.getInputStream();
InputStreamReader isr= new InputStreamReader(is,"UTF-8");
reader = new JsonReader(isr);
Gson gson=new Gson();
JsonObject root=gson.fromJson(reader,JsonObject.class);
//resultsの値のnullチェック
if(!root.get("results").isJsonNull()) {
JsonArray results=root.get("results").getAsJsonArray();
//ArrayListにパースするときにはTypeTokenを使う必要がある
list=gson.fromJson(results, new TypeToken<ArrayList<Address>>() {}.getType());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(con != null) {
con.disconnect();
}
}
return list;
}
}
ポイント解説
AddressクラスをJSONデータのキーの名前を一致して作成したので,JsonArrayオブジェクトからループを回すことなくArrayListを作成することができる。
list=gson.fromJson(results, new TypeToken<ArrayList<Address>>() {}.getType());
- 続いて新規サーブレットからMain.javaを作成する。このときパッケージはcontrollerとすること。doGet内に以下を記述する。(doPostは空にしておく)
package controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/Main")
public class Main extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg", "郵便番号を入力してください");
request.getRequestDispatcher("/WEB-INF/view/main.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
- WEB-INF内にviewフォルダを作成し、その中にmain.jspを以下のように作成する。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String msg=(String)request.getAttribute("msg");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>住所検索</title>
</head>
<body>
<div id="container">
<p><%=msg %></p>
<form action="Main" method="post">
<input type="text" name="zip" placeholder="000-0000" required>
<button type="submit">送信する</button>
</form>
</div><!-- container -->
</body>
</html>
- controller.Main.javaをサーバーで実行してみよう。以下のようにフォームが表示されれば成功だ。
- 郵便番号を入れて、送信ボタンを押したら作動するdoPostをcontroller.Main.javaを以下のように追記する。
package controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import model.Address;
import model.AddressParser;
@WebServlet("/Main")
public class Main extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg", "郵便番号を入力してください");
request.getRequestDispatcher("/WEB-INF/view/main.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String zip = request.getParameter("zip");
String msg=null;
if(zip == null || !zip.matches("[0-9]{3}-?[0-9]{4}")) {
msg="不正な郵便番号です";
}
if(msg == null) {
msg="通信結果";
String zipcode = zip.replace("-","");
String url =
String.format("https://zipcloud.ibsnet.co.jp/api/search?zipcode=%s",zipcode);
AddressParser parser = new AddressParser();
List<Address> list = parser.getList(url);
if(list.size() == 0) {
msg="実在しない郵便番号です";
}else {
request.setAttribute("list", list);
}
}
request.setAttribute("zip", zip);
request.setAttribute("msg",msg);
request.getRequestDispatcher("/WEB-INF/view/main.jsp").forward(request, response);
}
}
- WEB-INF/view/main.jspを以下のように追記
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="model.*,java.util.*"%>
<%
String zip = (String)request.getAttribute("zip");
zip = zip == null ? "":zip;
String msg=(String)request.getAttribute("msg");
List<Address> list = (List<Address>)request.getAttribute("list");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>住所検索</title>
</head>
<body>
<div id="container">
<p><%=msg %></p>
<form action="Main" method="post">
<input type="text" name="zip" placeholder="000-0000" value="<%=zip %>" required>
<button type="submit">送信する</button>
</form>
<% if(list != null && list.size() > 0){ %>
<div id="result">
<% for(Address a:list){ %>
<table>
<tr><td>郵便番号</td><td><%=a.getZipcode() %></td></tr>
<tr><td>都道府県コード</td><td><%=a.getPrefcode() %></td></tr>
<tr><td>都道府県名</td><td><%=a.getAddress1() %></td></tr>
<tr><td>市区町村名</td><td><%=a.getAddress2() %></td></tr>
<tr><td>町域名</td><td><%=a.getAddress3() %></td></tr>
<tr><td>都道府県名カナ</td><td><%=a.getKana1() %></td></tr>
<tr><td>市区町村名カナ</td><td><%=a.getKana2() %></td></tr>
<tr><td>町域名カナ</td><td><%=a.getKana3() %></td></tr>
</table>
<%} %>
</div><!-- result -->
<%} %>
</div><!-- container -->
</body>
</html>
- 入力が終わったら、controller.Main.javaをサーバーで起動して自分の郵便番号を入力してみよう。正しく表示されればうまくいっている。
スタイルの追加
- スタイルをあてよう。WEB-INF/view/main.jspに以下の1行を追記する。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="model.*,java.util.*" %>
<%
String msg=(String)request.getAttribute("msg");
String zip = (String)request.getAttribute("zip");
zip = zip == null ? "":zip;
List<Address> list = (List<Address>)request.getAttribute("list");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>住所検索</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="container">
<p><%=msg %></p>
<form action="Main" method="post">
<input type="text" name="zip" placeholder="000-0000" value="<%=zip %>" required>
<button type="submit">送信する</button>
</form>
<% if(list != null && list.size() > 0){ %>
<div id="result">
<% for(Address a:list){ %>
<table>
<tr><td>郵便番号</td><td><%=a.getZipcode() %></td></tr>
<tr><td>都道府県コード</td><td><%=a.getPrefcode() %></td></tr>
<tr><td>都道府県名</td><td><%=a.getAddress1() %></td></tr>
<tr><td>市区町村名</td><td><%=a.getAddress2() %></td></tr>
<tr><td>町域名</td><td><%=a.getAddress3() %></td></tr>
<tr><td>都道府県名カナ</td><td><%=a.getKana1() %></td></tr>
<tr><td>市区町村名カナ</td><td><%=a.getKana2() %></td></tr>
<tr><td>町域名カナ</td><td><%=a.getKana3() %></td></tr>
</table>
<%} %>
</div><!-- result -->
<%} %>
</div><!-- container -->
</body>
</html>
- cssファイルを作成していこう。webappsの直下にcssフォルダを作成し,main.cssファイルを作成する。
#container {
width: 96%;
margin: 20px auto;
}
#result {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
gap: 20px;
}
table {
border-collapse: collapse;
margin-top: 20px;
}
td {
padding: 5px 10px;
border: 1px solid #333;
}
- 実行してみよう。結果のテーブルに罫線があたっていれば成功だ。
989-2351
などの複数住所が存在している郵便番号もいれてみよう。
仕上げ
カスタムタグを使ってjspからプログラム要素を排除していこう。以下のリンクを参考に2つのjarファイルをWEB-INF/libの中にコピペで貼り付ける
JSTL (1.2) のインストール手順
JSTLをインストールするには、2つの異なるJARをダウンロードし、クラスパスにコピーする必要があります。 step1JSTL API(インタフェース)のダウンロード Maven Repository
- main.jspを以下のように変更する。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="model.*,java.util.*" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- スクリプトレット削除 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>住所検索</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="container">
<p>${msg}</p>
<form action="Main" method="post">
<input type="text" name="zip" placeholder="000-0000" value="${zip}" required>
<button type="submit">送信する</button>
</form>
<c:if test="${not empty list}">
<div id="result">
<c:forEach var="add" items="${list}">
<table>
<tr><td>郵便番号</td><td>${add.zipcode}</td></tr>
<tr><td>都道府県コード</td><td>${add.prefcode}</td></tr>
<tr><td>都道府県名</td><td>${add.address1}</td></tr>
<tr><td>市区町村名</td><td>${add.address2}</td></tr>
<tr><td>町域名</td><td>${add.address3}</td></tr>
<tr><td>都道府県名カナ</td><td>${add.kana1}</td></tr>
<tr><td>市区町村名カナ</td><td>${add.kana2}</td></tr>
<tr><td>町域名カナ</td><td>${add.kana3}</td></tr>
</table>
</c:forEach>
</div><!-- result -->
</c:if>
</div><!-- container -->
</body>
</html>
コメント