Spring
하나의 Suvlet으로 Controller 기능을 구현하는것의 단점
: 분기처리 로직이 추가됨으로 개발과 유지보수의 어려움
각 클래스들의 역할
Dispatcher Servlet
: 유일한 서블릿클래스로 모든 클라이언트의 요청을 가장 먼저 처리하는 Front Controller
Handler Mapping
: 클라이언트의 요청을처리할 Controller 매핑
Controller
: 실질적인 클라이언트의 요청을 처리
View Resolver
: Controller가 리턴한 View 이름으로 실행될 JSP 경로 완성
package com.maju.k1.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;
/**
* Servlet implementation class DispatcherServlet
*/
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapping handlerMapping;
private ViewResolver viewResolver;
public void init() throws ServletException{
// 초기화 메소드
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 {
// // TODO Auto-generated method stub
// response.getWriter().append("Served at: ").append(request.getContextPath());
process(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
doGet(request, response);
}
private void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 클라이언트의 요청 path 정보를 추출한다.
String uri = request.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/"));
System.out.println("path : " + uri );
System.out.println("path : " + path );
// 2. HandlerMapping을 통해 path에 해당하는 Controller를 실행한다.
Controller ctrl = handlerMapping.getController(path);
// 3. 겁색된 Controller를 실행한다.
String viewName = ctrl.handleRequest(request, response);
// 4. ViewResolver를 통해 viewName에 해당하는 화면을 검색한다.
String view = null;
if(!viewName.contains(".do")) {
view = viewResolver.getView(viewName);
System.out.println("==> .jsp 붙이기 확인 " + view );
}else {
view = viewName;
System.out.println("== > .do 붙이기 확인 : " + view );
}
// 5. 검색된 화면으로 이동한다.
response.sendRedirect(view);
}
}
package com.maju.k1.view.controller;
import java.util.HashMap;
import java.util.Map;
public class HandlerMapping {
private Map<String, Controller> mappings;
public HandlerMapping() {
mappings = new HashMap<String, Controller>();
mappings.put("/login.do", new LoginController());
mappings.put("/logout.do", new LogoutController());
mappings.put("/getBoadList.do", new GetBoardListController());
mappings.put("/getBoad.do", new GetBoardController());
mappings.put("/insertBoard.do", new InsertBoardController());
mappings.put("/updateBoard.do", new UpdateBoardController());
mappings.put("/deleteBoard.do", new DeleteBoardController());
}
public Controller getController(String path) {
return mappings.get(path);
}
}
package com.maju.k1.view.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Controller {
String handleRequest (HttpServletRequest request, HttpServletResponse response);
}
package com.maju.k1.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) {
System.out.println("==> getView " + prefix + viewName + suffix);
return prefix + viewName + suffix;
}
}
이러한 구조로도 게시판을 만들어 실행 할 수 있다.
맵핑된 .do 를 실행하여 DispatcherServlet에서 실행된 구조로 파일을 불러와 실행할 수 있다.
★가장 많이 사용하는 구조는 어노테이션 구조이다.★
★ 각 파일 별 어노테이션 추가 및 커맨드 화 ★
-- insert
package com.maju.k1.view.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.maju.k1.board.BoardVO;
import com.maju.k1.board.impl.BoardServiceImpl;
@Controller
public class InsertBoardController {
@RequestMapping(value="/insertBoard.do")
// 커맨드 화 (객체값을 하나의 객체로 전부 받아오는 것)
public String insertBoard(BoardVO vo, BoardServiceImpl service) {
service.insertBoard(vo);
return "getBoardList.do";
}
}
-- delete
package com.maju.k1.view.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.maju.k1.board.BoardVO;
import com.maju.k1.board.impl.BoardServiceImpl;
@Controller
public class DeleteBoardController{
@RequestMapping(value="/deleteBoard.do")
public String deleteController(BoardVO vo, BoardServiceImpl service) {
service.deleteBoard(vo);
return "getBoardList.do";
}
}
-- update
package com.maju.k1.view.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.maju.k1.board.BoardVO;
import com.maju.k1.board.impl.BoardServiceImpl;
@Controller
public class UpdateBoardController {
@RequestMapping(value="/UpdateBoard.do")
public String updateBoard(BoardVO vo, BoardServiceImpl service) {
service.updateBoard(vo);
return "getBoardList.do";
}
}
-- getBoard
package com.maju.k1.view.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.maju.k1.board.BoardVO;
import com.maju.k1.board.impl.BoardServiceImpl;
@Controller
public class GetBoardController {
@RequestMapping(value="/getBoard.do")
public ModelAndView getBoard(BoardVO vo, BoardServiceImpl service, ModelAndView mav) {
service.cntBoard(vo);
mav.addObject("m",service.getBoard(vo));
mav.setViewName("/board/getBoard.jsp");
return mav;
}
}
-- getBoardList
package com.maju.k1.view.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.maju.k1.board.BoardVO;
import com.maju.k1.board.impl.BoardServiceImpl;
@Controller
public class GetBoardListController {
@RequestMapping(value="/getBoardList.do")
public ModelAndView getBoardList(BoardVO vo, BoardServiceImpl service, ModelAndView mav) {
mav.addObject("li",service.getBoardList(vo));
mav.setViewName("/board/getBoardList.jsp");
return mav;
}
}
-- login
package com.maju.k1.view.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.maju.k1.user.UserVO;
import com.maju.k1.user.impl.UserServiceImpl;
@Controller
public class LoginController {
@RequestMapping(value="/login.do")
public String login(UserVO vo, UserServiceImpl service, HttpSession session) {
List<UserVO> user = (List<UserVO>) service.getUser(vo);
System.out.println("====> 유저 확인 " + user);
if(!user.isEmpty()){
UserVO m = user.get(0);
String name = m.getName();
session.setAttribute("name", name);
return "getBoardList.do";
}else{
return "/login/login.jsp";
}
}
}
-- logout
package com.maju.k1.view.controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LogoutController {
@RequestMapping(value="/logout.do")
public String logout(HttpSession session) {
session.invalidate();
return "/index.jsp";
}
}
각 커맨드화를 통해 코드의 내용을 줄일 수 있다.
@Controller 와 @RequestMapping 을 통해 각 컨트롤러 별 값을 정할 수 있고 그 값을 호출해서 사용이 가능하다.
BoardControllr
package com.maju.k1.view.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.maju.k1.board.BoardVO;
import com.maju.k1.board.impl.BoardServiceImpl;
@Controller
public class BoardController {
@RequestMapping(value="/insertBoard.do")
// 커맨드 화 (객체값을 하나의 객체로 전부 받아오는 것)
public String insertBoard(BoardVO vo, BoardServiceImpl service) {
service.insertBoard(vo);
return "getBoardList.do";
}
@RequestMapping(value="/deleteBoard.do")
public String deleteController(BoardVO vo, BoardServiceImpl service) {
service.deleteBoard(vo);
return "getBoardList.do";
}
@RequestMapping(value="/updateBoard.do")
public String updateBoard(BoardVO vo, BoardServiceImpl service) {
service.updateBoard(vo);
return "getBoardList.do";
}
@RequestMapping(value="/getBoard.do")
public ModelAndView getBoard(BoardVO vo, BoardServiceImpl service, ModelAndView mav) {
service.cntBoard(vo);
mav.addObject("m",service.getBoard(vo));
mav.setViewName("/board/getBoard.jsp");
return mav;
}
@RequestMapping(value="/getBoardList.do")
public ModelAndView getBoardList(BoardVO vo, BoardServiceImpl service, ModelAndView mav) {
mav.addObject("li",service.getBoardList(vo));
mav.setViewName("/board/getBoardList.jsp");
return mav;
}
}
LoginController
package com.maju.k1.view.controller;
import java.util.List;
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 com.maju.k1.user.UserVO;
import com.maju.k1.user.impl.UserServiceImpl;
@Controller
public class LoginController {
@RequestMapping(value="/login.do", method=RequestMethod.GET)
public String login(UserVO vo, UserServiceImpl service, HttpSession session) {
List<UserVO> user = (List<UserVO>) service.getUser(vo);
System.out.println("====> 유저 확인 " + user);
if(!user.isEmpty()){
UserVO m = user.get(0);
String name = m.getName();
session.setAttribute("name", name);
return "getBoardList.do";
}else{
return "/login/login.jsp";
}
}
@RequestMapping(value="/logout.do")
public String logout(HttpSession session) {
session.invalidate();
return "/index.jsp";
}
@RequestMapping(value="/login.do",method=RequestMethod.POST)
public String login(HttpSession session) {
session.invalidate();
return "getBoardList.do";
}
}
개발을 하다보면 많은 분량의 게시판을 작성하겠지만 연습을 하고있는 지금은 하나의 게시판을 사용하기에, 하나의 게시판이 있을때는 하나의 파일에 모든 컨트롤러를 묶어서 표기할 수 있다.
로그인 컨트롤러에 메소드를 정하는방법을 위해 GET과 POST 두가지 경우를 표기했다.
method 유형이 기입 되어있지 않을경우 기본적으로 모든 HTTP 요청 메서드에 대해 매핑된다.
즉, GET, POST, PUT, DELETE 등의 모든 HTTP 요청 메서드에 대해 처리할 수 있는 핸들러 메서드가 되는 것 !