Skip to content

Commit

Permalink
[FEAT] BusApiService 구현 (#62)
Browse files Browse the repository at this point in the history
## 작업 내용
- 가장 간단한 형태의 구현
- ApiKeyProperty interface
- BusApiKeyProperty
- PublicBusApiResp interface

## NOTE
- 240809 에 정해둔 형태의 가장 간단한 형태의 구현입니다. (에러 핸들링 없음)
- FE 작업 중에 데이터 주입이 급해서 작성되었습니다.
  - 버스 노선 정보 획득 필요 (검색 기능쪽에서)
- 버스 노선 정보가 총 5천개 가량되는데, 이를 정적 데이터로 획득하기 위한 방법이 필요합니다. (하나씩 가져와야하여 5일가량
소요됨)
  • Loading branch information
JuneParkCode authored Aug 11, 2024
1 parent 6061c06 commit 8d7ff18
Show file tree
Hide file tree
Showing 18 changed files with 398 additions and 7 deletions.
4 changes: 3 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ MYSQL_DATABASE=TALKKA_DB
MYSQL_URL=jdbc:mysql://localhost:3306/TALKKA_DB?createDatabaseIfNotExist=true

NAVER_CLIENT_ID=CLIENT_ID
NAVER_CLINET_SECRET=CLIENT_SECRET
NAVER_CLINET_SECRET=CLIENT_SECRET

SERVICE_KEY_1=SERVICE_KEY_1
3 changes: 3 additions & 0 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ dependencies {
// Thymeleaf 의 경우 테스트 혹은 관리자에서 추후에 사용하기 위해서 유지합니다.
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
// XML Parser
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.talkka.server.api.core.config;

public interface ApiKeyProperty {
String getApiKey();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.talkka.server.api.datagg.config;

import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import com.talkka.server.api.core.config.ApiKeyProperty;

import lombok.Getter;
import lombok.Setter;

@Getter
@Component
@ConfigurationProperties(prefix = "openapi.public.bus.service-key")
public class BusApiKeyProperty implements ApiKeyProperty {
@Setter
private List<String> keys;

private int rollingKeyIndex = 0;

@Override
public String getApiKey() {
rollingKeyIndex = (rollingKeyIndex + 1) % keys.size();
return keys.get(rollingKeyIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.talkka.server.api.datagg.dto;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "busLocationList")
public record BusLocationBodyDto(String endBus, String lowPlate, String plateNo, String plateType,
Integer remainSeatCnt, Long routeId, Long stationId, Integer stationSeq) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.talkka.server.api.datagg.dto;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "response")
public record BusLocationRespDto(@JacksonXmlProperty(localName = "comMsgHeader") Map<String, String> comMsgHeader,
@JacksonXmlProperty(localName = "msgHeader") Map<String, String> msgHeader,
@JacksonXmlProperty(localName = "msgBody") List<BusLocationBodyDto> msgBody)
implements PublicBusApiResp<BusLocationBodyDto> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.talkka.server.api.datagg.dto;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "busRouteInfoItem")
public record BusRouteInfoBodyDto(
String companyId, // 운수업체 아이디
String companyName, // 운수업체명
String companyTel, // 운수업체 전화번호
int districtCd, // 관할 지역 코드
String downFirstTime, // 평일 종점 첫차 시간
String downLastTime, // 평일 종점 막차 시간
Long endStationId, // 종점 정류소 아이디
String endStationName, // 종점 정류소명
int peekAlloc, // 평일 최소 배차 시간
String regionName, // 지역명
Long routeId, // 노선 아이디
String routeName, // 노선 번호
int routeTypeCd, // 노선 유형 코드
String routeTypeName, // 노선 유형명
String startMobileNo, // 기점 정류소 번호
Long startStationId, // 기점 정류소 아이디
String startStationName, // 기점 정류소명
String upFirstTime, // 평일 기점 첫차 시간
String upLastTime, // 평일 기점 막차 시간
int nPeekAlloc // 평일 최대 배차 시간
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.talkka.server.api.datagg.dto;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "response")
public record BusRouteInfoRespDto(@JacksonXmlProperty(localName = "comMsgHeader") Map<String, String> comMsgHeader,
@JacksonXmlProperty(localName = "msgHeader") Map<String, String> msgHeader,
@JacksonXmlProperty(localName = "msgBody") List<BusRouteInfoBodyDto> msgBody)
implements PublicBusApiResp<BusRouteInfoBodyDto> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.talkka.server.api.datagg.dto;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

/**
* @param routeId 노선 아이디
* @param routeName 노선 번호
* @param routeTypeCd 노선 유형 코드
* @param routeTypeName 노선 유형명
* @param regionName 노선 운행 지역
* @param districtCd 노선 관할 지역 코드 */
@JacksonXmlRootElement(localName = "busRouteList")
public record BusRouteSearchBodyDto(Long routeId, String routeName, String routeTypeCd, String routeTypeName,
String regionName, int districtCd) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.talkka.server.api.datagg.dto;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "response")
public record BusRouteSearchRespDto(@JacksonXmlProperty(localName = "comMsgHeader") Map<String, String> comMsgHeader,
@JacksonXmlProperty(localName = "msgHeader") Map<String, String> msgHeader,
@JacksonXmlProperty(localName = "msgBody") List<BusRouteSearchBodyDto> msgBody)
implements PublicBusApiResp<BusRouteSearchBodyDto> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.talkka.server.api.datagg.dto;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

/**
* @param stationId 정류소 아이디
* @param stationSeq 정류소 순번
* @param stationName 정류소 명칭
* @param mobileNo 정류소 고유 모바일 번호
* @param regionName 정류소 위치 지역명
* @param districtCd 노선 관할 지역 코드
* @param centerYn 중앙차로 여부 (N: 일반, Y: 중앙차로)
* @param turnYn 회차점 여부 (N: 일반, Y: 회차점)
* @param x 정류소 X 좌표
* @param y 정류소 Y 좌표 */
@JacksonXmlRootElement(localName = "busRouteStationList")
public record BusRouteStationBodyDto(Long stationId, Integer stationSeq, String stationName, String mobileNo,
String regionName, String districtCd, String centerYn, String turnYn, Double x,
Double y) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.talkka.server.api.datagg.dto;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "response")
public record BusRouteStationRespDto(@JacksonXmlProperty(localName = "comMsgHeader") Map<String, String> comMsgHeader,
@JacksonXmlProperty(localName = "msgHeader") Map<String, String> msgHeader,
@JacksonXmlProperty(localName = "msgBody") List<BusRouteStationBodyDto> msgBody)
implements PublicBusApiResp<BusRouteStationBodyDto> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.talkka.server.api.datagg.dto;

import java.util.List;
import java.util.Map;

public interface PublicBusApiResp<T> {
Map<String, String> comMsgHeader();

Map<String, String> msgHeader();

List<T> msgBody();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.talkka.server.api.datagg.service;

import java.util.List;

import com.talkka.server.api.datagg.dto.BusLocationBodyDto;
import com.talkka.server.api.datagg.dto.BusRouteInfoBodyDto;
import com.talkka.server.api.datagg.dto.BusRouteSearchBodyDto;
import com.talkka.server.api.datagg.dto.BusRouteStationBodyDto;

public interface BusApiService {
List<BusRouteSearchBodyDto> getSearchedRouteInfo(String routeName);

List<BusRouteInfoBodyDto> getRouteInfo(String apiRouteId);

List<BusRouteStationBodyDto> getRouteStationInfo(String apiRouteId);

List<BusLocationBodyDto> getBusLocationInfo(String apiRouteId);

// List<RouteBusStationArrivalInfoRespDto> getBusStationArrivalInfo(String routeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.talkka.server.api.datagg.service;

import java.net.URI;
import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;

import com.talkka.server.api.datagg.config.BusApiKeyProperty;
import com.talkka.server.api.datagg.dto.BusLocationBodyDto;
import com.talkka.server.api.datagg.dto.BusLocationRespDto;
import com.talkka.server.api.datagg.dto.BusRouteInfoBodyDto;
import com.talkka.server.api.datagg.dto.BusRouteInfoRespDto;
import com.talkka.server.api.datagg.dto.BusRouteSearchBodyDto;
import com.talkka.server.api.datagg.dto.BusRouteSearchRespDto;
import com.talkka.server.api.datagg.dto.BusRouteStationBodyDto;
import com.talkka.server.api.datagg.dto.BusRouteStationRespDto;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class BusApiServiceImpl implements BusApiService {
private final BusApiKeyProperty busApiKeyProperty;
private final RestTemplate restTemplate = new RestTemplate();
private static final String host = "apis.data.go.kr";

@Override
public List<BusRouteSearchBodyDto> getSearchedRouteInfo(String keyword) {
final String path = "/6410000/busrouteservice/getBusRouteList";
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("keyword", keyword);
URI uri = this.getOpenApiURI(path, params);
ResponseEntity<BusRouteSearchRespDto> resp = restTemplate.getForEntity(uri, BusRouteSearchRespDto.class);
return resp.getBody().msgBody();
}

@Override
public List<BusRouteInfoBodyDto> getRouteInfo(String apiRouteId) {
final String path = "/6410000/busrouteservice/getBusRouteInfoItem";
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("routeId", apiRouteId);
URI uri = this.getOpenApiURI(path, params);
ResponseEntity<BusRouteInfoRespDto> resp = restTemplate.getForEntity(uri, BusRouteInfoRespDto.class);
return resp.getBody().msgBody();
}

@Override
public List<BusRouteStationBodyDto> getRouteStationInfo(String apiRouteId) {
final String path = "/6410000/busrouteservice/getBusRouteStationList";
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("routeId", apiRouteId);
URI uri = this.getOpenApiURI(path, params);
ResponseEntity<BusRouteStationRespDto> resp = restTemplate.getForEntity(uri, BusRouteStationRespDto.class);
return resp.getBody().msgBody();
}

@Override
public List<BusLocationBodyDto> getBusLocationInfo(String apiRouteId) {
final String path = "/6410000/buslocationservice/getBusLocationList";
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("routeId", apiRouteId);
URI uri = this.getOpenApiURI(path, params);
ResponseEntity<BusLocationRespDto> resp = restTemplate.getForEntity(uri, BusLocationRespDto.class);
return resp.getBody().msgBody();
}

// @Override
// public List<RouteBusStationArrivalInfoRespDto> getBusStationArrivalInfo(String routeId) {
// return null;
// }

private URI getOpenApiURI(String path, MultiValueMap<String, String> params) {
final var builder = new DefaultUriBuilderFactory();
builder.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
return builder.builder()
.scheme("https")
.host(host)
.path(path)
.queryParam("serviceKey", this.busApiKeyProperty.getApiKey())
.queryParams(params)
.build();
}
}
10 changes: 9 additions & 1 deletion server/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,12 @@ spring:
user-name-attribute: response
thymeleaf:
prefix: classpath:/templates/
suffix: .html
suffix: .html


openapi:
public:
bus:
service-key:
keys:
- ${SERVICE_KEY_1}
Loading

0 comments on commit 8d7ff18

Please sign in to comment.