해당 포스팅의 목차는 다음과 같다.
1. @Controller
1) 어노테이션 사용 준비
2) 어노테이션 달기
2. @RequestMapping
1) Command객체
2) output 작업 방법_String
3) output 작업 방법_ModelAndView
3. controller로직 합치기
이전 포스팅까지의 내용을 참고하여 스프링 컨테이너가 참조하는 XML파일의 설정 정보를 @로 변경할 수 있으며, 해당 작업을 통해 command객체에 대한 이해를 도울 수 있다.
현재 포스팅까지의 내용이 반영된 코드 링크를 첨부하였다.
https://github.com/Hamjeonghui/Spring_MVC_1.git
GitHub - Hamjeonghui/Spring_MVC_1
Contribute to Hamjeonghui/Spring_MVC_1 development by creating an account on GitHub.
github.com
1. @Controller
1) 어노테이션 사용 준비
스프링 컨테이너가 어노테이션을 참조할 수 있도록 하기 위해서는 우선 name space의 설정과, 필요한 태그 명령어가 있다.
name space탭에서 context를 선택 후 저장한다.
4번 라인의 내용이 추가되며, context:component-scan>태그를 활용하여 어노테이션을 사용할 패키지를 참조한다. 작업 구조상 DS, HM & VR, C를 초기화 하여야하는데, DS는 이미 web.xml파일에서 <bean>으로 초기화 진행, HM & VR는 스프링 컨테이너 자체가 해당 클래스들을 내부적으로 초기화해주는 상황이기 때문에 실질적으로 초기화를 진행해야 할 클래스는 Controller 뿐이게 된다.
작성된 코드는 다음과 같다.
<context:component-scan base-package="com.test.app.controller" />
<!-- base-package="참조할 패키지" -->
2) 어노테이션 달기
위의 작업이 끝났다면, 각 Controller클래스의 초기화와 DI를 진행한다. 가장 처음으로 초기화를 위해 클래스 최상단에 @Component를 달아줄 수 있는데, @Service나 @Resitory와 마찬가지로 @Component하위에 속해있는 @Controller라는 어노테이션을 통해 스프링 컨테이너 내부적으로 참조가 용이해지도록 한다.
미완성 코드의 첨부(VER.1)
package com.test.app.controller.board;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import com.test.app.board.BoardVO;
import com.test.app.board.impl.BoardDAO;
@Controller
public class InsertBoardController {
public void insertBoard() {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
}
/*
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
ModelAndView mav=new ModelAndView();
mav.setViewName("redirect:main.do");
return mav;
}
*/
}
위 코드를 확인해보면, implements Controller가 삭제된 것을 확인할 수 있는데, @Controller라는 어노테이션을 사용함과 동시에 스프링 컨테이너는 해당 클래스가 이미 Controller객체임을 알게 되므로 굳이 스프링 컨테이너에게 두 번 알릴 필요가 없어지게 되면서 삭제 단계를 거치는 것이다.
*이때, import된 클래스를 잘 확인한다.*
import org.springframework.web.servlet.mvc.Controller;
=> implements Controller했을때의 import
import org.springframework.stereotype.Controller;
=> @Controller했을때의 import
implements를 삭제함에 따라 메서드 강제성 또한 제거되기 때문에 해당 작업에서 완전한 POJO가 되었다고도 표현한다. (강제성이 없고, 그로인해 인자로 사용되던 request, response의 임폴트가 제거되기 때문)
메서드명의 강제 또한 없으니 그냥 기존 로직(handleRequest메서드)에서 핵심으로 사용하던 dao의 비즈니스 메서드명을 참고하여 메서드를 생성하였다.
2. @RequestMapping
위에서 초기화가 끝났으니, 현재 단계에서 매핑을 진행한다. (요청에 맞는 처리로직을 한세트로 묶어주기!) 해당 작업 또한 어노테이션으로 진행된다.
1) Command객체
사용자의 요청.do에 따라 그에 해당되는 메서드가 수행되어야한다. 이 내용을 담은 어노테이션은 다음과 같다.
@RequestMapping(value="/어쩌구.do")
위의 어노테이션을 value의 요청에 따라 수행될 메서드 상단에 배치시키면 된다.
package com.test.app.controller.board;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import com.test.app.board.BoardVO;
import com.test.app.board.impl.BoardDAO;
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
public void insertBoard() {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
}
/*
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
ModelAndView mav=new ModelAndView();
mav.setViewName("redirect:main.do");
return mav;
}
*/
}
----★여기서부터 핵심★----
Command 객체는 Controller 메소드 매개변수로 받은 VO 객체라고 보면 된다. 즉, command객체는 VO이다.
더 자세한 내용은 아래의 링크를 통해 간단히 이해할 수 있다.
https://heewon26.tistory.com/4
Command 객체
Controller 객체에서 사용자의 요청(*.do)을 받을때 사용자가 입력하는 정보(이름,나이,성별등등)가 많거나 변경되는 상황 정보가 많으면 그만큼의 자바 코드가 필요해지며, 입력 정보가 변경될 때
heewon26.tistory.com
command객체를 활용함으로써 아래와 같은 이점이 내부적으로 발생하게 된다.
1) vo를 초기화(vo의 객체 생성)
2) request에 사용자가 입력한 값들을 추출해낼 수 있다.
3) vo의 setter를 자동호출하여, 2)에서 추출한 값을 매핑하여 저장할 수 있다.(vo.set어쩌구의 작업을 진행해준다는 얘기)
=> 이때, View에서 넘겨주는 name과 VO에서의 멤버변수명이 같아야한다.
즉, jsp로 대입해서 생각해보자면 command 객체 활용을 통해 <useBean>과 <setProperty>에 해당되는 내용이 자동으로 (내부에서) 진행된다는 의미이다.
사용 방법은 메서드에 인자로 사용할 객체를 두는 것이다. 해당 내용을 반영하여 코드를 작성하면 다음과 같다. 위의 코드와 같은 로직이므로 대조해서 보면 이해가 쉽다.
package com.test.app.controller.board;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.test.app.board.BoardVO;
import com.test.app.board.impl.BoardDAO;
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
public void insertBoard(BoardVO vo,BoardDAO boardDAO) {
boardDAO.insertBoard(vo);
}
/*
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
ModelAndView mav=new ModelAndView();
mav.setViewName("redirect:main.do");
return mav;
}
*/
}
현재까지의 코드로는 아직 해당 메서드의 가장 중요한 기능인 "다음으로 갈 경로와 모델에서 건네받은 정보 반환"이 이루어지지 않고 있다. 바로 다음 내용에서 추가로 알아보자.
2) output 작업 방법_String
view에 건네줄 데이터가 없어 경로만 전달할때 주로 사용되는 방법이다.
package com.test.app.controller.board;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.test.app.board.BoardVO;
import com.test.app.board.impl.BoardDAO;
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
public String insertBoard(BoardVO vo,BoardDAO boardDAO) {
boardDAO.insertBoard(vo);
return "redirect:main.do";
}
/*
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
ModelAndView mav=new ModelAndView();
mav.setViewName("redirect:main.do");
return mav;
}
*/
}
3) output 작업 방법_ModelAndView
view에 돌려줄 데이터가 있어 경로와 데이터를 같이 반환해야하는 경우 주로 사용된다.(경로만을 반환할때도 사용 가능)
package com.test.app.controller.board;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.test.app.board.BoardVO;
import com.test.app.board.impl.BoardDAO;
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
public ModelAndView insertBoard(BoardVO vo,BoardDAO boardDAO,ModelAndView mav) {
boardDAO.insertBoard(vo);
mav.setViewName("redirect:main.do");
//데이터는 mav.addObject("어쩌구", 저쩌구);를 통해 전달 가능
return mav;
}
/*
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
String content=request.getParameter("content");
String title=request.getParameter("title");
String writer=request.getParameter("writer");
BoardVO vo=new BoardVO();
vo.setContent(content);
vo.setTitle(title);
vo.setWriter(writer);
BoardDAO boardDAO=new BoardDAO();
boardDAO.insertBoard(vo);
ModelAndView mav=new ModelAndView();
mav.setViewName("redirect:main.do");
return mav;
}
*/
}
3. controller로직 합치기
위의 작업들로 인해 이전에는 Controller라는 객체 하나로 모든 Controller류(요청 처리 로직을 담은 class)의 메서드를 사용할 수 있었지만, implements가 제거된 현재 상태에서는 각 메서드를 사용하기 위해 각각의 Controller류의 객체화가 필요해지게 된다.
하지만 객체가 필요한 것이 아니라 그저 메서드의 사용만이 필요한 것이기에 모든 로직을 하나의 클래스 파일에 모아서 관리함으로써 여러개의 객체를 생성할 필요가 없어지게 된다.
예시 코드는 아래와 같다.
package com.test.app.controller.board;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.test.app.board.BoardVO;
import com.test.app.board.impl.BoardDAO;
@Controller
// 1. <bean> -> @Controller
// 2. implements Controller 필요없음 -> 제거
// 3. 메서드 강제 사라짐!!!
// 4. 완전한 POJO가 되었다!!!!!
// -> req,res,...가 존재하지않음 => 경량의 객체
public class BoardController { // 하나의 컨트롤러파일로 아래의 메서드들을 관리
@RequestMapping(value="/insertBoard.do") //이런 요청이 오면,
public String insertBoard(BoardVO vo,BoardDAO boardDAO) { //이 메서드를 사용
boardDAO.insertBoard(vo);
return "redirect:main.do";
}
@RequestMapping(value="/deleteBoard.do")
public String deleteBoard(BoardVO vo,BoardDAO boardDAO) {
boardDAO.deleteBoard(vo);
return "redirect:main.do";
}
@RequestMapping(value="/main.do")
public ModelAndView getBoardList(BoardVO vo, BoardDAO boardDAO, ModelAndView mav) {
List<BoardVO> datas=boardDAO.getBoardList(vo);
mav.addObject("datas", datas); // Model을 이용하여 전달할 정보를 저장!
mav.setViewName("main.jsp");
return mav;
}
@RequestMapping(value="/updateBoard.do")
public String updateBoard (BoardVO vo, BoardDAO boardDAO) {
boardDAO.updateBoard(vo);
return "redirect:main.do";
}
}
'Spring' 카테고리의 다른 글
[AOP] xml을 @로 바꾸기 : 횡단관심_aop(2) (0) | 2022.04.05 |
---|---|
[AOP] AOP개념의 이해 : 횡단관심_aop(1) (0) | 2022.04.04 |
[IoC] MVC패턴 이해 실습_2 : Spring제공 클래스 사용 (0) | 2022.03.31 |
[IoC] MVC패턴 이해 실습_1 (0) | 2022.03.30 |
[IoC] 스프링, DB연동_service (0) | 2022.03.29 |