티스토리 뷰

Spring은 어노테이션 기반 설정을 제공함으로써 과도한 XML 설정으로 인한 문제를 해결할 수 있도록 한다. 

마찬가지로, 이전에 bean 객체로 등록한 모든 클래스들을 어노테이션 설정으로 선언하여 사용할 수 있다는 것이다.

 

바로 들어가보자.


우선, action-servlet.xml 파일에서 이전에 등록한 모든 HandlerMapping, viewResolver, Controller 를 지운 뒤, 어노테이션을 사용할 수 있도록 context:component-scan 을 걸어준다.

 

◎action-servlet.xml

<?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"
	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.2.xsd">

	<context:component-scan base-package="com.choonham.view"></context:component-scan>
	
</beans>

 

 

각 컨트롤러 선언부 위에 @Controller 어노테이션을 작성하여 컨테이너가 컨트롤러 객체를 자동 생성하게 할 수 있다.

@Controller 어노테이션을 작성했기 때문에, 더 이상 Controller인터페이스를 구현받아서 컨트롤러 클래스를 작성할 수 없다. 

따라서 다음과 같이 간단하게 기존 자바 클래스 생성 방식(POJO 방식)으로 컨트롤러를 작성한다.

 

◎DeleteBoardController.java (기존 xml 등록 방식)

package com.freeflux.view.board;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

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



public class DeleteBoardController implements Controller {

	public DeleteBoardController() {
	}

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{
		System.out.println("삭제 처리");
		String seq=request.getParameter("seq");
		
		BoardVO vo=new BoardVO();
		vo.setSeq(Integer.parseInt(seq));
		
		BoardDAO boardDAO=new BoardDAO();
		boardDAO.deleteBoard(vo);
		
		ModelAndView mav= new ModelAndView();
		mav.setViewName("redirect:getBoardList.do");
		return  mav;

	}

}

 

◎DeleteBoardController.java (어노테이션 방식)

package com.freeflux.view.board;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;

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


@Controller
public class DeleteBoardController{

	public DeleteBoardController() {
	}

	public void deleteBoard(HttpServletRequest request){
		System.out.println("삭제 처리");
		String seq=request.getParameter("seq");
		
		BoardVO vo=new BoardVO();
		vo.setSeq(Integer.parseInt(seq));
		
		BoardDAO boardDAO=new BoardDAO();
		boardDAO.deleteBoard(vo);
	}

}

하지만 이렇게 구성하면, xml 자체에서 mapping 코드 자체가 삭제되었기 때문에 "/deleteBoard.do" 요청에 대하여 메서드가 호출되게 할 수가 없다. 

 

이 경우, @RequestMapping 어노테이션을 이용하여 설정해주면 된다.

 

◎DeleteBoardController.java (어노테이션 방식)

package com.freeflux.view.board;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

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


@Controller
public class DeleteBoardController{

	public DeleteBoardController() {
	}
	
	@RequestMapping(value="/deleteBoard.do")
	public void deleteBoard(HttpServletRequest request){
		System.out.println("삭제 처리");
		String seq=request.getParameter("seq");
		
		BoardVO vo=new BoardVO();
		vo.setSeq(Integer.parseInt(seq));
		
		BoardDAO boardDAO=new BoardDAO();
		boardDAO.deleteBoard(vo);
	}

}

위와 같이 @RequestMapping을 사용하면 클라이언트의 요청 정보를 굳이 request.getParameter로 받지 않아도 내부 Command객체(VO) 가 알아서 Mapping을 모두 처리해준다. 

 

즉, 아래 코드와 같이 Request 객체를 인자로 받는 것이 아닌, Command 객체를 인자로 받게 되면, 스프링 컨테이너가 해당 메서드를 호출할 때, 사용자의 입력 값들을 자동으로 set 해준 뒤 넘겨준다. (매우 편리)

 

◎DeleteBoardController.java (어노테이션 방식)

package com.freeflux.view.board;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

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


@Controller
public class DeleteBoardController{

	public DeleteBoardController() {
	}
	
	@RequestMapping(value="/deleteBoard.do")
	public void deleteBoard(BoardVO vo){
		System.out.println("삭제 처리");

		BoardDAO boardDAO=new BoardDAO();
		boardDAO.deleteBoard(vo);
	}

}

 

즉, 위와 같이 코드를 짜서 실행해도 전혀 문제가 없다는 것이다.

 

하지만 위 코드의 문제점은 리턴 타입이 없다는 것이다. 이는 요청을 받을 수는 있겠지만, 절대로 요청을 내보낼 수는 없다. 

 

따라서 어떤 요청을 보낼 지를 명시해줘야 한다.

 

◎DeleteBoardController.java (어노테이션 방식)

package com.freeflux.view.board;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

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

@Controller
public class InsertBoardController{

	public InsertBoardController() {
	}
	
	@RequestMapping(value = "/insertBoard.do")
	 public String insertBoard(BoardVO vo){
		System.out.println("글 등록 처리");
		
		BoardDAO boardDAO=new BoardDAO();
		boardDAO.insertBoard(vo);
		
		//redirect 접두사 없이 사용할 경우 포워딩 방식
		return "redirect:getBoardList.do";

	}

}

리턴 타입이 반드시 String일 필요는 없지만, 편의를 위해 사용했다. (ModelAndView객체를 사용해도 무관)

또한 DAO객체도 매개변수로 받아서 사용할 수도 있다.

 

다음 코드와 같이 사용해도 무관하지만, POJO 방식으로 유지하는 것이 핵심이다.

 

◎GetBoardListController.java (어노테이션 방식), ModelAndView 반환

package com.freeflux.view.board;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

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

@Controller
public class GetBoardListController{

	public GetBoardListController() {
	}
	
	@RequestMapping(value= "/getBoardList.do")
	public ModelAndView getBoardList(BoardVO vo, BoardDAO dao, ModelAndView mav) {
		System.out.println("목록 처리");
        
		List<BoardVO> boardList= dao.getBoardList(vo);
		
		mav.addObject("boardList", boardList);
		mav.setViewName("getBoardList.jsp");
		return mav;
	}

}

 

◎GetBoardListController.java (어노테이션 방식), String 반환

package com.freeflux.view.board;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

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

@Controller
public class GetBoardListController{

	public GetBoardListController() {
	}
	
	@RequestMapping(value= "/getBoardList.do")
	public String getBoardList(BoardVO vo, BoardDAO dao, Model model) {
		System.out.println("목록 처리");
        
		List<BoardVO> boardList= dao.getBoardList(vo);
		
		model.addAttribute("boardList", boardList);
		
		return "getBoardList.jsp";
	}

}

또한 servlet 클래스 파일에서 사용했던 것과 같이, 해당 메서드가 Get 요청을 받아서 수행되는 메서드인지, post 요청을 받아서 수행되는 건지 아래 코드와 같이 method = RequestMethod.GET, POST 인자를 통해 설정할 수 있다.

 

◎LoginController.java

package com.freeflux.view.user;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.freeflux.biz.user.UserVO;
import com.freeflux.biz.user.impl.UserDAO;

@Controller
public class LoginController{

	public LoginController() {
	}

	@RequestMapping(value = "login.do", method = RequestMethod.POST)
	public String login(UserVO vo, UserDAO dao) {
		
		UserVO user = dao.getUser(vo);

		// 3. 화면 네비게이션
		ModelAndView mav = new ModelAndView(); 
		
		if (user != null) {
			return "redirect:getBoardList.do";    // /WEB-INF/board/getBoardList.do.jsp
			
		} else {
			return "login.jsp";             // /WEB-INF/board/login.jsp
		}
		//  redirect: 은 ViewResolver가 설정되어 있더라도 이를 무시하고 리다이렉트!!!
	}

}

 


Controller 에서 Command 객체로 넘겨준 값은 jsp에서 jstl을 이용해 사용할 수 있는데, 이때의 변수명은 클래스명의 맨 앞글자가 소문자로 바뀐 형태이다.

 

ex) UserVO -> userVO

 

혹은 개발자가 @ModelAttribute()를 이용하여 이를 직접 지정할수도 있다.

 

◎LoginController.java

package com.freeflux.view.user;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.freeflux.biz.user.UserVO;
import com.freeflux.biz.user.impl.UserDAO;

@Controller
public class LoginController{

	public LoginController() {
	}

	@RequestMapping(value = "login.do", method = RequestMethod.POST)
	public String login(@ModelAttribute("user") UserVO vo, UserDAO dao) {
		
		UserVO user = dao.getUser(vo);

		// 3. 화면 네비게이션
		ModelAndView mav = new ModelAndView(); 
		
		if (user != null) {
			return "redirect:getBoardList.do";    // /WEB-INF/board/getBoardList.do.jsp
			
		} else {
			return "login.jsp";             // /WEB-INF/board/login.jsp
		}
		//  redirect: 은 ViewResolver가 설정되어 있더라도 이를 무시하고 리다이렉트!!!
	}

}

xml 문서를 이용하여 설정하는 경우: 

 - Controller가 수시로 변경되어야 하는 경우(솔루션 개발)

 - 설정 방법

 

어노테이션을 이용하여 설정하는 경우:

 - Controller가 고정되어서 사용되는 경우(특정 기업에 대한 프로젝트 작업)

 

Comments