day65) Spring-Controller 설계2:DispatcherServlet-servlet.xml @로 변경하기
이전 내용: https://code-learning.tistory.com/107
day64) Spring-Controller설계
Spring에서 제공하는 DispatcherServlet과 스프링 컨테이너를 활용하여 Controller를 설계해보자. [설계] NewFile.jsp에서 글을 쓰면 /WEB-INF/NewFile1.jsp(url로 접근할 수 없도록)에서 출력 [View] NewFile.jsp..
code-learning.tistory.com
위 게시글에서 DispatcherServlet-servlet.xml을 살펴보면 ViewResolver클래스를 호출하여 prefix와 suffix를 set해주는 과정, HandlerMapping클래스 호출하여 *.do action과 해당 클래스를 매핑하는 구문으로 이루어져 action이 많아질 수록 설정이 많아지는 것을 볼 수 있다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- DS를 위한 스프링 컨테이너를 위한 설정파일. init()이 자동호출될적에 필요 -->
<!-- DS 생성 -> init() 자동호출 -> DI -> 컨테이너가 하는 일 -> 설정파일(.xml) -> DS-servlet.xml -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
<!-- id를 써줄 것: 1. ~Resolver를 많이 써서 내부적으로 viewResolver를 쓸 수 있도록 설정해둠 -->
<!-- viewResolver를 통해 간다면 WEB-INF 경로도 접근가능해진다 -->
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- redirect: 가 붙지 않은 viewName을 보면, DS는 Mav객체에서 M정보를 추출, req객체에서 M정보를 저장해서 JSP포워딩 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/insert.do">next</prop>
</props>
</property>
</bean>
<bean class="com.test.app.controller.board..insertBoardController" id="insertBoard"></bean>
</beans>
이러한 점을 보완하기 위해 어노테이션을 사용하여 설정파일을 가볍게 하고자 한다.
[방법]
HandlerMapping과 ViewResolver는 SpringFramework가 제공하는 기능이므로 구현할 필요가 없다.
1.DispatcherServlet-servlet.xml에서 Namespaces -> context추가
2. component-scan을 통해 controller 클래스를 볼수 있도록 설정
<context:component-scan base-package="(controller패키지 경로)"/>
3.~controller 클래스 변경
-기존 insertBoardController.java
public class InsertBoardController implements Controller {
@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-1. @Controller 어노테이션 추가
- DispatcherServlet-servlet.xml에서 <bean>으로 ~Controller클래스 객체를 생성, 매핑파여 처리하던 부분을 @controller를 통해 처리한다.
- implements Controller가 필요없어지므로 삭제
- 메서드 강제가 없어져 Controller 인터페이스도 쓸모가 없어지므로 삭제
- 완전한 POJO가 되었다!!!!!
-> req,res,...가 존재하지않음 => 경량의 객체
3-2. /insertBoard.do 요청에대해 insertBoard()메서드가 수행되어야한다.
- @RequestMapping(value="/insertBoard.do")
ver1
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
public void insertBoard(HttpServletRequest request) {
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);
}
}
3-3. Command객체 사용
기존에는 req를 통해 받아온 파라미터들을 하나하나 vo에 set해야 했지만 스프링이 제공하는 커맨드 객체를 사용하면 일련의 과정을 줄일 수 있다.
- 인자를 request에서 VO로 바꾼다
- VO 객체 생성
- VO의 setter 자동호출, 추출한 값을 매핑 저장
== VO에 setter주입
ver2
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
public void insertBoard(BoardVO vo,BoardDAO boardDAO) {
boardDAO.insertBoard(vo);
}
}
3-4. return값 void -> String -> ModelAndView
-return할 페이지에 전달할 값이 없다면 String을 통해 경로만 지정하면된다
(ViewResolver가 인식할 수 있도록 "redirect: ~"를 붙이자
-ViewResolver에서 인식하는 디폴트 전달방식이 forward방식이므로 전달할 값이 있다면 .addObject메서드를 통해 값을 저장하고 .setViewName메서드에 해당 경로만 지정해주면 된다.
ver3
@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");
return mav;
}
}
3-5. 각자 다른 action에 따른 controller객체를 호출하게 된다면 singleton패턴에 어긋나므로 하나의 클래스 내부에 @controller를 통해 모든 .do 행동에 생성되고, 각각의 @RequestMapping을 통해 해당 메서드를 찾아갈 수 있도록한다.
package com.test.app.controller;
import java.util.List;
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 BoardController {
// 1. Controller 교체
// 2. 반환타입의 변경 -> ModelAndView(무엇을 보낼지_정보_datas,data,member,... + 어디로 가야하는지_경로)
@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="/board.do")
public ModelAndView getBoard(BoardVO vo,BoardDAO boardDAO,ModelAndView mav) {
vo=boardDAO.getBoard(vo);
mav.addObject("data", vo);
mav.setViewName("board.jsp");
return mav;
}
@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="/updateBoard.do")
public String updateBoard(BoardVO vo,BoardDAO boardDAO) {
boardDAO.updateBoard(vo);
return "redirect:main.do";
}
}