[spring] 비즈니스 계층

업데이트:



비즈니스 계층은 고객의 요구사항을 반영하는 계층으로 프레젠테이션 계층과 영속 계층의 중간 다리 역할을 한다. 영속 계층은 데이터베이스를 기준으로 해서 설계를 나눠 구현하지만, 비즈니스 계층은 로직을 기준으로 처리한다.



비즈니스 계층의 설정

  • 패키지, 파일 생성
    비즈니스1
// 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 bardVO);
	
	public boolean remove(Long bno);
	
	public List<BoardVO > getList();
}


BoardService 메서드를 설계할 때 메서드 이름은 현실적인 로직의 이름을 붙여 사용는게 관례이다.

// BoardService

package org.zerock.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.zerock.domain.BoardVO;
import org.zerock.mapper.BoardMapper;

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

@Log4j
@Service
@AllArgsConstructor
public class BoardServiceImpl implements BoardService {
	
	//spring 4.3 이상에서 자동 처리
	private BoardMapper mapper;
	
	@Override
	public void register(BoardVO board) {
		
	}
}


BoardServiceImpl 클래스에서 가장 중요한 부분은 @Service라는 어노테이션이다. @Service는 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해 사용한다.





스프링의 서비스 객체 설명

인터페이스와 구현 클래스를 작성했다.

  • root-context.xml Namespaces
    비즈니즈2
<context:component-scan base-package="org.zerock.service"></context:component-scan>





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

테스트를 진행하기 위해 아래 테스트 클래스를 생성한다.

비즈니즈3


package org.zerock.service;

import static org.junit.Assert.assertNotNull;

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/wabapp/WEB-INF/spring/root_context.xml")
@Log4j

public class BoardServiceTests {
	
	@Setter(onMethod_ = {@Autowired})
	private BoardService service;
	
	private void testExist(){
		log.info(service);
		assertNotNull(service);
	}
}



작성후 BoardService 객체가 제대로 주입이 가능한지 확인하는 작업으로 시작된다. 만약 정상적으로 주입이 되었다면 다음과 같은 로그가 출력된다.

INFO : org.zerock.service.BoardServiceTests - org.zerock.service.BoardServiceImpl@5d8bafa9
INFO : org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@18eed359: startup date [Fri May 28 21:43:16 KST 2021]; root of context hierarchy
INFO : com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...


등록 작업 구현과 테스트

등록 작업은 BoardServiceImpl에서 파라미터로 전달되는 BoardVO 타입의 객체를 BoardMapper를 통해서 처리한다.

// BoardServiceImpl 수정

@Override
public void register(BoardVO board) {
    log.info("register.....:" + board);
    mapper.insertSelectKey(board);
}


// BoardServiceTests 일부
@Test
public void testRegister() {
    BoardVO board = new BoardVO();
    board.setTitle("새로 작성하는 글");
    board.setContent("새로 작성하는 글");
    board.setWriter("newbie");
    
    service.register(board);
    
    log.info("생성된 게시글 번호 : " + board.getBno());
}


INFO : org.zerock.service.BoardServiceTests - 생성된 게시글 번호 : 19





조회 작업의 구현과 테스트

// BoardServiceImpl 일부

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


// 테스트 코드 클래스

@Test
public void testGet() {
    log.info(service.get(1L));
}

비즈니스4





삭제/수정 구현

삭제/수정 메서드의 리턴 타입을 void로 설계할 수도 있지만 더 엄격하게 처리하기 위해 Boolean 타입으로 처리한다.

//BoardServiceImpl 클래스 

@Override
public boolean modify(BoardVO board) {
    log.info("modify..... " + board);
    return mapper.update(board) == 1;
}

@Override
public boolean remove(Long bno) {
    log.info("remove....... " + bno);
    return mapper.delete(bno) == 1;
}


// BoardServiceTests 클래스

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")
@Log4j
public class BoardServiceTests {
	
	@Setter(onMethod_ = {@Autowired})
	private BoardService service;
	
	@Test
	public void testExist(){
		log.info(service);
		assertNotNull(service);
	}
	
	@Test
	public void testRegister() {
		BoardVO board = new BoardVO();
		board.setTitle("새로 작성하는 글");
		board.setContent("새로 작성하는 글");
		board.setWriter("newbie");
		
		service.register(board);
		
		log.info("생성된 게시글 번호 : " + board.getBno());
	}
	
	@Test
	public void testGet() {
		log.info(service.get(1L));
	}
	
	@Test
	public void testDelete() {
		
		// 게시물 번호의 존재 여부를 알고 확인하고 테스트 
		log.info("REMOVE RESULT : " + service.remove(2L));
	}
	
	@Test
	public void testUpdate() {
		BoardVO board= service.get(1L);
	if(board == null) return;
	
	board.setTitle("제목 수정");
	log.info("MODIFY RESULT : " + service.modify(board));
	}
}


testDelete()의 경우에는 해당 게시물이 존재할 때 true를 반환하는 것을 확인할 수 있다. testUpdate의 경우에는 특정한 게시물을 먼저 조회하고, title 값을 수정한 후 이후를 업데이트한다.







  • 참고 : 코드로 배우는 스프링 웹 프로젝트

태그:

카테고리:

업데이트:

댓글남기기