FrontController 구현

su dong·2023년 6월 26일
0

이전 코드를 보면 Controller각각에 @WebServlet이 들어가 있어서 요청에 대해서 각각 응답을 했다.

이것을 FrontController를 사용해서 공통된 부분을 처리해주는 식으로 리팩토링 했다.

  • ViewResolver사용 이유: 경로상의 변경사항이 발생했을 때 일괄적으로 고치기 쉽다.
  • 이렇게 분리하는 이유는 컨트롤러 코드를 변경하지 않기 위함임.
  • Controller interface는 예술임... 저 인터페이스를 만족하면, 누구든지 대체 가능함.
  1. 사용자가 특정 url로 요청을 보낸다.
  2. 그러면 그 url에 해당하는 controller가 있는지 frontController에서 매핑 정보를 확인한다.
  3. 있다면 request 객체에 있는 parameter 값을 모두 paramMap에 넣어서 해당하는 controller를 호출한다.(없으면 404 에러)
  4. controller에서는 필요하다면 paramMap.get()을 사용해서 내부의 비즈니스 로직을 실행한다. 결과 데이터는 model에 담는다. 비즈니스 로직을 모두 수행한 후 사용할 jsp파일 이름을 반환한다.
  5. viewResolver를 호출해서 논리주소를 물리주소로 바꾼다. 물리주소를 view로 반환한다.
  6. view.render(model)을 호출한다. myview객체에서 model에 담긴 정보를 request객체에 담고(request.setAttribute), viewpath에 해당하는 jsp를 매핑한다(dispatcher).
  7. JSP forward()
  8. JSP에서는 html을 응답한다.

frontcontroller.java

package com.example.zerobasewifimission.frontcontroller;

import com.example.zerobasewifimission.frontcontroller.controller.DeleteSearchHistory;
import com.example.zerobasewifimission.frontcontroller.controller.DownLoadWifiInfo;
import com.example.zerobasewifimission.frontcontroller.controller.SearchHistoryList;
import com.example.zerobasewifimission.frontcontroller.controller.ShowNearByWifi;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

// frontController에서 공통적인 부분 처리 1)map에서 찾아서 있으면 매핑해줌 2)Controller interface를 통해서 controller형식 통일
// 3) ViewResolver 사용 4) render(model)호출
// ModelView를 통해서 메시지 주고받음. Controller의 Servlet 의존성 제거.
@WebServlet(name = "frontControllerServlet", urlPatterns = "/front-controller/*")
public class FrontControllerServlet extends HttpServlet {
    private Map<String, Controller> controllerMap = new HashMap<>();

    public FrontControllerServlet() {
        controllerMap.put("/Gradle___com_example___zerobase_wifi_mission_1_0_SNAPSHOT_war/front-controller/delete", new DeleteSearchHistory());
        controllerMap.put("/Gradle___com_example___zerobase_wifi_mission_1_0_SNAPSHOT_war/front-controller/download-wifi", new DownLoadWifiInfo());
        controllerMap.put("/Gradle___com_example___zerobase_wifi_mission_1_0_SNAPSHOT_war/front-controller/search-history", new SearchHistoryList());
        controllerMap.put("/Gradle___com_example___zerobase_wifi_mission_1_0_SNAPSHOT_war/front-controller/show-nearbyWifi-20", new ShowNearByWifi());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Controller controller = getController(request);
        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, String> paramMap = createParamMap(request);
        Map<String, Object> model = new HashMap<>();
        String viewName = controller.process(paramMap, model);

        MyView view = viewResolver(viewName);
        view.render(model, request, response);
    }

    private Controller getController(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        Controller controller = controllerMap.get(requestURI);
        return controller;
    }

    private Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            paramMap.put(paramName, request.getParameter(paramName));
        }
        return paramMap;
    }

    private MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }
}

myview.java

package com.example.zerobasewifimission.frontcontroller;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

public class MyView {
    private String viewPath;

    public MyView(String viewPath) {
        this.viewPath = viewPath;
    }

    public void render(Map<String, Object> model, HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException {
        modelToRequestAttribute(model, request);
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
    private void modelToRequestAttribute(Map<String, Object> model, HttpServletRequest request) {
        model.forEach((key, value) -> request.setAttribute(key, value));
    }
}

Controller.interface

package com.example.zerobasewifimission.frontcontroller;

import java.util.Map;

public interface Controller {
    String process(Map<String, String> paramMap, Map<String, Object> model);
}

showNearByWifi.java

package com.example.zerobasewifimission.frontcontroller.controller;

import com.example.zerobasewifimission.domain.WifiInfo;
import com.example.zerobasewifimission.frontcontroller.Controller;

import com.example.zerobasewifimission.repository.SearchHistoryRepository;
import com.example.zerobasewifimission.repository.WifiInfoRepository;

import java.util.List;
import java.util.Map;

public class ShowNearByWifi implements Controller {
    SearchHistoryRepository searchHistoryRepository = SearchHistoryRepository.getInstance();
    WifiInfoRepository wifiInfoRepository = WifiInfoRepository.getInstance();
    @Override
    public String process(Map<String, String> paramMap, Map<String, Object> model)  {
        //위치기반 검색시 해당 검색 기록 저장
        String xc = paramMap.get("LAT");
        String yc = paramMap.get("LNT");
        searchHistoryRepository.saveSearchHistory(xc,yc);

        List<WifiInfo> wifiInfoList = wifiInfoRepository.getNearbyWifiInfo(xc, yc);
        model.put("wifiInfoList", wifiInfoList);
        model.put("xc",xc);
        model.put("yc",yc);

        return "ShowNearByWifi";
    }
}

showNearByWifi.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
  <title>JSP - Hello World</title>
</head>
<body>
<h1>와이파이 정보 구하기</h1>

<a href="/Gradle___com_example___zerobase_wifi_mission_1_0_SNAPSHOT_war/"></a>
<span>|</span>
<a href="search-history">위치 히스토리 목록</a>
<span>|</span>
<a href="show-wifi">OPEN API 와이파이 정보 가져오기</a>
<span>|</span>
<a href="sqlite-test">sqlite test</a>
<form action="show-nearbyWifi-20" method="post">
  LAT: <input type="number" step="any" id="lat" name="LAT"  />
  LNT: <input type="number" step="any" id="lnt" name="LNT"  />
  <button type="submit">근처 와이파이 정보 보기</button>
</form>
<button type="button" onclick="getLocation()">내 위치 가져오기</button>

<script>
  function getLocation() {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(fillFormWithPosition);
    } else {
      alert("Geolocation is not supported by this browser.");
    }
  }
  function fillFormWithPosition(position) {
    document.getElementById('lat').value = position.coords.latitude;
    document.getElementById('lnt').value = position.coords.longitude;
  }
</script>
<div>현재 내 위치</div>
<div>LAT : ${xc}</div>
<div>LNT : ${yc}</div>
<table border='17'>
  <tr>
    <th>거리</th>
    <th>관리번호</th>
    <th>자치구</th>
    <th>와이파이명</th>
    <th>도로명주소</th>
    <th>상세주소</th>
    <th>설치위치</th>
    <th>설치유형</th>
    <th>설치기관</th>
    <th>서비스구분</th>
    <th>망종류</th>
    <th>설치년도</th>
    <th>실내외구분</th>
    <th>WIFI접속환경</th>
    <th>X좌표</th>
    <th>Y좌표</th>
    <th>작업일자</th>
  </tr>
<c:forEach var="wifi" items="${wifiInfoList}">
  <tr>
    <td>${wifi.distance}</td>
    <td>${wifi.id}</td>
    <td>${wifi.region}</td>
    <td>${wifi.name}</td>
    <td>${wifi.address1}</td>
    <td>${wifi.address2}</td>
    <td>${wifi.floor}</td>
    <td>${wifi.installType}</td>
    <td>${wifi.installMby}</td>
    <td>${wifi.serviceType}</td>
    <td>${wifi.cmcwr}</td>
    <td>${wifi.installYear}</td>
    <td>${wifi.inout}</td>
    <td>${wifi.remars3}</td>
    <td>${wifi.lat}</td>
    <td>${wifi.lnt}</td>
    <td>${wifi.workTime}</td>
  </tr>
  </c:forEach>
</table>
</body>
</html>
profile
사람들을 돕는 문제 해결사, 개발자 sudong입니다. 반갑습니다. tkddlsqkr21@gmail.com

0개의 댓글