Service 계층 이용하기

service계층

: 완충작용
직접 DAO를 쓰는 것이 아니라 service 계층을 통한다.

package com.springbook.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 org.springframework.web.servlet.ModelAndView;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
/*
@SessionAttributes
Request요청중에 board라는 이름의 객체가 Model에 저장되어있으면
그것을 Session에 저장해라
*/
@Controller
@SessionAttributes("board")
public class BoardController {
	
	@Autowired
	private BoardService boardService;
	
//	RequestMapping보다 먼저 적용되어서 아래 Map객체는 자동으로 Model에 저장되고
//	화면 이동시 전달되게 된다
	@ModelAttribute("conditionMap")
	public Map<String, String> searchConditionMap(){
		Map<String, String> conditionMap = new HashMap<String, String>();
		conditionMap.put("제목", "TITLE");
		conditionMap.put("내용", "CONTENT");
		return conditionMap;
	}

	@RequestMapping("/insertBoard.do")
	public String insertBoard(BoardVO vo) {
		boardService.insertBoard(vo);
		return "getBoardList.do";
	}
	
//	@ModelAttribute("board") BoardVO vo
//	board 이름의 객체를 찾아서 vo에 값을 담아줘
	@RequestMapping("/updateBoard.do")
	public String updateBoard(@ModelAttribute("board") BoardVO vo) {
		System.out.println(vo);
		boardService.updateBoard(vo);
		return "getBoardList.do";
	}
	
	@RequestMapping("/deleteBoard.do")
	public String deleteBoard(BoardVO vo) {
		boardService.deleteBoard(vo);
		return "getBoardList.do";
	}
	
	@RequestMapping("/getBoard.do")
	public String getBoard(BoardVO vo, Model model) {
		model.addAttribute("board", boardService.getBoard(vo));
		return "getBoard.jsp";
	}
	
	@RequestMapping("/getBoardList.do")
	public String getBoardList(@RequestParam(value="searchCondition",
					defaultValue="TITLE", required=false) String condition,
							   @RequestParam(value="searchKeyword",
					defaultValue="", required=false) String keyword
			, BoardVO vo, Model model) {
		System.out.println("검색 조건 : " + condition);
		System.out.println("검색 단어 : " + keyword);
		model.addAttribute("boardList", boardService.getBoardList(vo));
		return "getBoardList.jsp";
	}
}

그런데 boardService는 bean이 아니므로 no such bean이라는 오류가 발생한다.
해결방법에는 세가지가 있다.

1. 직접 대입

2. 경로 추가

service를 빈으로 만들던 applicationContext 파일을 presentation-layer 파일에 통합
-> 디스패처서블릿이 presentation 파일을 읽어 bean들을 생성하도록 기존의 application context파일을 presentation파일에 합친다

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<!-- annotation을 읽어서 bean을 생성 ( springbook.view 패키지의 컴포넌트들을 스캔해서 bean 생성 ) -->
	<context:component-scan base-package="com.springbook.view"></context:component-scan>
	
	<context:component-scan base-package="com.springbook.biz" />

	<!-- AOP 어노테이션 자동 인식 설정 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	
	<context:property-placeholder 
				location="classpath:config/database.properties"/>
	
	<!-- DataSource 설정 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
						destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- Transaction 설정 -->
	<bean id="txManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- Transaction Advice 설정 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="*"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<aop:pointcut id="txPointcut"
				expression="execution(* com.springbook.biz..*(..))"/>
		<aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice"/>
	</aop:config>
	
</beans>

biz패키지의 파일도 bean으로 만들게 된다

@Autowired 살리기

3. contextLoaderListener 이용

presentation파일을 원래대로 돌린다.
합쳐진 파일이라면 상관없지만, 파일이 다를 때는 board controller가 생성되려면 boardservice bean이 먼저 만들어져야 한다. 그럴 때 사용하기 좋은 것이 ContextLoaderListener이다.

web.xml


정리
two layer 아키텍쳐 (규모가 커지면 분리할 필요성이 생길 때 쓸 수 있다)
bean을 만드는 파일에는 2가지가 있었다.
application 파일과 presentation파일.
차이점 : 전자는 기존의 db, business, service와 같은 기본 객체들을 넣어놓은 곳
후자는 사용자 요청에 따른 controller를 주로 준비하는 곳

좋은 웹페이지 즐겨찾기