[Spring] MVC 구조 만들기

전주은·2022년 12월 20일
0

Step0. modal.network 패키지 > request/ response 패키지와 Header 클래스

사용목적

  • Header: 성공여부와 결과를 같이 전달하기 위해
  • request/response:
  • 선택사항
package com.koreait.day6.model.network;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;


@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Header<T> {    //제네릭을 받는 이유: response / request 같이 받을 수 있어서
    private LocalDateTime transactionTime;
    private String resultCode;
    private T data; //객체 넣을 곳
    private String description; //에러 발생했을때 넣을 곳



    public static <T> Header<T> OK(){
        return (Header<T>) Header.builder().transactionTime(LocalDateTime.now())
                .resultCode("OK").description("정상").build();    

    public static <T> Header<T> OK(T data){
        return (Header<T>)Header.builder().transactionTime(LocalDateTime.now())
                .resultCode("OK").description("정상").data(data).build();
    }

    public static <T> Header<T> ERROR(String description){
        return (Header<T>)Header.builder().transactionTime(LocalDateTime.now())
                .resultCode("Error").description("에러!").build();
    }
}

OK호출시 저걸 리턴시켜줌! 클라이언트가 요청하면 아래처럼 출력

    {
        transactionTime: 현재시간,
        resultCode: 200,
        desctiption: "정상"
    }

step1.ifs(인터페이스) 패키지 > CrudInterface 인터페이스

사용목적

  • 관리용이성
  • 선택사항
package com.koreait.day6.ifs;

import com.koreait.day6.model.network.Header;

public interface CrudInterface<Req,Res> {
    Header<Res> create(Header<Req> request);
    Header<Res> read(Long id);
    Header<Res> update(Header<Req> request);
    Header<Res> delete(Long id);
}

2.controller 패키지 > CrudController 추상클래스

사용목적

package com.koreait.day6.controller;

import com.koreait.day6.ifs.CrudInterface;
import com.koreait.day6.model.network.Header;
import org.springframework.stereotype.Component;

@Component      //Component: 기본적으로 타입기반의 자동주입 어노테이션 (Autowired 비슷한 기능)
public abstract class CrudController<Req, Res, Entity> implements CrudInterface<Req, Res> {
    @Override
    public Header<Res> create(Header<Req> request) {
        return null;
    }

    @Override
    public Header<Res> read(Long id) {
        return null;
    }

    @Override
    public Header<Res> update(Header<Req> request) {
        return null;
    }

    @Override
    public Header<Res> delete(Long id) {
        return null;
    }
}

3.controller.api패키지 > UserApiController

package com.koreait.day6.controller.api;

import com.koreait.day6.controller.CrudController;
import com.koreait.day6.model.entity.Users;
import com.koreait.day6.model.network.Header;
import com.koreait.day6.model.network.request.UserApiRequest;
import com.koreait.day6.model.network.response.UserApiResponse;
import com.koreait.day6.service.UserApiLogicService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/api/user")    //http://localhost:8888/api/user
@RequiredArgsConstructor
public class UserApiController extends CrudController<UserApiRequest, UserApiResponse, Users> {
    private final UserApiLogicService userApiLogicService;
    //final 메소드: 더이상 오버라이딩 되지않도록 함
    /*  //헤더를 통해서 오게됨
        {
            "transaction_time": "2022-12-14",
            "resultCode": "ok",
            "description": "정상",
            "data":{
                "userid":"ryuzy",
                "userpw":"1111",
                "name":"류정원",
                "hp":"010-1111-1111",
                "email":"ryuzy@naver.com"
            }
        }
     */
    @Override
    @PostMapping("")    //http://localhost:8888/api/user (post)
    public Header<UserApiResponse> create(@RequestBody Header<UserApiRequest> request) {
        return userApiLogicService.create(request);

    }

    @Override
    @GetMapping("{id}")     //http://localhost:8888/api/user/{id} (get)
    public Header<UserApiResponse> read(@PathVariable(name="id") Long id) {
        return userApiLogicService.read(id);
    }

    @Override
    @PutMapping("")     //http://localhost:8888/api/user  (put)
    public Header<UserApiResponse> update(@RequestBody Header<UserApiRequest> request) {
        return userApiLogicService.update(request);
    }

    @Override
    @DeleteMapping("{id}")  //http://localhost:8888/api/user/{id} (delete)
    public Header<UserApiResponse> delete(@PathVariable Long id) {
        return userApiLogicService.delete(id);
    }
}

4.service 패키지 > UserApiLogicService와 BaseService 추상클래스

BaseService

package com.koreait.day6.service;

import com.koreait.day6.ifs.CrudInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;

@Component  //자동주입?
public abstract class BaseService<Req,Res,Entity> implements CrudInterface<Req,Res> {
    // 빈 타입을 못찾거나 의존성 주입을 할 수 없는 경우 null 에러가 발생, optional로 설정->빈생성 무조건
    @Autowired(required = false)
    protected JpaRepository<Entity, Long> baseRepository;
}

UserApiLogicService

package com.koreait.day6.service;


import com.koreait.day6.model.entity.Users;
import com.koreait.day6.model.enumclass.UserStatus;
import com.koreait.day6.model.network.Header;
import com.koreait.day6.model.network.request.UserApiRequest;
import com.koreait.day6.model.network.response.UserApiResponse;
import com.koreait.day6.repository.UsersRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.time.LocalDateTime;
import java.util.Optional;


@Service
@RequiredArgsConstructor
public class UserApiLogicService extends BaseService<UserApiRequest, UserApiResponse, Users >{

    private final UsersRepository usersRepository;  //자동주입되려면 꼭 private final

    //메소드만들자!! json보내주는걸로 여기서만 쓸거니까 private
    //객체를 리턴시켜주면 json으로 나오는거 알쥐!!?
    private UserApiResponse response(Users users){
        UserApiResponse userApiResponse = UserApiResponse.builder()
                .id(users.getId())
                .userid(users.getUserid())
                .userpw(users.getUserpw())
                .name(users.getName())
                .hp(users.getHp())
                .email(users.getEmail())
                .regDate(users.getRegDate())
                .status(users.getStatus())
                .build();
        return userApiResponse;
    }


    @Override
    public Header<UserApiResponse> create(Header<UserApiRequest> request) {
        UserApiRequest userApiRequest = request.getData();  //@Component 상속받아서 빈이 채워짐?
        Users users = Users.builder().userid(userApiRequest.getUserid())
                .userpw(userApiRequest.getUserpw()).name(userApiRequest.getName())
                .hp(userApiRequest.getHp()).email(userApiRequest.getEmail())
                .status(UserStatus.REGISTERED).build();
        Users newUsers = baseRepository.save(users);
        return Header.OK(response(newUsers));
    }

    @Override
    public Header<UserApiResponse> read(Long id) {
        return baseRepository.findById(id).map(users -> response(users))
                .map(Header::OK).orElseGet(()->Header.ERROR("데이터 없음"));
    }

    @Override
    public Header<UserApiResponse> update(Header<UserApiRequest> request) {
        /* 내코드
        UserApiRequest userApiRequest = request.getData();
        Optional<Users> users = baseRepository.findById(1L);
        users.ifPresent(
                selectUsers  -> {
                    selectUsers.setUserpw(userApiRequest.getUserpw());
                    selectUsers.setName(userApiRequest.getName());
                    baseRepository.save(selectUsers);
                }
        );
        return null;
        */
        UserApiRequest userApiRequest = request.getData();
        Optional<Users> users = usersRepository.findByUserid(userApiRequest.getUserid());
        return users.map(
                user -> {
                    user.setUserpw(userApiRequest.getUserpw());
                    user.setName(userApiRequest.getName());
                    user.setHp(userApiRequest.getHp());
                    user.setEmail(userApiRequest.getEmail());
                    return user;
                }).map(user -> usersRepository.save(user))
                .map(user -> response(user))
                .map(Header::OK)
                .orElseGet(()->Header.ERROR("데이터 없음")
                );
    }

    @Override
    public Header delete(Long id) {
        /*내코드
        Optional<Users> users = baseRepository.findById(id);
        users.ifPresent(
                selectUsers ->{
                    baseRepository.delete(selectUsers);
                }
        );
        return null;
         */
        Optional<Users> users = baseRepository.findById(id);
        return users.map(user->{
            baseRepository.delete(user);
            return Header.OK();
        }).orElseGet(()->Header.ERROR("데이터 없음"));
    }
}

0개의 댓글