-
[프로젝트] 해양 재난 상황판 (2)개발/프로젝트 2022. 3. 1. 22:22
JAVA Springboot를 사용해서 REST API를 구축했다.
DB 연결
가장 먼저 전에 구현한 DB를 JDBC를 이용해서 스프링부트와 연결해주었다.
///// application.properties ///// server.address=localhost server.port = 8080 spring.datasource.url = jdbc:mysql://localhost:3306/mydb spring.datasource.username = root spring.datasource.password = password spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update logging.level.org.hibernate = info spring.jpa.properties.hibernate.show_sql = true spring.jpa.properties.hibernate.fromat_sql = true spring.jpa.properties.hibernate.use_sql_comments = true
엔티티와 DTO 구성
DB에서 데이터를 받아올 엔티티를 구성한다.
스프링부트에서 바로 DB를 조작하면 데이터가 취약해질 수 있기 때문에 엔티티를 만들고
이를 DTO로 넘겨서 DTO를 조작하는 방법을 사용한다.
//// shipDTO.java //// package com.example.demo.dto; import java.time.LocalDateTime; import lombok.Builder; import lombok.Data; @Data @Builder(toBuilder = true) public class shipDTO { private String shipId; // 선박 고유 id private String shipName; // 선박 이름 private String shipOwner; // 선박주 명 private String shipPhone; // 선박 전화번호 private String shipTime; // 출항 시간 private String shipPurpose; // 출항 목적 private String shipPeople; // 탑승 승객 수 private String shipLat; // 선박 위치 위도 private String shipLon; // 선박 위치 경도 private String shipIns; // 보험 유무 }
//// shipEntity.java //// package com.example.demo.entity; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import javax.persistence.*; @Getter @Builder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity(name="ship") public class shipEntity { @Id @Column(nullable = false) private String shipId; @Column(nullable = false, unique = true, length = 30) private String shipName; @Column(nullable = false, length = 30) private String shipOwner; @Column(nullable = false, length = 30) private String shipPhone; @Column(nullable = false, length = 50) //private String shipTime; private String shipTime; @Column(nullable = false, length = 50) private String shipPurpose; @Column(nullable = false, length = 50) private String shipPeople; @Column(nullable = false, length = 30) private String shipLat; @Column(nullable = false, length = 30) private String shipLon; @Column(nullable = false, length = 30) private String shipIns; }
Entity ↔ DTO변환
두 클래스간 정보를 동기화 하는 함수
///// shipService.java ///// package com.example.demo.service; import java.util.List; import com.example.demo.dto.shipDTO; import com.example.demo.entity.shipEntity; public interface shipService { default shipEntity dtoToEntity(shipDTO dto) { shipEntity entity = shipEntity.builder() .shipId(dto.getShipId()) .shipName(dto.getShipName()) .shipOwner(dto.getShipOwner()) .shipPhone(dto.getShipPhone()) .shipTime(dto.getShipTime()) .shipPurpose(dto.getShipPurpose()) .shipPeople(dto.getShipPeople()) .shipLat(dto.getShipLat()) .shipLon(dto.getShipLon()) .shipIns(dto.getShipIns()) .build(); return entity; } default shipDTO entityToDTO(shipEntity entity) { shipDTO dto = shipDTO.builder() .shipId(entity.getShipId()) .shipName(entity.getShipName()) .shipOwner(entity.getShipOwner()) .shipPhone(entity.getShipPhone()) .shipTime(entity.getShipTime()) .shipPurpose(entity.getShipPurpose()) .shipPeople(entity.getShipPeople()) .shipLat(entity.getShipLat()) .shipLon(entity.getShipLon()) .shipIns(entity.getShipIns()) .build(); return dto; } }
Repo - Service - ServiceImpl 구조
//// accRepo.java //// package com.example.demo.repo; import org.springframework.stereotype.Repository; import java.util.List; import com.example.demo.entity.accEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @Repository public interface accRepo extends JpaRepository<accEntity, Long>{ Integer countByAccTypeLike(String accType); List<accEntity> findByAccId(String accId); List<accEntity> findByAccStateNotLike(String accType); @Query("select count(acc_type) from accident where acc_type like ?1 and acc_time = ?2") public Integer countByAccTypeByDate(String acctype, String acctime); @Query("select count(acc_id) from accident where acc_time = ?1") public Integer countByDay(String acctime); @Query("select count(acc_id) from accident where week(acc_time)=week(?1) and year(acc_time) = year(?1)") public Integer countByWeek(String acctime); @Query("select count(acc_id) from accident where substring(acc_time,1,7) = substring(?1,1,7) and acc_time <= ?1") public Integer countByMonth(String acctime); @Query("select count(acc_id) from accident where year(acc_time) = substring(?1, 1,4) and acc_time <= ?1") public Integer countByYear(String acctime); }
//// accService.java //// package com.example.demo.service; import java.util.List; import com.example.demo.dto.accDTO; import com.example.demo.dto.accTypeDTO; import com.example.demo.entity.accEntity; public interface accService { List<accDTO> getListAll(); accTypeDTO countByType(/*String accDate*/); List<accDTO> getOne(String accId); default accEntity dtoToEntity(accDTO dto) { accEntity entity = accEntity.builder() .accId(dto.getAccId()) .resId(dto.getResId()) .accType(dto.getAccType()) .accDetail(dto.getAccDetail()) .accCall(dto.getAccCall()) .accCaller(dto.getAccCaller()) .accSubmit(dto.getAccSubmit()) .accState(dto.getAccState()) .accLat(dto.getAccLat()) .accLon(dto.getAccLon()) .accResp(dto.getAccResp()) .accTime(dto.getAccTime()) .accInfo(dto.getAccInfo()) .accShipId(dto.getAccShipId()) .dispId(dto.getDispId()) .build(); return entity; } default accDTO entityToDTO(accEntity entity) { accDTO dto = accDTO.builder() .accId(entity.getAccId()) .resId(entity.getResId()) .accType(entity.getAccType()) .accDetail(entity.getAccDetail()) .accCall(entity.getAccCall()) .accCaller(entity.getAccCaller()) .accSubmit(entity.getAccSubmit()) .accState(entity.getAccState()) .accLat(entity.getAccLat()) .accLon(entity.getAccLon()) .accResp(entity.getAccResp()) .accTime(entity.getAccTime()) .accInfo(entity.getAccInfo()) .accShipId(entity.getAccShipId()) .dispId(entity.getDispId()) .build(); return dto; } }
///// accServiceImpl.java ///// package com.example.demo.service; import java.time.LocalDate; import java.util.List; import java.util.stream.Collectors; import com.example.demo.dto.accDTO; import com.example.demo.dto.accTypeDTO; import com.example.demo.repo.accRepo; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class accServiceImpl implements accService { private final accRepo repo; // 해양사고 분류별 count @Override public accTypeDTO countByType(/*String accDate*/){ //LocalDate accDates = LocalDate.parse(accDate); LocalDate accDates = LocalDate.now(); String dateStr = accDates.toString(); //Date accDates = new Date(); accTypeDTO dto = accTypeDTO.builder() .accAccident(repo.countByAccTypeByDate("%사고", dateStr)) .accPolution(repo.countByAccTypeByDate("%오염", dateStr)) .accOrder(repo.countByAccTypeByDate("%치안", dateStr)) .accSecurity(repo.countByAccTypeByDate("%안보", dateStr)) .accComplaint(repo.countByAccTypeByDate("%민원", dateStr)) .accPerDay(repo.countByDay(dateStr)) .accPerWeek(repo.countByWeek(dateStr)) .accPerMonth(repo.countByMonth(dateStr)) .accPerYear(repo.countByYear(dateStr)) .build(); return dto; } // 해양사고 전체 @Override public List<accDTO> getListAll(){ return repo.findByAccStateNotLike("종료").stream().map(this::entityToDTO).collect(Collectors.toList()); } // accId별 사고 하나 @Override public List<accDTO> getOne(String accId){ return repo.findByAccId(accId).stream().map(this::entityToDTO).collect(Collectors.toList()); } }
Controller 구성
URL를 연결해주었고, 이 URL으로 접속했을 때 리스트 형태로 받아온 데이터를 JSON형태로 표출해준다.
package com.example.demo.controller; import com.example.demo.service.shipService; import java.util.HashMap; import java.util.List; import com.example.demo.dto.shipDTO; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import lombok.RequiredArgsConstructor; @RestController @RequiredArgsConstructor @RequestMapping("/v1") @CrossOrigin("*") public class Controller { private final shipService shipserv; // 모든 배에 대한 정보 @GetMapping("/ship") public HashMap<String, Object> getship(@RequestParam(name="shipid", required = false) String shipId){ if(shipId != null){ List<shipDTO> dto = shipserv.getOne(shipId); HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put(shipId, dto); return hashMap; } else{ List<shipDTO> list = shipserv.getListAll(); HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put("list", list); return hashMap; } } }
자바에 익숙하지 않았는데, 스프링 부트까지 함께 익히느라 많이 헤맸었다.
그래도 REST API구조, Builder, MVC 패턴 등 자바의 여러가지 기술들을 익힐 수 있었다.
Django를 사용할 때에는 기본적으로 SQLite로 모두 처리되기 때문에 프로젝트 진행 측면에서는 DB를 손댈 필요가 없었는데, 스프링부트를 하면서 JDBC, ORM, JPA에 대해서 이해할 수 있었다.
'개발 > 프로젝트' 카테고리의 다른 글
[프로젝트] 약 추천 서비스 (0) 2022.06.03 [프로젝트] 해양 재난 상황판 (1) (0) 2022.02.10 [프로젝트] TradingBot / 업비트 자동 매매 봇 (0) 2022.01.18 [프로젝트] Django 프로젝트 / Heros (0) 2021.12.09