Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8장 #12

Draft
wants to merge 2 commits into
base: step5-qna-with-ajax
Choose a base branch
from
Draft

8장 #12

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/core/mvc/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
import javax.servlet.http.HttpServletResponse;

public interface Controller {
String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception;
ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) throws Exception;
}
32 changes: 8 additions & 24 deletions src/main/java/core/mvc/DispatcherServlet.java
Original file line number Diff line number Diff line change
@@ -1,56 +1,40 @@
package core.mvc;

import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.RequestDispatcher;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebServlet(name = "dispatcher", urlPatterns = "/", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);
private static final String DEFAULT_REDIRECT_PREFIX = "redirect:";

private RequestMapping rm;

@Override
public void init() throws ServletException {
public void init() {
rm = new RequestMapping();
rm.initMapping();
}

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
String requestUri = req.getRequestURI();
logger.debug("Method : {}, Request URI : {}", req.getMethod(), requestUri);

Controller controller = rm.findController(requestUri);
try {
String viewName = controller.execute(req, resp);
if (viewName != null) {
move(viewName, req, resp);
}
ModelAndView modelAndView = controller.execute(req, resp);
View view = modelAndView.getView();
view.render(modelAndView.getModel(), req, resp);
} catch (Throwable e) {
logger.error("Exception : {}", e);
logger.error("Exception: ", e);
throw new ServletException(e.getMessage());
}
}

private void move(String viewName, HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (viewName.startsWith(DEFAULT_REDIRECT_PREFIX)) {
resp.sendRedirect(viewName.substring(DEFAULT_REDIRECT_PREFIX.length()));
return;
}

RequestDispatcher rd = req.getRequestDispatcher(viewName);
rd.forward(req, resp);
}
}
11 changes: 7 additions & 4 deletions src/main/java/core/mvc/ForwardController.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package core.mvc;

import next.controller.AbstractController;

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

public class ForwardController implements Controller {
private String forwardUrl;
public class ForwardController extends AbstractController {
private final String forwardUrl;

public ForwardController(String forwardUrl) {
this.forwardUrl = forwardUrl;
// TODO: null 체크를 생성자 첫 줄에서 하는 건 어떨까? + Objects.requireNonNull()
if (forwardUrl == null) {
throw new NullPointerException("forwardUrl is null. 이동할 URL을 입력하세요.");
}
}

@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
return forwardUrl;
public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) {
return jspView(forwardUrl);
}
}
31 changes: 31 additions & 0 deletions src/main/java/core/mvc/JsonView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package core.mvc;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class JsonView implements View {

@Override
public void render(final Map<String, ?> model, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.print(objectMapper.writeValueAsString(model));
}

private Map<String, Object> createModelFromRequest(final HttpServletRequest request) {
Map<String, Object> models = new HashMap<>();
Enumeration<String> attributeNames = request.getAttributeNames();
while (attributeNames.hasMoreElements()) {
String name = attributeNames.nextElement();
models.put(name, request.getAttribute(name));
}
return models;
}
}
36 changes: 36 additions & 0 deletions src/main/java/core/mvc/JspView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package core.mvc;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class JspView implements View {

private static final String DEFAULT_REDIRECT_PREFIX = "redirect:";

private final String viewName;

public JspView(final String viewName) {
Objects.requireNonNull(viewName, "viewName is null.");
this.viewName = viewName;
}

@Override
public void render(final Map<String, ?> model, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
if (viewName.startsWith(DEFAULT_REDIRECT_PREFIX)) {
response.sendRedirect(viewName.substring(DEFAULT_REDIRECT_PREFIX.length()));
return;
}

Set<String> keys = model.keySet();
for (String key : keys) {
request.setAttribute(key, model.get(key));
}

RequestDispatcher rd = request.getRequestDispatcher(viewName);
rd.forward(request, response);
}
}
27 changes: 27 additions & 0 deletions src/main/java/core/mvc/ModelAndView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package core.mvc;

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

public class ModelAndView {
private final View view;
private final Map<String, Object> model = new HashMap<>();

public ModelAndView(final View view) {
this.view = view;
}

public ModelAndView addObject(final String attributeName, final Object attributeValue) {
model.put(attributeName, attributeValue);
return this;
}

public View getView() {
return view;
}

public Map<String, Object> getModel() {
return Collections.unmodifiableMap(model);
}
}
9 changes: 9 additions & 0 deletions src/main/java/core/mvc/View.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package core.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public interface View {
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
16 changes: 16 additions & 0 deletions src/main/java/next/controller/AbstractController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package next.controller;

import core.mvc.Controller;
import core.mvc.JsonView;
import core.mvc.JspView;
import core.mvc.ModelAndView;

public abstract class AbstractController implements Controller {
protected ModelAndView jspView(String forwardUrl) {
return new ModelAndView(new JspView(forwardUrl));
}

protected ModelAndView jsonView() {
return new ModelAndView(new JsonView());
}
}
12 changes: 7 additions & 5 deletions src/main/java/next/controller/HomeController.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package next.controller;

import core.mvc.ModelAndView;
import next.dao.QuestionDao;

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

import core.mvc.Controller;
import next.dao.QuestionDao;
public class HomeController extends AbstractController {

public class HomeController implements Controller {
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) {
QuestionDao questionDao = new QuestionDao();
req.setAttribute("questions", questionDao.findAll());
return "home.jsp";
return jspView("home.jsp")
.addObject("questions", questionDao.findAll());
}
}
28 changes: 11 additions & 17 deletions src/main/java/next/controller/qna/AddAnswerController.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
package next.controller.qna;

import java.io.PrintWriter;

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

import core.mvc.ModelAndView;
import next.controller.AbstractController;
import next.dao.AnswerDao;
import next.model.Answer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;

import core.mvc.Controller;
import next.dao.AnswerDao;
import next.model.Answer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AddAnswerController implements Controller {
public class AddAnswerController extends AbstractController {
private static final Logger log = LoggerFactory.getLogger(AddAnswerController.class);

@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) {
// TODO: Answer에 Builder 패턴 적용, 아래에서 사용
Answer answer = new Answer(req.getParameter("writer"), req.getParameter("contents"),
Long.parseLong(req.getParameter("questionId")));
log.debug("answer : {}", answer);

AnswerDao answerDao = new AnswerDao();
Answer savedAnswer = answerDao.insert(answer);
ObjectMapper mapper = new ObjectMapper();
resp.setContentType("application/json;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.print(mapper.writeValueAsString(savedAnswer));
return null;
return jsonView()
.addObject("answer", savedAnswer);
}
}
26 changes: 11 additions & 15 deletions src/main/java/next/controller/qna/DeleteAnswerController.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
package next.controller.qna;

import java.io.PrintWriter;
import core.mvc.ModelAndView;
import next.controller.AbstractController;
import next.dao.AnswerDao;
import next.model.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import com.fasterxml.jackson.databind.ObjectMapper;
public class DeleteAnswerController extends AbstractController {
private static final Logger log = LoggerFactory.getLogger(DeleteAnswerController.class);

import core.mvc.Controller;
import next.dao.AnswerDao;
import next.model.Result;

public class DeleteAnswerController implements Controller {
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) {
Long answerId = Long.parseLong(req.getParameter("answerId"));
AnswerDao answerDao = new AnswerDao();

answerDao.delete(answerId);

ObjectMapper mapper = new ObjectMapper();
resp.setContentType("application/json;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.print(mapper.writeValueAsString(Result.ok()));
return null;
return jsonView()
.addObject("result", Result.ok());
}
}
20 changes: 11 additions & 9 deletions src/main/java/next/controller/qna/ShowController.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package next.controller.qna;

import core.mvc.ModelAndView;
import next.controller.AbstractController;
import next.dao.AnswerDao;
import next.dao.QuestionDao;

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

import core.mvc.Controller;
import next.dao.AnswerDao;
import next.dao.QuestionDao;
public class ShowController extends AbstractController {

public class ShowController implements Controller {
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
Long questionId = Long.parseLong(req.getParameter("questionId"));
public ModelAndView execute(HttpServletRequest req, HttpServletResponse resp) {
long questionId = Long.parseLong(req.getParameter("questionId"));
QuestionDao questionDao = new QuestionDao();
AnswerDao answerDao = new AnswerDao();
req.setAttribute("question", questionDao.findById(questionId));
req.setAttribute("answers", answerDao.findAllByQuestionId(questionId));
return "/qna/show.jsp";
return jspView("/qna/show.jsp")
.addObject("question", questionDao.findById(questionId))
.addObject("answers", answerDao.findAllByQuestionId(questionId));
}
}
Loading