개발/[Spring] 블로그 만들기

[코드로 배우는 스프링 웹 프로젝트] 9강. 비즈니스(Business) 계층 구현하기

ee2ee2 2021. 12. 30. 17:16
728x90
반응형

해당 프로젝트는 코드로 배우는 스프링 웹 프로젝트(개정판)을 기반으로 진행됩니다.


이번 시간에는 비즈니스 계층을 구현해본다.

비즈니스 계층이란, 고객의 요구사항을 반영하는 계층으로 프레젠테이션 계층과 영속 계층의 중간다리 역할을 한다. 로일반적으로 비즈니스 영역에 있는 객체들은 '서비스(Service)'라는 용어를 많이 사용한다.


1. 비즈니스 계층의 설정

비즈니스 계층을 위한 org.zerock.service 패키지를 생성하고, service 패키지 내 BoardService.java(Interface)와 BoardServiceImp.java (Class) 를 추가한다.

(설계를 할 때, 각 계층 간의 연결은 인터페이스를 이용해서 느슨한(loose) 결합을 하도록 한다.)

BoardService 인터페이스

package org.zerock.service;

import java.util.List;

import org.zerock.domain.BoardVO;

public interface BoardService {
	
	public void register(BoardVO board);
	
	public BoardVO get(Long bno);
	
	public boolean modify(BoardVO board);
	
	public boolean remove(Long bno);
	
	public List<BoardVO> getList();
}

 

BoardServiceImpl 클래스

package org.zerock.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zerock.domain.BoardVO;
import org.zerock.mapper.BoardMapper;

import lombok.AllArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j;


@Log4j
@Service //계층 구조상 주로 비즈니스 영역을 담당하는 객체를 표시하기 위함.
@AllArgsConstructor //모든 파라미터를 이용하는 생성자를 만들어 줌
public class BoardServiceImpl implements BoardService{

	@Setter(onMethod_ = @Autowired)
	private BoardMapper mapper;
	
	@Override
	public void register(BoardVO board) {
		...
	}
	
}

1.1 스프링의 서비스 객체 설정 (root-context.xml)

: 서비스 객체가 스프링의 빈으로 인식하기 위해서 root-context.xml에 @service 어노테이션이 있는 org.zerock.service 패키지를 스캔하도록 추가해야함.

 

root-context.xml의 네임스페이스 탭에서 context 항목추가

Source 탭으로 이동 후, 아래 소스 추가

<!-- Service 작성한 클래스를 스프링의 Bean으로 인식하기 위해 아래 패키지를 스캔하도록 추가 (@Service 어노테이션으로 구분) -->
<context:component-scan base-package="org.zerock.service"></context:component-scan>

 

JAVA 설정의 경우

@Configuration
@ComponentScan(basePackages = {"org.zerock.service"})
@MapperScan(basePackages = {"org.zerock.mapper"}) 
public class RootConfig {

... 생략

 


2. 비즈니스 계층의 구현과 테스트

테스트를 위해 'src/test/java' 밑에 org.zerock.service.BoardServiceTests 클래스를 작성한다.

 

BoardServiceTests.java

:  BoardService 객체가 제대로 주입이 가능한지 확인한다.

package org.zerock.service;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
//Java Config
//@ContextConfiguration(classes = {org.zerock.config.RootConfig.class})
@Log4j
public class BoardServiceTests {
	
	@Setter(onMethod_ = @Autowired)
	private BoardService service;
	
	
	@Test //BoardService 객체가 제대로 주입이 가능한지 확인하는 메소드
	public void testExist() {
		
		log.info("Service 객체 주입 확인 : " + service);
		assertNotNull(service);
	}
	
}

 

테스트 결과

 


객체 주입 테스트까지 완료되었으니, BoardService에 작성해놓았던 Interface들의 메소드를 완성해보자.

BoardServiceImple 클래스

package org.zerock.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zerock.domain.BoardVO;
import org.zerock.mapper.BoardMapper;

import lombok.AllArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j;


@Log4j
@Service
@AllArgsConstructor
public class BoardServiceImpl implements BoardService{

	@Setter(onMethod_ = @Autowired)
	private BoardMapper mapper;
	
	@Override
	public void register(BoardVO board) {
		log.info("register ... : " + board);
		mapper.insertSelectKey(board);
	}

	@Override
	public BoardVO get(Long bno) {
		log.info("get... : " + bno);
		return mapper.get(bno);
	}

	@Override
	public boolean modify(BoardVO board) {
		log.info("modify...." + board);
		return mapper.modify(board) == 1; //수정이 정상적으로 이뤄지면 1 반환
	}

	@Override
	public boolean remove(Long bno) {
		log.info("delete...." + bno);
		return mapper.remove(bno) == 1;	//삭제가 정상적으로 이뤄지면 1 반환
	}

	@Override
	public List<BoardVO> getList() {
		log.info("getList...");
		
		return mapper.getList();
	}

}

BoardServiceTests.java (테스트 코드)

package org.zerock.service;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.zerock.domain.BoardVO;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
//Java Config
//@ContextConfiguration(classes = {org.zerock.config.RootConfig.class})
@Log4j
public class BoardServiceTests {
	
	@Setter(onMethod_ = @Autowired)
	private BoardService service;
	
	
	@Test //BoardService 객체가 제대로 주입이 가능한지 확인하는 메소드
	public void testExist() {
		
		log.info("Service 객체 주입 확인 : " + service);
		assertNotNull(service);
	}
	
	@Test //service를 이용한 게시글 등록 테스트
	public void testRegister() {
		BoardVO board = new BoardVO();
		board.setTitle("새로운 글");
		board.setContent("새로운 내용");
		board.setWriter("newbie2");
		
		//service.register(board);
		
		//log.info("생성된 게시물의 번호 : " + board.getBno());
	}
	
	@Test //service를 이용한 전체 게시글 조회 테스트
	public void testgetList() {
		service.getList().forEach(board -> log.info(board));
	}
	
	@Test //service를 이용한 1개의 게시글 조회 테스트
	public void testget() {
		log.info(service.get(1L));
	}
	
	@Test //service를 이용한 1개의 게시글 삭제 테스트
	public void testDelete() {
		log.info("REMOVE RESULT : " + service.remove(34L));
	}
	
	@Test //service를 이용한 1개의 게시글 수정 테스트
	public void testModify() {
		BoardVO board = service.get(1L);
		
		//게시글이 없으면 종료
		if(board == null) {
			return;
		}
		
		board.setTitle("제목 수정 글입니다.");
		log.info("UPDATE RESULT : " + service.modify(board));
	}
}