Spring MVC
Spring Framework의 특성인 IoC를 이용하여 개발자가 직접 클래스를 만들지 않고 Spring에서 제공하는 클래스를 활용하여 Spring MVC 방식으로 코드를 작성할 수 있습니다.
web.xml
기존에는 개발자가 직접 생성한 DispatcherServlet.java를 사용하였지만 스프링에서 제공하는 DispatcherServlet-servlet.xml을 사용할 수 있습니다.
Resolver
Resolver는 주로 뷰(View)와 컨트롤러(Controller) 사이에서 데이터를 변환하거나 처리하는 데 사용됩니다. 특정 역할을 자동으로 처리하며 반드시 id를 명시해줘야 합니다.
ViewResolver
ViewResolver는 사용자에게 보여질 뷰를 결정하는 역할을 합니다. 주로 컨트롤러에서 반환된 뷰 이름을 기반으로 실제 뷰 템플릿의 위치를 찾아서 렌더링하도록 지시합니다. Contoller류의 객체가 .handleRequest()의 수행결과로 String을 반환했을 때 prefix(접두사)와 suffix(접미사)를 판단해서 처리합니다. Spring에서는 다양한 ViewResolver 구현을 제공합니다.
Spring MVC 변경
- web.xml에서 직접 생성한 DispatcherServlet.java를 Spring에서 제공하는 클래스로 변경
- 컨테이너를 구동할 것이기 때문에 컨테이너 설정 등을 정의하는 xml 파일이 필요
- DispatcherServlet-servlet.xml
- Spring이 제공하는 Controller 클래스로 변경
- 반환타입을 String에서 ModelAndView로 변경
- HandlerMapping 생성
- HandlerMapping이 요청에 대한 Controller 객체 반환을 수행
- HandlerMapping은 DispatcherServlet에서 DI되는 객체
- DispatcherServlet-servlet에서 초기화
- HandlerMapping은 POJO이기 때문에 web.xml에서 설정할 수 없음
- HandlerMapping은 생성자 주입이 아니라 setter 주입
ViewResolver 페이지 은닉
해당 페이지를 열 때 경유해야 하는 페이지가 있는 경우에는 WEB-INF 하위 폴더에 jsp 파일을 위치시킵니다. 페이지를 열 때 어떠한 데이터가 오지 않을 경우 에러가 발생할 수 있으므로 ViewResolver를 통해 페이지를 은닉합니다. 해당 방식은 사용자의 직접 접근(URL 조작)을 차단할 수 있고 오직 ViewResolver를 통해서만 이동할 수 있습니다.
실습
package com.spring.view.controller;
public class ViewResolver {
public String prefix;
public String suffix;
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getView(String viewName) {
return prefix+viewName+suffix;
}
}
ViewResolver.java
package com.spring.view.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapping handlerMapping;
private ViewResolver viewResolver;
public void init() {
handlerMapping = new HandlerMapping();
viewResolver = new ViewResolver();
viewResolver.setPrefix("./");
viewResolver.setSuffix(".jsp");
}
public DispatcherServlet() {
super();
}
private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String uri=request.getRequestURI();
String command=uri.substring(uri.lastIndexOf("/"));
System.out.println("command: "+command);
Controller ctrl=handlerMapping.getController(command);
String viewName=ctrl.handleRequest(request, response);
// viewName이 .do를 가지고있으면 VIEW로 가는것이 아니다
String path=viewName;
if(!viewName.contains(".do")) {
path=viewResolver.getView(viewName);
}
response.sendRedirect(path);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response);
}
}
DispatcherServler.java
package com.spring.view.controller;
import java.util.HashMap;
import java.util.Map;
public class HandlerMapping {
// FrontController에서 사용되는 factory 클래스의 이름
// 팩토리 패턴을 사용하기때문에 싱글톤이 유지됨
private Map<String,Controller> mappings;
public HandlerMapping() {
mappings=new HashMap<String,Controller>();
mappings.put("/main.do", new MainController());
mappings.put("/login.do", new LoginController());
mappings.put("/logout.do", new LogoutController());
}
public Controller getController(String command) {
Controller ctrl=mappings.get(command);
return ctrl;
}
}
HandlerMapping.java
package com.spring.view.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.spring.biz.board.BoardDAO;
public class MainController implements Controller {
@Override
public String handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("MainController 로그");
BoardDAO bDAO=new BoardDAO();
request.setAttribute("datas", bDAO.selectAll(null));
return "main"; // main.jsp(VIEW)로 가려고함
}
}
MainController.java
GitHub
https://github.com/Qkrwnsgus0522/Spring