티스토리 뷰

 

[ 1. 게시판 만들기 - 비지니스 계층 만들기 : Service ]

 

[ + Mapper은 전 게시물의 mapper을 그대로 사용하였습니다. ]

 

[ 1 - 1. Service Interface 만들기 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.service;

import java.util.List;

import org.zerock.myapp.domain.BoardVO;
import org.zerock.myapp.exception.ServiceException;

// + 롬복은 인터페이스에서 사용이 불가능하다.
// + 비지니스 로직은 Service에서 구현되어야 한다.
public interface BoardService {
	
	// + 1. 게시파 전체 목록을 조회하여 리스트로 반환해주는 메소드
	public abstract List <BoardVO> getAllList() throws ServiceException;
	
	// + 2. 게시판에서 특정 게시물 조회
	public abstract BoardVO get(Integer bno) throws ServiceException;
	
	// + 3. 게시판에서 게시물 삭제 요청 처리
	public abstract Integer remove(Integer bno) throws ServiceException;
	
	// + 4. 게시판에서 게시물 수정 요청 처리
	public abstract boolean update(BoardVO vo) throws ServiceException;
	
	// + 5. 게시판에서 새로운 게시물 추가 요청 처리
	public abstract Integer add(BoardVO vo) throws ServiceException;
	
	// + 6. 게시판에서 새로운 게시물 추가 요청 처리 2
	public abstract boolean addAuto(BoardVO vo) throws ServiceException;

} // end interface

 

[ 1 - 2. Service Class 만들기 - mapper 주입 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.service;

import java.util.List;
import java.util.Objects;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zerock.myapp.domain.BoardVO;
import org.zerock.myapp.exception.DAOException;
import org.zerock.myapp.exception.ServiceException;
import org.zerock.myapp.mapper.BoardMapper;

import lombok.Setter;
import lombok.extern.log4j.Log4j2;


@Log4j2

@Service
public class BoardServiceImpl implements BoardService, InitializingBean, DisposableBean {
// + InitializingBean는 빈 객체가 만들어진 직후에, DisposableBean는 빈이 파괴되기 직전에
	
	// ===========================================================
	
	@Setter(onMethod_= {@Autowired})
	private BoardMapper mapper;
	
	// ===========================================================
	// + 전체 게시글 조회
	// ===========================================================

	@Override
	public List<BoardVO> getAllList() throws ServiceException {
		// + 핵심 비지니스 로직 : DB 게시판 테이블을 조회하여, 게시글 전체목록을 얻어내 Model로 반환
		// + 하지만, Model은 Controller에서만 Model을 생성할 수 있다.
		// + 그러기 위해서는 mapper을 빈으로 가져와야 한다.
		
		log.trace("getAllList() invoked.");
		
		try {
			
			Objects.requireNonNull(this.mapper);
			return this.mapper.selectAllList();
			
		} catch ( DAOException e ) {
			throw new ServiceException(e);
		} // try - catch

	} // getAllList
	
	// ===========================================================
	// + 특정 게시글 조회
	// ===========================================================
	
	@Override
	public BoardVO get(Integer bno) throws ServiceException {
		
		log.trace("get() invoked.");
		
		try {
			return this.mapper.select(bno);
		} catch (DAOException e) {
			throw new ServiceException(e);
		} // try - catch
		
	} // get
	
	// ===========================================================
	// + 특정 게시글 삭제
	// ===========================================================
	
	@Override
	public Integer remove(Integer bno) throws ServiceException {
		
		log.trace("getAllList() invoked.");
		
		try {
			return this.mapper.delete(bno);
		} catch (DAOException e) {
			throw new ServiceException(e);
		} // try - catch
		
	} // remove
	
	// ===========================================================
	// + 게시물 추가 ( bno도 지정하는 버전 )
	// ===========================================================
	
	@Override
	public Integer add(BoardVO vo) throws ServiceException {
		
		log.trace("getAllList() invoked.");
		
		try {
			return this.mapper.insert(vo);
		} catch (DAOException e) {
			throw new ServiceException(e);
		} // try - catch
		
	} // add
	
	// ===========================================================
	// + 게시물 추가 2 ( bno를 시퀀스가 해주는 버전 )
	// ===========================================================

	@Override
	public boolean addAuto(BoardVO vo) throws ServiceException {
		
		log.trace("getAllList() invoked.");

		try {
			return this.mapper.insertSelectKey(vo) == 1;
		} catch (DAOException e) {
			throw new ServiceException(e);
		} // try - catch
		
	} // assAuto
	
	// ===========================================================
	// + 게시물 수정
	// ===========================================================
	
	@Override
	public boolean update(BoardVO vo) throws ServiceException {
		
		log.trace("update() invoked.");
		
		try {
			return this.mapper.update(vo) == 1;
		} catch (DAOException e) {
			throw new ServiceException(e);
		} // try - catch
		
	} // update
	
	// ===========================================================
	// + destroy : 후처리
	// ===========================================================

	@Override
	public void destroy() throws Exception {
		log.trace("destroy() invoked.");
		
	} // DisposableBean : destroy ( 후처리 작업 )
	
	// ===========================================================
	// + afterPropertiesSet : 필드의 의존성 주입이 정삭적인지 체크
	// ===========================================================

	@Override
	public void afterPropertiesSet() throws Exception {
		log.trace("afterPropertiesSet() invoked.");
		
		// + 의존성 주입 체크
		Objects.requireNonNull(this.mapper);
		log.trace("\t + this.mapper : {}", this.mapper);
		
	} // InitializingBean : afterPropertiesSet ( 전처리 작업)
	
	// ===========================================================

} // end class

 

[ 1 - 3. Test 하기 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.service;

import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.zerock.myapp.domain.BoardVO;
import org.zerock.myapp.exception.ServiceException;

import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;

@Log4j2
@NoArgsConstructor

// JUNIT 5 버전
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "file:src/main/webapp/**/spring/**/*-context.xml")

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BoardServiceTests {
	
	// =====================================================
	
	@Setter(onMethod_= {@Autowired})
	private BoardService service;
	
	// =====================================================
	
	@BeforeAll
	void beforeAll() {
		log.trace("beforeAll() invoked.");
		Objects.requireNonNull(this.service);
		log.trace("\t + this.service : {}", this.service);
	} // beforeAll
	
	// =====================================================
	// + 1. 게시물 전체 조회
	// =====================================================
	
	@Disabled
	@Test
	@Order(1)
	@DisplayName("1. test getAllList")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void testgetAllList() throws ServiceException {
		
		log.trace("testgetAllList() invoked.");
		
		this.service.getAllList().forEach(log::info);
		
	} // testgetAllList
	
	// =====================================================
	// + 2. 특정 게시글 조회
	// =====================================================
	
	@Disabled
	@Test
	@Order(2)
	@DisplayName("2. test Get")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void testGet() throws ServiceException {
		
		log.trace("testGet() invoked.");
		
		int bno = 77;
		
		BoardVO vo = this.service.get(bno);
		assertNotNull(vo);
		
		log.info("\t + vo : {}", vo);
		
	} // testGet
	
	// =====================================================
	// + 3. 특정 게시물 삭제
	// =====================================================
	
	@Disabled
	@Test
	@Order(3)
	@DisplayName("3. test Remove")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void testRemove() throws ServiceException {
		
		log.trace("testRemove() invoked.");
		
		int bno = 7;
		int affectedLine = this.service.remove(bno);
		
		log.info("\t + affectedLine : {}", affectedLine);
		
	} // testRemove
	
	// =====================================================
	// + 4. 게시글 추가 1
	// =====================================================
	
	@Disabled
	@Test
	@Order(4)
	@DisplayName("4. test add")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void testAdd() throws ServiceException {
		
		log.trace("testAdd() invoked.");
		
		BoardVO vo = new BoardVO ( 678, "WOW", "WOWOWOW", "WOWW");
		
		int affectedLine = this.service.add(vo);
		log.info("\t + affectedLine : {}", affectedLine);
		
	} // testAdd
	
	// =====================================================
	// + 5. 게시글 추가 2 (****)
	// =====================================================
	
	// @Disabled
	@Test
	@Order(5)
	@DisplayName("5. test AddAuto")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void testAddAuto() throws ServiceException {
		
		log.trace("testAddAuto() invoked.");
		
		BoardVO vo = new BoardVO ( null, "AAAAAA", "BBBBB", "CCCC");
		
		if ( this.service.addAuto(vo) ) {
			log.info("\t + New Board Registered.");
			log.info("\t + vo : {}", vo);
		} else {
			log.info("\t + NO Board Registered.");
		} // if - else
		
	} // testAddAuto
	
	// =====================================================
	// + 6. 게시글 수정 (****)
	// =====================================================
	
	// @Disabled
	@Test
	@Order(6)
	@DisplayName("6. test Update")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void testUpdate() throws ServiceException {
		
		log.trace("testUpdate() invoked.");
		
		BoardVO vo = new BoardVO ( 10, "AAAAAA", "BBBBB", "CCCC");
		
		if ( this.service.update(vo) ) {
			log.info("\t + Board Update!!!");
			log.info("\t + vo : {}", vo);
		} else {
			log.info("\t + NO Update.");
		} // if - else
		
	} // testUpdate

} // end class

[ 2. 게시판 만들기 - 프레젠 테이션 계층 ]

 

[ + mapper와 service는 위와 동일한 것을 사용하고 있습니다. ]

 

[ 2 - 1. Controller Exception 생성 - 컨트롤러에서 발생하는 예외처리 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.exception;


// + 프레젠테이션 계층의 모든 종류의 Controller 구현에서 발생하는 예외를 의미
public class ControllerException extends Exception {
	private static final long serialVersionUID = 1L;

	public ControllerException(String message) {
		super(message);
	} // constructor
	
	public ControllerException(Exception e) {
		super(e);
	} //constructor

} // end class

 

[ 2 - 2. Controller 생성 - service 주입 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.zerock.myapp.domain.BoardVO;
import org.zerock.myapp.exception.ControllerException;
import org.zerock.myapp.service.BoardService;

import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@Controller
@RequestMapping("/board/*")	// 기본 URI
public class BoardController implements InitializingBean {
	
	// + Bean 의존성 주입
	// + 자동 의존성 주입 발생 : (1) 주입받을 필드가 1개 (2) 이 필드를 매개변수로 가지는 생성자
	// + 위와 같은 상황일 때에는 따로 주입 시그널을 보내지 않아도 자동으로 주입된다.
	@Setter(onMethod_= {@Autowired})
	private BoardService boardService;
	
	// ===============================================
	// + 1. 게시판 목록조회 요청 처리 핸들러 메소드 
	// ===============================================
	
	@GetMapping("/list")	// 상세 URI
	public void list (Model model) throws ControllerException {
		log.info("list({}) invoked.", model);
		
		try {
			
			// + 목록 조회하는 service
			List<BoardVO> list = this.boardService.getAllList();
			
			// + 아래와 같은 방법 외에도 model이 아닌 Map으로 받아서, 
			// + model에 저장하는 것이 아니라 Map에 저장하는 방법도 있다.
			// Map<String, Object> map = new HashMap<>();
			// map.put("__LIST__", list);
			
			// + 리스트가 비어있지 않을 때 model로 바인딩
			if ( list != null ) {
				
				model.addAttribute("__LIST__",list);
				// + model은 Request Scope에 저장하게 되는데,
				// + 이때 공유 영역에서는 NULL을 저장하지 않는다.
				// + 그렇기에 이 경우 사실 if문은 필요 없다.
				
				list.forEach(log::info);
				
			} // if
			
		} catch(Exception e) {
			throw new ControllerException(e);
		} // try - catch : ServiceException을 ControllerException으로
		
	} // list

	// ===============================================
	// + 선처리
	// ===============================================
	@Override
	public void afterPropertiesSet() throws Exception {
		
		log.trace("afterPropertiesSet() invoked.");
		
		// 필드에 의존성이 잘 주입 되었는지 확인한다.
		Objects.requireNonNull(this.boardService);
		log.info("\t + this.boardService : {}", this.boardService);
		
	} // afterPropertiesSet

} // end class

 

[ 2 - 3. Controller에서 return해주는 것에 맞는 view 준비 ]

 

더보기

[ + 코드 보기 ]

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>View - bord/list.jsp</title>
</head>

<body>

    <h1>/WEB-INF/views/bord/list.jsp</h1>
    <hr>

    <h1> I AM bord/list!!!</h1>
    
    <h7> ${__LIST__}</h7>
    
</body>

</html>

 

 

 

 

728x90
댓글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
최근에 올라온 글
Total
Today
Yesterday
공지사항