Spring/Spring

day64) Spring-Controller설계1

code_learner 2022. 3. 31. 15:01

Spring에서 제공하는 DispatcherServlet과 스프링 컨테이너를 활용하여 Controller를 설계해보자.

 

 

[설계]

NewFile.jsp에서 글을 쓰면 /WEB-INF/NewFile1.jsp(url로 접근할 수 없도록)에서 출력


[View]

NewFile.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<form action="next.do" method="post">
	<input type="text" name="msg">
	<input type="submit" value="다음페이지">
</form>

</body>
</html>

NewFile1.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1>${msg}</h1>

</body>
</html>

 

[web.xml]

.do 요청이 오게된다면 필터를 통해 인코딩처리가 되고, Spring에서 제공하는 DispatcherServlet에 Mapping

더보기
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://Java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<filter>
		<filter-name>encFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encFilter</filter-name>
		<url-pattern>*.do</url-pattern>
	</filter-mapping>
	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>

 

 


DispatcherServlet이 생성되게 된다면 init()메서드가 자동으로 호출되게 되는데 여기서 스프링이 제공하는 HandlerMappingViewResolver 주입해주어야 한다.

 

아래코드는 직접 작성해보는 DS, HM, VR(Spring에서 사용하지 않는다)

 

-DS

더보기
package com.test.app.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

/**
 * Servlet implementation class DispatcherServlet
 */
// DS은 FrontController의 역할!
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");
	}
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DispatcherServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doAction(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doAction(request, response);
	}
	
	private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1. 사용자(브라우저,클라이언트)의 요청을 추출
		String uri=request.getRequestURI();
		String command=uri.substring(uri.lastIndexOf("/"));
		System.out.println(command);
		
		// 2. 요청을 분기처리
		// -> HandlerMapping을 통해서 command에 해당하는 Controller객체를 반환
		Controller ctrl=handlerMapping.getController(command);
		String viewName=ctrl.handleRequest(request, response);
		//  1) 싱글톤패턴 유지
		//  2) 가독성 향상
		
		if(!viewName.contains(".do")) {
			viewName=viewResolver.getView(viewName);
		}
		response.sendRedirect(viewName);
	}

}

-HandlerMapping

더보기
package com.test.app.controller;

import java.util.HashMap;
import java.util.Map;

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

import com.test.app.controller.board.BoardController;
import com.test.app.controller.board.DeleteBoardController;
import com.test.app.controller.board.InsertBoardController;
import com.test.app.controller.board.MainController;
import com.test.app.controller.board.UpdateBoardController;
import com.test.app.controller.member.LoginController;
import com.test.app.controller.member.LogoutController;

// 어떤 요청처리 로직을 가진 클래스(==Action,Controller)를 반환해야하는지 알려주는 클래스
public class HandlerMapping {
	private Map<String,Controller> mappings;
	
	public HandlerMapping() {
		mappings=new HashMap<String,Controller>();
		mappings.put("/next.do", new NextController());
	}
	
	public Controller getController(String path) {
		return mappings.get(path);
	}
}

-ViewResolver

더보기
package com.test.app.controller;

public class ViewResolver {
	private String prefix;
	private String suffix;
	public String getPrefix() {
		return prefix;
	}
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}
	public String getSuffix() {
		return suffix;
	}
	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}
	
	// input: Controller가 어떤 View로 이동해야하는지 반환
	// output: 다음 실행될 JSP 경로를 생성
	public String getView(String viewName) {
		return prefix+viewName+suffix;
	}
}

 


 

 

[DispatcherServlet-servlet.xml]

위 코드들을 스프링에서 제공하므로 우리는 처리만 해달라고 DispatcherServlet-servlet.xml파일에 설정만 해주면 스프링컨 테이너가 ViewResolver, HandlerMapping을 주입해주고, 스프링제공 DS가 각각 처리해준다.

더보기
<?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="/next.do">next</prop>
			</props>
		</property>
	</bean>
	<bean class="controller.NextController" id="next"></bean>

</beans>

 


[NextController.jsp]

Handler매핑으로 수행할 Controller(Action)

더보기
package controller;

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

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

public class NextController implements Controller{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String msg = request.getParameter("msg");
		ModelAndView mav = new ModelAndView();
		mav.addObject("msg", msg);//가지고갈 정보
		mav.setViewName("NewFile1");//보낼 위치
		return mav;
	}

}