이전 코드를 보면 Controller각각에 @WebServlet이 들어가 있어서 요청에 대해서 각각 응답을 했다.
이것을 FrontController를 사용해서 공통된 부분을 처리해주는 식으로 리팩토링 했다.
- ViewResolver사용 이유: 경로상의 변경사항이 발생했을 때 일괄적으로 고치기 쉽다.
- 이렇게 분리하는 이유는 컨트롤러 코드를 변경하지 않기 위함임.
- Controller interface는 예술임... 저 인터페이스를 만족하면, 누구든지 대체 가능함.
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");
}
}
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));
}
}
package com.example.zerobasewifimission.frontcontroller;
import java.util.Map;
public interface Controller {
String process(Map<String, String> paramMap, Map<String, Object> model);
}
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";
}
}
<%@ 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>