Spring

[Spring] 데이터 소스를 통한 프로젝트 만들기

Journey Jeong 2023. 5. 4. 13:10

 

1. 인덱스로 메뉴 만들기

 

 

- layout > header.html 에 메뉴 추가(링크 생성하기) 

<!DOCTYPE html>
<html>
<header>
	<h1>헤더영역</h1>
	<div class="wrap view-size">
		<a href="/">HOME</a>
		<a href="/board">게시글</a>
		<a href="/my-board">마이게시글</a>
		<a href="/subway">지하철 엘레베이터</a>
	</div>
</header>
</html>

- 해당 위치에 html 생성하기  (myboard > list.html) 

<!DOCTYPE html>
<html xmlns:th="//www.thymeleaf.org"
	th:replace="layout/layout1 :: layout(~{::head},~{this::main})" >
<head>
	
</head>	
<main>
	<h1>메인영역</h1>
	<div class="wrap view-size">
		<section>
			<h1>게시글내용</h1>
			<div class="wrap">
				<p class="tit">지하철 엘레베이터 정보</p>
			</div>
		</section>
	</div>
</main>

 


2. 컨트롤러 만들기

 

 

- @Controller 어노테이션 적용 

- @Getmapping 할 메서드 만들기 : 

          @GetMapping(어디 주소로 들어오면?)

          public String 메서드명(){ return "여기로 이동시켜줘"}

ㅡmodel 메서드 넣기 (추후 인터페이스와 클래스에 값에도 model 넣어주기) 

 

package com.green.nowon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.green.nowon.service.SubwayElevatorService;

import lombok.RequiredArgsConstructor;

//@RequiredArgsConstructor
@Controller
public class SubwayController {

	private final SubwayElevatorService service; //Constructor DI 
	
	
	public SubwayController(SubwayElevatorService service) { 
		this.service = service; 
	}
	 
	
	@GetMapping("/subway")
	public String subway(Model model) throws Exception {
		service.getElevatorInfo(model);
		return "subway/list";
		
	}
	
}

 

 

3. 서비스 인터페이스 만들기 

 

 

-  컨트롤러에 서비스 할 인터페이스 생성하기  :

         private final 인터페이스명 service; 

 

-  자동 생성하기 

package com.green.nowon.service;

public interface SubwayElevatorService {

}

인터페이스 상속받은 클래스 생성하기:  @Service 적용해주기 

package com.green.nowon.service.impl;

import org.springframework.stereotype.Service;

import com.green.nowon.service.SubwayElevatorService;

@Service
public class SubwayElevatorServiceProcess implements SubwayElevatorService{

}

 

 

 


4. 생성자 초기화 해주기 

 

 

방법 1>  클래스에 @RequiredArgsConstructor 적용하기 

package com.green.nowon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import com.green.nowon.service.SubwayElevatorService;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class SubwayController {

	private final SubwayElevatorService service; //Constructor DI 
	
	
	@GetMapping("/subway")
	public String subway() {
		return "subway/list";
	}
	
}

방법 2>  public 컨트롤러이름(서비스명 변수){ this.변수 = 변수};

package com.green.nowon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import com.green.nowon.service.SubwayElevatorService;

import lombok.RequiredArgsConstructor;

@Controller
public class SubwayController {

	private final SubwayElevatorService service; //Constructor DI 
	
	public SubwayController(SubwayElevatorService service) {
		this.service = service;
	}
	
	@GetMapping("/subway")
	public String subway() {
		return "subway/list";
	}
	
}

 

 

- subway 메서드에 가지고올 정보의 메서드 넣기 예> service.getElevatorInfo();

package com.green.nowon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import com.green.nowon.service.SubwayElevatorService;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class SubwayController {

	private final SubwayElevatorService service; //Constructor DI 
	
	/*
	 * public SubwayController(SubwayElevatorService service) { this.service =
	 * service; }
	 */
	
	@GetMapping("/subway")
	public String subway() {
		service.getElevatorInfo();
		return "subway/list";
		
	}
	
}

 

 

 

- 자동으로 메서드와 오버라이드 생성 

package com.green.nowon.service;

public interface SubwayElevatorService {

	void getElevatorInfo();

}
package com.green.nowon.service.impl;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.green.nowon.service.SubwayElevatorService;

@Service
public class SubwayElevatorServiceProcess implements SubwayElevatorService{


	@Override
	public void getElevatorInfo() {
		// TODO Auto-generated method stub
		
	}

}

 

 

 

 

5. 키 정보 가지고 오기

 

https://data.seoul.go.kr/dataList/OA-15514/S/1/datasetView.do

 

열린데이터광장 메인

데이터분류,데이터검색,데이터활용

data.seoul.go.kr

 - 서울시 장애인 편의시설 정보에서 open API 에 인증키 신청 후 키발급

        -> 불러올 데이터의 키값의 변수 선언 private String 변수명 

        -> @Value("${seoul.key}") 후 git config server 에 업데이트 또는 Value(키값)

@Value("${seoul.key}")
	private String seoulKey;

 

 

 

- api 이용안내 클릭 후 복사 붙여넣기  - 예외처리 및  내 data 형식과 맞게 수정해주기 

 

* 컨트롤러 서비스까지 Exception 으로 예외처리 해주기 

 

- 가이드를 따라 내 프로젝트에 맞게 수정해주기

    -> sample 이나 데이터 타입 등 

package com.green.nowon.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.green.nowon.service.SubwayElevatorService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class SubwayElevatorServiceProcess implements SubwayElevatorService{

	@Value("${seoul.key}")
	private String seoulKey;
	
	@Override
	public void getElevatorInfo() throws Exception {
		
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode(seoulKey,"UTF-8") );
		urlBuilder.append("/" +  URLEncoder.encode("json","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("subwayTourInfo","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("5","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
			// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
			
			// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
			//urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		String apiURL=urlBuilder.toString();
		System.out.println(apiURL); // URL 정보 가지고 오기 
		URL url = new URL(apiURL);
		
		//접속 확인하기 
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		//conn.setRequestProperty("Content-type", "application/json"); //데이터값 변경
		int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null;

 

 

 

6. 데이터 값 불러오기 

- 먼저 연결 성공/ 실패 값 불러오기 

int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null; 
		
		//apiUrl주소에 정상적으로 접속헀을때 
		if(responseCode == HttpURLConnection.HTTP_OK) {
			responseJSONData=readBody(conn.getInputStream());
			log.debug("-------> JSON-DATA READ SUCCESS!!!!");
			
		}else { //접속 실패 시 
			responseJSONData=readBody(conn.getErrorStream());
			log.debug("-------> JSON-DATA READ ERROR!!!!");
			
		}
		System.out.println(responseJSONData);
		conn.disconnect();

- 데이터 값 가지고 오기 

위에서 만들어진 readbody 메서드 안에 넣기 

		//////////////////////////
		//대소문자 구분하지 않는 맵핑 
		// JSONSTRING -> java Obj 맵핑 
		//ObjectMapper mapper=new ObjectMapper()
		ObjectMapper mapper = JsonMapper.builder() 
								.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) 
								.build();
		//responseJSONData 데이터를 최상위 데이타에 맵핑해줄게용
		ResponseData result = mapper.readValue(responseJSONData, ResponseData.class); 
		System.out.println(result); // 결과 확인 
		
	}
	
	//응답데이터를 스트림을 통해서 한줄씩 읽어서 문자열로 리턴해주는 메서드 
	private String readBody(InputStream inputStream) throws IOException {
		InputStreamReader isr=new InputStreamReader(inputStream) ;
		BufferedReader lineReader = new BufferedReader(isr);
		
		StringBuilder responseBody = new StringBuilder(); // return할 데이터를 읽어온다
		
		String data; // return할 데이터 
		while ( (data = lineReader.readLine()) != null/* 한줄씩 읽어오고, 없을때 그만한다 */) {
			responseBody.append(data);
		}
		
		lineReader.close(); //예외 발생
		isr.close(); //예외 발생
		return responseBody.toString();
	}

}

 

>> 5~6번 완성 

 

package com.green.nowon.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.green.nowon.openapi.seoul.ResponseData;
import com.green.nowon.service.SubwayElevatorService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class SubwayElevatorServiceProcess implements SubwayElevatorService{

	@Value("${seoul.key}")
	private String seoulKey;
	
	@Override
	public void getElevatorInfo() throws Exception {
		
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode(seoulKey,"UTF-8") );
		urlBuilder.append("/" +  URLEncoder.encode("json","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("subwayTourInfo","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("5","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
			// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
			
			// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
			//urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		String apiURL=urlBuilder.toString();
		System.out.println(apiURL); // URL 정보 가지고 오기 
		URL url = new URL(apiURL);
		
		//접속 확인하기 
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		//conn.setRequestProperty("Content-type", "application/json"); //데이터값 변경
		int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null; 
		
		//apiUrl주소에 정상적으로 접속헀을때 
		if(responseCode == HttpURLConnection.HTTP_OK) {
			responseJSONData=readBody(conn.getInputStream());
			log.debug("-------> JSON-DATA READ SUCCESS!!!!");
			
		}else { //접속 실패 시 
			responseJSONData=readBody(conn.getErrorStream());
			log.debug("-------> JSON-DATA READ ERROR!!!!");
			
		}
		//System.out.println(responseJSONData);
		conn.disconnect();
		
		//////////////////////////
		//대소문자 구분하지 않는 맵핑 
		// JSONSTRING -> java Obj 맵핑 
		//ObjectMapper mapper=new ObjectMapper()
		ObjectMapper mapper = JsonMapper.builder() 
								.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) 
								.build();
		//responseJSONData 데이터를 최상위 데이타에 맵핑해줄게용
		ResponseData result = mapper.readValue(responseJSONData, ResponseData.class); 
		System.out.println(result); // 결과 확인 
		
	}
	
	//응답데이터를 스트림을 통해서 한줄씩 읽어서 문자열로 리턴해주는 메서드 
	private String readBody(InputStream inputStream) throws IOException {
		InputStreamReader isr=new InputStreamReader(inputStream) ;
		BufferedReader lineReader = new BufferedReader(isr);
		
		StringBuilder responseBody = new StringBuilder(); // return할 데이터를 읽어온다
		
		String data; // return할 데이터 
		while ( (data = lineReader.readLine()) != null/* 한줄씩 읽어오고, 없을때 그만한다 */) {
			responseBody.append(data);
		}
		
		lineReader.close(); //예외 발생
		isr.close(); //예외 발생
		return responseBody.toString();
	}

}

-- 잘 Run 되고 메뉴 눌렀을때 info 가 나오면 여기까지 잘 성공한겨 --

 

 

 

7. 맵핑하기 

 

 

(1) data 클래스 생성 후 아래 api 참고하여 클래스 추가 생성하기  

- ResounseData 클래스 생성하여 아래 SubwayTourInfo 클래스 생성 // 자동생성 

- list 와 Result 클래스 생성하기 

package com.green.nowon.openapi.seoul;

import lombok.Data;

@Data
public class ResponseData {

	private SubwayTourInfo subwayTourInfo; //클래스 만들기, api 참고하여 클래스명 생성 
}
package com.green.nowon.openapi.seoul;

import java.util.List;

import lombok.Data;

@Data
public class SubwayTourInfo {

	private int list_total_count;
	private RESULT result; // 클래스 생성 
	private List<item> row; //배열이기에 list 로 선언 //이름이 별도 없어서 item  //클래스 생성 
	
}
package com.green.nowon.openapi.seoul;

import lombok.Data;

@Data
public class RESULT {
	private String CODE;
	private String MESSAGE; 
}

 

(2) item 클래스에 샘플코드 넣어주기 

 

- Crtl +f 후 " 는 지워주고 : 는 ; // 로 바꿔주기

- 후 private String 넣어주기  

package com.green.nowon.openapi.seoul;

import lombok.Data;

@Data
public class item { //18개 필드 필요 
	private String NO; // 173
	private String LINE; // 4,
	private String LINE_NAME; // 4호선,
	private String STATION; // 노원,
	private String STATION_IMAGE; // <img src=\https; ////wis.eseoul.go.kr/images/disable/subway/4_173_M.jpg\ alt=\노원 이미지\ NAME=\stationImg\ ID=\stationImg\/>,
	private String COURSE1; // 당고개,
	private String COURSE2; // 오이도,
	private String ELEVATER; // http; ////wis.seoul.go.kr/rest/file/thumbnail/fb1h26s5y0znrfth8e9tpq9z8c6u3hx2/1,
	private String ELEVATER_TXT; // 승강기 위치는 9번 출구쪽에 있습니다\r\r\r\n\r\r\r\n승강기를 이용하여 2층 대합실로 올라가십시오.\r\r\r\n\r\r\r\n좌측 방향으로 이동하여 우측 개찰구를 통과하십시오.\r\r\r\n\r\r\r\n승강기를 이용하여 승강장으로 올라가십시오.,
	private String STATION_IMAGE2; // <img src=\https; ////wis.eseoul.go.kr/images/disable/subway/20130228180252.jpg\ alt=\노원 이미지\ NAME=\stationBigImg\ ID=\stationBigImg\/>,
	private String USEYN; // Y,
	private String ICON_PATH; // <img src=\http; ////wis.seoul.go.kr/images/disable/subway/20081021143442.jpg\ alt=\에스켈레이터 이미지\ />,<img src=\http; ////wis.seoul.go.kr/images/disable/subway/20081021143830.jpg\ alt=\엘리베이터 이미지\ />,<img src=\http; ////wis.seoul.go.kr/images/disable/subway/20081021143901.jpg\ alt=\화장실 이미지\ />,<img src=\http; ////wis.seoul.go.kr/images/disable/subway/20081021143945.jpg\ alt=\휠체어리프트 이미지\ />,
	private String EXIT_INFO; // ||1@상계6.7동 주민센터, 상계7동 치안센터, 상계중학교, 상계 119안전센터, 성민복지관||,||2@노원구청, 신상중학교, 상수초등학교, 한국성서대학교, 상계주공아파트 1-6단지, 기업은행 노원역지점, KDB산업은행, 한국전력공사북부지점, 노원 헌혈의 집||,||3@운전면허시험장,용화여고,||,||4@수협,기업은행,상계초등교,국민은행,||,||9@상계동, 창동지하철차량기지, 도봉운전면허시험장, 용화여고, 상월초등학교, 대림.현대아파트, 상계주공아파트||,||10@상계2동주민센터, 상계10동우체국, 상계초등학교, 온곡중학교, 우성아파트, 동양메이저아파트||,
	private String TELNO_INFO; // 긴급전화(역무실) ; // 02-6110-4111,
	private String TIME_INFO1; // 노원 ; // 06시04분,
	private String TIME_INFO2; // 노원 ; // 24시59분,
	private String TIME_INFO3; // 노원 ; // 05시30분,
	private String TIME_INFO4; // 노원 ; // 23시12분
	
}

 

-- Run 후 목록 눌렀을때,  콘솔에 내용이 나오면 성공 -- 

 

(3) model 넣어주기

package com.green.nowon.service;

import org.springframework.ui.Model;

public interface SubwayElevatorService {

	void getElevatorInfo(Model model) throws Exception;

}
package com.green.nowon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.green.nowon.service.SubwayElevatorService;

import lombok.RequiredArgsConstructor;

//@RequiredArgsConstructor
@Controller
public class SubwayController {

	private final SubwayElevatorService service; //Constructor DI 
	
	
	public SubwayController(SubwayElevatorService service) { 
		this.service = service; 
	}
	 
	
	@GetMapping("/subway")
	public String subway(Model model) throws Exception {
		service.getElevatorInfo(model);
		return "subway/list";
		
	}
	
}

- getElevatorInfo 메서드안에 model 데이터값 넣어주기

model.addAttribute("list", result.getSubwayTourInfo().getRow()); //row 의 데이터

package com.green.nowon.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.green.nowon.openapi.seoul.ResponseData;
import com.green.nowon.service.SubwayElevatorService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class SubwayElevatorServiceProcess implements SubwayElevatorService{

	@Value("${seoul.key}")
	private String seoulKey;
	
	@Override
	public void getElevatorInfo(Model model) throws Exception {
		
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode(seoulKey,"UTF-8") );
		urlBuilder.append("/" +  URLEncoder.encode("json","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("subwayTourInfo","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("30","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
			// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
			
			// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
			//urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		String apiURL=urlBuilder.toString();
		System.out.println(apiURL); // URL 정보 가지고 오기 
		URL url = new URL(apiURL);
		
		//접속 확인하기 
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		//conn.setRequestProperty("Content-type", "application/json"); //데이터값 변경
		int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null; 
		
		//apiUrl주소에 정상적으로 접속헀을때 
		if(responseCode == HttpURLConnection.HTTP_OK) {
			responseJSONData=readBody(conn.getInputStream());
			log.debug("-------> JSON-DATA READ SUCCESS!!!!");
			
		}else { //접속 실패 시 
			responseJSONData=readBody(conn.getErrorStream());
			log.debug("-------> JSON-DATA READ ERROR!!!!");
			
		}
		//System.out.println(responseJSONData);
		conn.disconnect();
		
		//////////////////////////
		
		// JSONSTRING -> java Obj 맵핑 
		//ObjectMapper mapper=new ObjectMapper()
		//대소문자 구분하지 않는 맵핑 
		ObjectMapper mapper = JsonMapper.builder() 
								.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) 
								.build();
		//responseJSONData 데이터를 최상위 데이타에 맵핑해줄게용
		ResponseData result = mapper.readValue(responseJSONData, ResponseData.class); 
		System.out.println(result); // 결과 확인 
		
		model.addAttribute("list", result.getSubwayTourInfo().getRow()); //row 의 데이터 
		
	}
	
	//응답데이터를 스트림을 통해서 한줄씩 읽어서 문자열로 리턴해주는 메서드 
	private String readBody(InputStream inputStream) throws IOException {
		InputStreamReader isr=new InputStreamReader(inputStream) ;
		BufferedReader lineReader = new BufferedReader(isr);
		
		StringBuilder responseBody = new StringBuilder(); // return할 데이터를 읽어온다
		
		String data; // return할 데이터 /* 한줄씩 읽어오고, 없을때 그만한다 */
		while ( (data = lineReader.readLine()) != null) {
			responseBody.append(data);
		}
		
		lineReader.close(); //예외 발생
		isr.close(); //예외 발생
		return responseBody.toString();
	}

}

 

8. 데이터 뿌리기 

 

 

- 테이블 생성

- thbody에 th each 연결 (원하는 태그만) item.java보고 연결하기 

- 더 많은 값을 보고 싶으면 SubWayElevatorServiceProcess 의 urlBuilder.append 의 마지막 줄을 5-> 원하는 수만큼 숫자로 변경 

- 정렬이 되어있지 않기에, serviceprocess에 넣었던 model 을 아래와 같이 변경 

model.addAttribute("list", result.getSubwayTourInfo().getRow().stream()
									.sorted(Comparator.comparing(item::getLINE_NAME))
									.filter(item->item.getLINE().equals("1"))
									.collect(Collectors.toList())); //row 의 데이터 //호선별로 정렬 //1호선만
<!DOCTYPE html>
<html xmlns:th="//www.thymeleaf.org"
	th:replace="layout/layout1 :: layout(~{::head},~{this::main})" >
<head>
	<style type="text/css">
		td{width: 80px; height:28px; border-bottom: 1px solid #a9a9a9;}
		td:nth-of-type(6){width: 100px;}
		td:last-child{width:300px;}	
	</style>
	
</head>	
<main>
	<h1>메인영역</h1>
	<div class="wrap view-size">
		<section>
			<h1>게시글내용</h1>
			<div class="wrap">
				<p class="tit">지하철 엘레베이터 정보</p>
				
				<table>
					<thead>
						<tr>
							<td>고유번호</td>
							<td>노선</td>
							<td>역명칭</td>
							<td>운행방향1</td>
							<td>운행방향2</td>
							<td>편의시설</td>
							<td>연락처</td>
						</tr>
					</thead>
					<tbody>
						<tr th:each="dto:${list}">
							<td th:text="${dto.NO}">고유번호</td>
							<td th:text="${dto.LINE_NAME}">노선</td>
							<td th:text="${dto.STATION}">역명칭</td>
							<td>
								<div th:text="${dto.COURSE1}"> 운행방향1 </div>
							</td>
							<td>
								<div th:text="${dto.COURSE2}"> 운행방향2 </div>
							</td>							
							<td th:utext="${dto.ICON_PATH}">편의시설</td> <!-- 아이콘이라 u -->
							<td th:text="${dto.TELNO_INFO}">연락처</td>
						</tr>
					</tbody>
				</table>
			</div>
		</section>
	</div>
</main>
</html>

 

 

>>>>>> 완료!! 

 


 

** 다른 데이터 추가해보기! 

 

1. 메뉴 추가 하기 

<!DOCTYPE html>
<html>
<header>
	<h1>헤더영역</h1>
	<div class="wrap view-size">
		<a href="/">HOME</a>
		<a href="/board">게시글</a>
		<a href="/my-board">마이게시글</a>
		<a href="/subway">지하철 엘레베이터</a>
		<a href="/bus">버스정류장</a>
	</div>
</header>
</html>

 

 

2. 컨트롤러 위에 이미 만든 것 아래에 추가하기

package com.green.nowon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.green.nowon.service.SeoulAPIService;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class SeoulAPIController {

	private final SeoulAPIService service; //Constructor DI 
	
	@GetMapping("/subway")
	public String subway(Model model) throws Exception {
		service.getElevatorInfo(model);
		return "seoulapi/subway-list";
		
	}
	@GetMapping("/bus")
	public String bus(Model model) throws Exception {
		service.getbusStopLocationXyInfo(model);
		return "seoulapi/bus-list";
		
	}
	
}

 

3. 이미 만들었던 인터페이스 안에 메서드 추가하기 

package com.green.nowon.service;

import org.springframework.ui.Model;

public interface SeoulAPIService {

	void getElevatorInfo(Model model) throws Exception;

	void getbusStopLocationXyInfo(Model model)throws Exception;

}

 

4. 이미 만들었던 서비스 process 안에 메서드 추가하기 (오버라이드) 

- 똑같은 샘플 코드 넣어주고  맞게 수정하기 

- 접속 확인 코드 넣기 

- 맵핑코드 넣어주기

- 뿌리는 태그 넣기 

	@Override
	public void getbusStopLocationXyInfo(Model model) throws Exception {
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode(seoulKey,"UTF-8") ); /*인증키 (sample사용시에는 호출시 제한됩니다.)*/
		urlBuilder.append("/" +  URLEncoder.encode("json","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("busStopLocationXyInfo","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("5","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
		
		String apiURL=urlBuilder.toString();
		System.out.println(apiURL); // URL 정보 가지고 오기 
		URL url = new URL(apiURL);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		
		conn.disconnect();
		
		int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null; 
		
		//apiUrl주소에 정상적으로 접속헀을때 
		if(responseCode == HttpURLConnection.HTTP_OK) {
			responseJSONData=readBody(conn.getInputStream());
			log.debug("-------> JSON-DATA READ SUCCESS!!!!");
					
		}else { //접속 실패 시 
			responseJSONData=readBody(conn.getErrorStream());
			log.debug("-------> JSON-DATA READ ERROR!!!!");
		}
		System.out.println(responseJSONData);
		
		ObjectMapper mapper = new ObjectMapper();
		ResponseBusData result= mapper.readValue(responseJSONData, ResponseBusData.class);
		System.out.println(result);
		
		// 뿌리는 태그 
		model.addAttribute("list",result.getBusStopLocationXyInfo().getRow()); //row 의 데이터 //호선별로 정렬 //1호선만 
				
	}

>> 완성

package com.green.nowon.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Comparator;
import java.util.stream.Collectors;

import org.hibernate.cache.spi.support.AbstractReadWriteAccess.Item;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.green.nowon.openapi.bus.ResponseBusData;
import com.green.nowon.openapi.seoul.ResponseData;
import com.green.nowon.openapi.seoul.item;
import com.green.nowon.service.SeoulAPIService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class SeoulAPIServiceProcess implements SeoulAPIService{

	@Value("${seoul.key}")
	private String seoulKey;
	
	

	@Override
	public void getbusStopLocationXyInfo(Model model) throws Exception {
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode(seoulKey,"UTF-8") ); /*인증키 (sample사용시에는 호출시 제한됩니다.)*/
		urlBuilder.append("/" +  URLEncoder.encode("json","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("busStopLocationXyInfo","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("5","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
		
		String apiURL=urlBuilder.toString();
		System.out.println(apiURL); // URL 정보 가지고 오기 
		URL url = new URL(apiURL);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		
		conn.disconnect();
		
		int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null; 
		
		//apiUrl주소에 정상적으로 접속헀을때 
		if(responseCode == HttpURLConnection.HTTP_OK) {
			responseJSONData=readBody(conn.getInputStream());
			log.debug("-------> JSON-DATA READ SUCCESS!!!!");
					
		}else { //접속 실패 시 
			responseJSONData=readBody(conn.getErrorStream());
			log.debug("-------> JSON-DATA READ ERROR!!!!");
		}
		System.out.println(responseJSONData);
		
		ObjectMapper mapper = new ObjectMapper();
		ResponseBusData result= mapper.readValue(responseJSONData, ResponseBusData.class);
		System.out.println(result);
		
		// 뿌리는 태그 
		model.addAttribute("list",result.getBusStopLocationXyInfo().getRow()); //row 의 데이터 //호선별로 정렬 //1호선만 
				
	}
	
	
	
	@Override
	public void getElevatorInfo(Model model) throws Exception {
		
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode(seoulKey,"UTF-8") );
		urlBuilder.append("/" +  URLEncoder.encode("json","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("subwayTourInfo","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("100","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
			// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
			
			// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
			//urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		String apiURL=urlBuilder.toString();
		System.out.println(apiURL); // URL 정보 가지고 오기 
		URL url = new URL(apiURL);
		
		//접속 확인하기 
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		//conn.setRequestProperty("Content-type", "application/json"); //데이터값 변경
		int responseCode = conn.getResponseCode(); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		String responseJSONData=null; 
		
		//apiUrl주소에 정상적으로 접속헀을때 
		if(responseCode == HttpURLConnection.HTTP_OK) {
			responseJSONData=readBody(conn.getInputStream());
			log.debug("-------> JSON-DATA READ SUCCESS!!!!");
			
		}else { //접속 실패 시 
			responseJSONData=readBody(conn.getErrorStream());
			log.debug("-------> JSON-DATA READ ERROR!!!!");
			
		}
		//System.out.println(responseJSONData);
		conn.disconnect();
		
		//////////////////////////
		
		// JSONSTRING -> java Obj 맵핑 
		//ObjectMapper mapper=new ObjectMapper()
		//대소문자 구분하지 않는 맵핑 
		ObjectMapper mapper = JsonMapper.builder() 
								.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) 
								.build();
		//responseJSONData 데이터를 최상위 데이타에 맵핑해줄게용
		ResponseData result = mapper.readValue(responseJSONData, ResponseData.class); 
		System.out.println(result); // 결과 확인 
		
		model.addAttribute("list", result.getSubwayTourInfo().getRow().stream()
									.sorted(Comparator.comparing(item::getLINE_NAME))
									.filter(item->item.getLINE().equals("1"))
									.collect(Collectors.toList())); //row 의 데이터 //호선별로 정렬 //1호선만 
		
	}
	
	//응답데이터를 스트림을 통해서 한줄씩 읽어서 문자열로 리턴해주는 메서드 
	private String readBody(InputStream inputStream) throws IOException {
		InputStreamReader isr=new InputStreamReader(inputStream) ;
		BufferedReader lineReader = new BufferedReader(isr);
		
		StringBuilder responseBody = new StringBuilder(); // return할 데이터를 읽어온다
		
		String data; // return할 데이터 /* 한줄씩 읽어오고, 없을때 그만한다 */
		while ( (data = lineReader.readLine()) != null) {
			responseBody.append(data);
		}
		
		lineReader.close(); //예외 발생
		isr.close(); //예외 발생
		return responseBody.toString();
	}



}

 

 

5. 데이터 태그 맵핑하기 api 코드와 동일하게 

-@JsonProperty 는 대소문자 구분때문에... 

package com.green.nowon.openapi.bus;

import lombok.Data;

@Data
public class ResponseBusData {

	private BusStopLocationXyInfo busStopLocationXyInfo;
}
package com.green.nowon.openapi.bus;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;

@Data
public class BusStopLocationXyInfo {
	
	@JsonProperty("list_total_count")
	private int listTotalCount;
	
	@JsonProperty("RESULT")
	private Result result;
	
	private List<busitem> row;
}
package com.green.nowon.openapi.bus;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;

@Data
public class Result {

	@JsonProperty("CODE")
	private String code;
	
	@JsonProperty("MESSAGE")
	private String message;
}
package com.green.nowon.openapi.bus;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;

@Data
public class busitem {
	
	@JsonProperty("STOP_NO")
	private String STOP_NO;// 01001,
	@JsonProperty("STOP_NM")
	private String STOP_NM;// 종로2가사거리,
	@JsonProperty("XCODE")
	private String XCODE;// 126.9877498816,
	@JsonProperty("YCODE")
	private String YCODE;// 37.5697651251
}

 

5. bus Html 수정하기 

<!DOCTYPE html>
<html xmlns:th="//www.thymeleaf.org"
	th:replace="layout/layout1 :: layout(~{::head},~{this::main})" >
<head>
	<style type="text/css">
		td{width: 200px; height:28px; border-bottom: 1px solid #a9a9a9; text-align: center;}
		td:nth-of-type(2){width: 300px;}
	</style>
	
</head>	
<main>
	<h1>메인영역</h1>
	<div class="wrap view-size">
		<section>
			<h1>게시글내용</h1>
			<div class="wrap">
				<p class="tit">버스 정류장 정보</p>
					<table>
						<thead>
							<tr>
								<td>고유번호</td>
								<td>정류장이름</td>
								<td>X좌표</td>
								<td>Y좌표</td>
							</tr>
						</thead>
						<tbody>
							<tr th:each="dto:${list}">
								<td th:text="${dto.STOP_NO}">고유번호</td>
								<td th:text="${dto.STOP_NM}">정류장이름</td>
								<td th:text="${dto.XCODE}">X좌표</td>
								<td th:text="${dto.YCODE}">Y좌표</td>
							</tr>
						</tbody>
						
					
					</table>
			</div>
		</section>
	</div>
</main>
</html>