ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로젝트] 해양 재난 상황판 (2)
    개발/프로젝트 2022. 3. 1. 22:22
     

    GitHub - LJBang/make_RESTAPI: Spring Boot를 이용해 DB의 데이터를 제공하는 rest api 만들기

    Spring Boot를 이용해 DB의 데이터를 제공하는 rest api 만들기. Contribute to LJBang/make_RESTAPI development by creating an account on GitHub.

    github.com

     

    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에 대해서 이해할 수 있었다.

    댓글

Designed by Tistory.