gson-2.8.9.jar
json-20220320.jar
1) jsp 페이지에서 주소를 입력받음
2) 입력받은 주소를 구글맵 api에 전달해 위도, 경도를 JSON으로 받아옴
구글 api 연결하는 방법
URL 객체 만들어서 openConnection()
메서드 호출 -> 받아온 URLConnection의 getInputStream()
메서드 호출 -> InputStream
반환
InputStream 읽기 위해 BufferedReader
객체 생성
(생성자에 new InputStreamReader(InputStream객체, 인코딩타입) 넣어주기)
BufferedReader로 받아온 데이터 읽어오는 방법
읽을 내용(JSON 형태의 문자열) 담을 String
변수(str),
읽은 내용을 누적할 StringBuilder
변수(strBuilder) 만들기
while((str = 버퍼.readLine()) != null) {
// 데이터셋 다음 줄로 이동후 그 값을 str에 담고, 해당 값이 존재하면
strBuilder.append(str);
// StringBuilder에 해당 값을 이어붙임
}
StringBuilder
을 JSON 객체
로 만들어 값 가져오기JSONArray
객체로 받아오기JSONArray arr = jsonObj.getJSONArray("results");
해당 배열의 첫번째 값(JSON객체) 받아오고, 받아온 JSON 객체 안에 든 JSON객체를 계속 받아와서 최종적으로 "lat", "lng" 키의 값을 Double 타입으로 받아옴
3) 받아온 JSON을 자바 DTO에 담아 바인딩 후 출력 페이지로 포워드
4) 출력 페이지에서 DTO에 담긴 위도, 경도 값을 가져와 카카오 맵 api를 사용해서 자바스크립트로 코드로 지도 화면 출력
1) 주소 입력 페이지 : form
태그의 action
속성으로 서블릿 매핑
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주소 입력</title>
</head>
<body>
<form action="map">
주소 : <input type="text" name="addr" value="창원시 마산회원구 양덕북12길 113">
<input type="submit" value="입력">
</form>
</body>
</html>
2) 컨트롤러 서블릿 : jsp에서 요청받은 주소 처리
주소를 DAO에 파라미터로 전달해 메서드 호출하고 위도, 경도, 위치값 담은 DTO 받기
받은 DTO를 request에 바인딩하고 출력 페이지로 포워드
package controller;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
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 dao.MapDAO;
import dto.MapDTO;
@WebServlet("/map")
public class MapController extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 주소 정보를 한글로 받기 때문에 한글 깨짐 방지
request.setCharacterEncoding("utf-8");
// 입력한 주소를 변수로 받기
String addr = request.getParameter("addr");
// dao 사용을 위해 객체 생성
MapDAO dao = new MapDAO();
// dao의 메서드 호출해 MapDTO 받아오기
MapDTO dto = dao.getByGeoDataByAddress(addr);
dto.setName(addr);
// request에 바인딩하고 포워드
request.setAttribute("mapInfo", dto);
RequestDispatcher dispatch = request.getRequestDispatcher("view.jsp");
dispatch.forward(request, response);
}
}
3) DAO 클래스 : 주소를 가지고 구글맵 api를 사용해 JSON 형태의 문자열로 돌려받고,
해당 문자열을 JSON객체/JSON배열 객체 등으로 변환해 필요한 값을 가져옴
값(위도, 경도)을 DTO에 set하고 해당 DTO 리턴
package dao;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import org.json.JSONArray;
import org.json.JSONObject;
import dto.MapDTO;
public class MapDAO {
public MapDTO getByGeoDataByAddress(String addr) throws IOException {
// return할 데이터 준비
MapDTO dto = new MapDTO();
// API key(키값)
String API_KEY = "AIzaSyDXMN6Lg3WVVzi20NcbAEEBJu6Xw9Ai3Cs";
// 입력한 주소(address), API key(key)를 파라미터로 가지는 url 준비 (google 서버에 전달하기 위해)
// 주소는 한글이므로 url에 붙일 때 깨지지 않도록 URLEncoder.encode() 사용
String surl = "https://maps.googleapis.com/maps/api/geocode/json?address=" + URLEncoder.encode(addr, "UTF-8") + "&key="+API_KEY;
// html에서 a태그, form 태그 쓰는 것처럼 자바에서 다른 서버에 action 요청하는 방법 : URL 객체 사용하기
URL url = new URL(surl);
// URL.openConnection() : google에 쿼리 날리기(action 실행)
// URLConnection.getInputStream() : java가 아닌 외부에서 데이터 받아오기(InputStream)
InputStream is = url.openConnection().getInputStream();
// 받아온 데이터 버퍼(보조 스트림)에 담기
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "utf-8"));
// StringBuilder : String 객체는 내용이 변할 때마다 객체가 새로 생성되는데,
// StringBuilder는 한 객체에 내용을 계속 누적시키므로 내용이 계속 변해도 메모리를 절약할 수 있음
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
// 받아온 데이터 읽어와서 값 strBuilder에 누적하기
while ((inputStr = streamReader.readLine()) != null) {
responseStrBuilder.append(inputStr);
}
System.out.println("StrBuilder : " + responseStrBuilder);
System.out.println("======================================");
// 받아온 문자열은 json 형식으로 되어 있음, 사용하기 위해 json 객체로 변환하기
JSONObject jsonObj = new JSONObject(responseStrBuilder.toString());
System.out.println("jsonObj : " + jsonObj);
System.out.println("======================================");
// 해당 json 객체는 results라는 키에 모든 json 객체를 값(배열)으로 가지기 때문에,
// results 키의 값인 배열을 JSONArray로 만들어 각 배열 요소에 접근함
JSONArray results = jsonObj.getJSONArray("results");
if(results.length() > 0) {
JSONObject obj;
// 배열의 첫번째 값 가져오기 : json 객체
obj = results.getJSONObject(0);
// 그 객체 안의 geometry 키의 값(json객체) -> 안의 location 키의 값(json객체) -> 안의 lat 키의 값(double) 가져오기 : 위도, 경도 가져오기
Double lat = obj.getJSONObject("geometry").getJSONObject("location").getDouble("lat");
Double lng = obj.getJSONObject("geometry").getJSONObject("location").getDouble("lng");
System.out.println("lat : " + lat + ", lng : " + lng);
System.out.println("======================================");
// 받아온 위치 값을 MapDTO에 set하고 리턴
dto.setX(lat);
dto.setY(lng);
return dto;
}
// if문 실행되지 않았을때 null 리턴
return null;
}
}
4) DTO : 위도(x좌표), 경도(y좌표), 주소(name)을 멤버로 가지는 DTO
package dto;
public class MapDTO {
private String name;
private double x;
private double y;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
5) 지도 출력 페이지 : 카카오 맵 api 사용, js 코드로 지도 화면 출력
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="dto.MapDTO" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주소 출력</title>
</head>
<body>
<%
// 바인딩한 MapDTO 가져오기
MapDTO dto = (MapDTO) request.getAttribute("mapInfo");
%>
<!-- 카카오 지도 web api에서 소스 가져오기 -->
<div id="map" style="width:500px;height:400px;"></div>
<p><%= dto.getName() %></p>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=6d096e2d7e3f4c07523b417978a66ad0"></script>
<script>
var container = document.getElementById('map');
var options = {
center: new kakao.maps.LatLng(<%= dto.getX() %>, <%= dto.getY() %>),
level: 3
};
var map = new kakao.maps.Map(container, options);
</script>
</body>
</html>
💻 실행 결과