온 코딩

[Spring] (게시판 예제)프레젠테이션레이어와 비즈니스레이어 통합 본문

복습 ARCHIVE/모델별 프로젝트

[Spring] (게시판 예제)프레젠테이션레이어와 비즈니스레이어 통합

SummerON 2021. 6. 28. 10:53

Spring Framework 사용 시 Controller는 DAO를 직접 사용하면 안된다

1. DAO 교체 시 프리젠테이션 영역의 컨트롤러 내부 소스 코드를 일일이 수정해야 하는 번거로움 때문에 유지보수가 어려움

=> 따라서 Controller는 비즈니스 컴포넌트에게 요청을 하여 사용자 요청사항을 처리해야 한다.

 

* 프리젠테이션 영역은 사용자에게 배포가 되는 코드들이기 때문에 한번 작성한 코드는 수정하지 않을 목적으로 사용

다만, 서버를 사용할 경우 

 

프레젠테이션 영역에서 비즈니스 컴포넌트 사용하기 

@Autowired로 비즈니스 컴포넌트 의존성 주입 

Service 인터페이스를 구현받아 impl클래스를 만들어 DAO 접근 

프레젠테이션 영역에서 사용을 할 때는 인터페이스를 사용하여 Autowired를 통해 impl 자동 주입

서비스 구현 메서드에서만 AOP 설정 가능 (횡단 관심이기 때문에)

비즈니스 컴포넌트를 사용하는 클라이언트는 인터페이스의 추상 메서드를 호출하여 인터페이스를 구현한 Service 구현 객체의 메서드를 실행할 수 있다.

package com.hhw.view.board;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.hhw.biz.board.BoardVO;
import com.hhw.biz.board.impl.BoardDAO;

@Controller
@SessionAttributes("board")
public class BoardController {

	@Autowired
	private BoardService boardService;
    //BoardService를 구현받은 BoardServiceImpl 객체가 자동으로 생성됨
	
	public BoardController() {
	}
	
	//검색 조건 목록
	@ModelAttribute("conditionMap")
	public Map<String, String> searchConditionMap(){
		Map<String, String> conditionMap = new HashMap<String, String>();
		
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		
		return conditionMap;
	}
	
	// 글 등록
	@RequestMapping(value = "/insertBoard.do")
	public String insertBoard(BoardVO vo) {
		
		System.out.println("어노테이션 컨트롤러 : 글 등록 처리");
		// 1. 사용자 입력 정보 추출 - Command 로 자동 등록
		// 2. DB 연동처리
		boardService.insertBoard(vo);
		return "redirect:getBoardList.do";
	}// POJO 스타일

	// 글 수정
	@RequestMapping(value = "/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo) {
		System.out.println("어노테이션 컨트롤러 : 글 업데이트 처리");
//		System.out.println("글쓴이 : " + vo.getWriter()); //테스트코드
		boardService.updateBoard(vo);
		return "redirect:getBoardList.do";

	}

	// 글 삭제
	@RequestMapping(value = "/deleteBoard.do")
	public String deleteBoard(BoardVO vo) {
		System.out.println("어노테이션 컨트롤러 : 글 삭제 처리");
		boardService.deleteBoard(vo);
		return "redirect:getBoardList.do";

	}

	// 글 상세조회
	@RequestMapping(value = "/getBoard.do")
	public String getBoard(BoardVO vo, Model model) {
		System.out.println("어노테이션 컨트롤러 : 글 상세조회 처리");
		// 리턴 - 검색 결과는 model에 저장
		model.addAttribute("board", boardService.getBoard(vo)); // model정보 저장
		return "getBoard.jsp";
	}

	// 글 목록검색`
	@RequestMapping(value = "/getBoardList.do")
	public String getBoardList(@RequestParam(value = "searchCondition", defaultValue = "TITLE") String condition,
			@RequestParam(value = "searchKeyword", defaultValue = "") String keyword, BoardVO vo, Model model) {
		System.out.println("어노테이션 컨트롤러 : 글 목록 검색 처리");
		System.out.println(condition +"  :  "+ keyword);
		model.addAttribute("boardList", boardService.getBoardList(vo)); // model정보
																	// 저장
		return "getBoardList.jsp";
	}

}

 

2-Layered 아키텍쳐

일반적인 프레임 워크 기반의 웹 프로젝트는 두개의 레이어로 나누어 시스템 개발 

비즈니스 레이어 설정파일 : applicationContext.xml 

프레젠테이션 레이어 : presentation-layer.xml

web.xml에서 명령에 따라 DispatcherServlet이 생성되어  presentation-layer.xml 파일을 읽고 스프링컨테이너를 구동하면 Controller객체들이 생기며 프레젠테이션 영역 활용 가능, 이 때 applicationContext.xml 파일을 읽어 비즈니스 컴포넌트 생성하기 위해 ContextLoaderLisner 클래스 사용

 

ContextLoaderListener

비즈니스 컴포넌트 로딩에 대한 클래스를 등록하는 것

web.xml 파일에 등록

서블릿컨테이너가 web.xml 파일을 읽어서 구동 될 때 자동으로 메모리에 생성 됨 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  
  <filter>
  	<filter-name>characterEncoding</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
	<init-param>
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param> 	
  </filter>
  
  <filter-mapping>
  	<filter-name>characterEncoding</filter-name>
  	<url-pattern>*.do</url-pattern>
  </filter-mapping>
  
  <servlet>
    <description></description>
    <display-name>action</display-name>
    <servlet-name>action</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    	<param-name>contextConfigLocation</param-name>
    	<param-value>/WEB-INF/config/presentation-layer.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classPath:applicationContext.xml</param-value>
  </context-param>
  <listener>
  	<listener-class>
  		org.springframework.web.context.ContextLoaderListener
  	</listener-class>
  </listener>
  
</web-app>

* web.xml : 애플리케이션 전체에 대한 환경설정

1. 인코딩

2. DispatcherServlet 등록

  => presentation-layer.cxml : 컨트롤러 등록

3. 비지니스 컴포넌트 로딩에 대한 클래스 등록 (ContextLoaderLisner)

  => applicationContext.xml 

   - 비즈니스 컴포넌트 등록을 위한 스캔작업

   - 데이터베이스 처리에 관련된 등록작업

   - AOP에 관련된 등록작업 

 

스프링 컨테이너의 구동 순서와 관계

스프링 컨테이너의 구동 순서와 관계

  1. web.xml 파일을 로딩하여 서블릿 컨테이너 구동
  2. 서블릿 컨테이너는 ContextLoaderLisener 객체를 생성(Pre Loading) => Root 컨테이너
  3. 사용자가 .do 요청을 서버에 전달하면 DispatcherServlet객체 생성 
  4. DispatcherServlet 객체는 presentation-layer.xml 파일을 로딩하여 두번째 스프링 컨테이너 구동 
  5. 두번째 스프링 컨테이너에서 controller 객체 매모리에 생성 

역주행 , 의존성 주입 

 

Comments