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

6주차 미션 / 서버 2조 황정안 #56

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f4a34a9
feat: servlet jsp 기본 예시 구현
lyouxsun Oct 7, 2024
33f5315
feat: jsp로 변경, HomeController 추가
lyouxsun Oct 7, 2024
bb5d666
feat: 개인정보 수정
lyouxsun Oct 7, 2024
c87f576
feat: 로그인, 로그아웃 구현
lyouxsun Oct 7, 2024
662a3b3
feat: 회원 목록 보안 강화 구현
lyouxsun Oct 7, 2024
2906265
feat: 개인정보 수정 보안 강화 구현
lyouxsun Oct 7, 2024
f200d11
feat: mvc 프레임워크 구현
lyouxsun Oct 7, 2024
6471c34
fix: 한글 인코딩 오류 수정
lyouxsun Oct 12, 2024
71712f9
fix: requestMapping으로 선언
lyouxsun Oct 12, 2024
37c008a
feat: 순수 jdbc로 userDao 클래스 구현
lyouxsun Oct 24, 2024
3f23dbe
refactor: jdbcTemplate 구현
lyouxsun Oct 24, 2024
0f60e28
refactor: try-with-resource, generic 적용
lyouxsun Oct 24, 2024
7fe01ab
refactor(controller): MemoryUserRepository에서 UserDao로 변경
lyouxsun Oct 28, 2024
a5f5cd2
refactor(db): 미사용 MemoryUserRepository 제거
lyouxsun Oct 28, 2024
0f567e6
feat(Question): Question 엔티티 생성
lyouxsun Oct 28, 2024
b99d53f
feat(QuestionDao): QuestionDao 구현
lyouxsun Oct 28, 2024
6bdf143
feat: 홈화면에서 질문 목록 조회
lyouxsun Oct 28, 2024
6da08b6
feat: 회원만 질문 가능하도록 구현
lyouxsun Oct 28, 2024
e92d397
feat: 질문 생성 및 저장 구현
lyouxsun Oct 28, 2024
a6fd9c7
feat(ShowQuestionController): 질문 조회 기능 구현
lyouxsun Oct 29, 2024
920d11d
feat(UpdateQuestionController): 질문 수정 기능 구현
lyouxsun Oct 29, 2024
65a94b6
feat(Answer): Answer 엔티티 생성
lyouxsun Oct 29, 2024
8cad687
feat(AnswerDao): AnswerDao 구현
lyouxsun Oct 30, 2024
cabe08f
feat(ShowQuestionController): 답변 조회 기능 구현
lyouxsun Oct 30, 2024
9c4b088
feat(CreateAnswerController): 답변 생성 기능 구현
lyouxsun Oct 30, 2024
295d2a0
chore(controller): 폴더 구조 변경
lyouxsun Oct 30, 2024
e6f81dd
미션 구현 완
jungan777 Nov 7, 2024
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
10 changes: 10 additions & 0 deletions .run/WebServerLauncher.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="WebServerLauncher" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="WebServerLauncher" />
<module name="java-webMVC.main" />
<option name="VM_PARAMETERS" value="-Dfile.encoding=UTF-8" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
41 changes: 0 additions & 41 deletions src/main/java/core/db/MemoryUserRepository.java

This file was deleted.

11 changes: 0 additions & 11 deletions src/main/java/core/db/Repository.java

This file was deleted.

86 changes: 86 additions & 0 deletions src/main/java/core/jdbc/JdbcTemplate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package core.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class JdbcTemplate<T> {

public void update(String sql, PreparedStatementSetter pstmtSetter) throws SQLException {
try (Connection conn = ConnectionManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmtSetter.setParameters(pstmt);
pstmt.executeUpdate();
}
}

public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws SQLException {
List<T> objects = new ArrayList<>();

try (Connection conn = ConnectionManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();) {
while (rs.next()) {
T object = rowMapper.mapRow(rs);
objects.add(object);
}
}
return objects;
}

public T queryForObject(String sql, PreparedStatementSetter pstmtSetter, RowMapper<T> rowMapper) throws SQLException {
ResultSet rs = null;
T object = null;

try (Connection conn = ConnectionManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);) {
pstmtSetter.setParameters(pstmt);
rs = pstmt.executeQuery();
if (rs.next()) {
object = rowMapper.mapRow(rs);
}
} finally {
if (rs != null)
rs.close();
}
return object;
}

public void update(String sql, PreparedStatementSetter pstmtSetter, KeyHolder keyHolder) throws SQLException {
ResultSet rs = null;
try (Connection conn = ConnectionManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS)) {
pstmtSetter.setParameters(pstmt);
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
if (rs.next()) {
keyHolder.setId((int) rs.getLong(1));
}
} finally {
if (rs != null)
rs.close();
}
}

public List<T> query(String sql, PreparedStatementSetter pstmtSetter, RowMapper<T> rowMapper) throws SQLException {
List<T> objects = new ArrayList<>();
ResultSet rs = null;

try (Connection conn = ConnectionManager.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);) {
pstmtSetter.setParameters(pstmt);
rs = pstmt.executeQuery();
while (rs.next()) {
T object = rowMapper.mapRow(rs);
objects.add(object);
}
} finally {
if (rs != null)
rs.close();
}
return objects;
}
}
13 changes: 13 additions & 0 deletions src/main/java/core/jdbc/KeyHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package core.jdbc;

public class KeyHolder {
private int id;

public void setId(int id) {
this.id = id;
}

public int getId() {
return id;
}
}
9 changes: 9 additions & 0 deletions src/main/java/core/jdbc/PreparedStatementSetter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package core.jdbc;

import java.sql.PreparedStatement;
import java.sql.SQLException;

@FunctionalInterface
public interface PreparedStatementSetter {
void setParameters(PreparedStatement ps) throws SQLException;
}
11 changes: 11 additions & 0 deletions src/main/java/core/jdbc/RowMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package core.jdbc;

import jwp.model.User;

import java.sql.ResultSet;
import java.sql.SQLException;

@FunctionalInterface
public interface RowMapper<T> {
T mapRow(ResultSet rs) throws SQLException;
}
19 changes: 19 additions & 0 deletions src/main/java/core/mvc/AbstractController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package core.mvc;

import core.mvc.view.JsonView;
import core.mvc.view.JspView;
import core.mvc.view.ModelAndView;
import core.mvc.view.View;

public abstract class AbstractController implements Controller {
//todo: interface 틀을 감싸는게(규약을 정하는) 목적
//todo: abstract class 는 확장에 목적 따라ㅓ 여기선 abstract 가 나을듯이 맥락에서 고려해보기 -> 그냥 class는 구현을 할 위험이 있으니 abstract 처리 하는게 좋을ㄷㅅ
//목적에 따라 다르다!!
protected ModelAndView jspView(String viewName){
return new ModelAndView(new JspView(viewName));
}
protected ModelAndView jsonView() {
return new ModelAndView(new JsonView());
}

}
11 changes: 11 additions & 0 deletions src/main/java/core/mvc/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package core.mvc;

import core.mvc.view.ModelAndView;
import core.mvc.view.View;

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

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

import core.mvc.view.ModelAndView;
import core.mvc.view.View;

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 java.io.IOException;

@WebServlet(name = "dispatcher", urlPatterns = "/", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
private RequestMapping requestMapping;
private static final String REDIRECT_PREFIX = "redirect:";

@Override
public void init() throws ServletException {
requestMapping = new RequestMapping();
}

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = req.getRequestURI();
Controller controller = requestMapping.getController(url);
try {
ModelAndView mav = controller.execute(req, resp);
mav.render(req,resp);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new ServletException(e.getMessage());
}
}

private void move(String viewName, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
if (viewName.startsWith(REDIRECT_PREFIX)) {
resp.sendRedirect(viewName.substring(REDIRECT_PREFIX.length()));
return;
}
RequestDispatcher rd = req.getRequestDispatcher(viewName);
rd.forward(req, resp);
}

}
23 changes: 23 additions & 0 deletions src/main/java/core/mvc/ForwardController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package core.mvc;

import core.mvc.view.ModelAndView;

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

public class ForwardController extends AbstractController {

private final String forwardUrl;

public ForwardController(String forwardUrl) {
this.forwardUrl = forwardUrl;
if (forwardUrl == null) {
throw new NullPointerException("forwardUrl is null");
}
}

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

import jwp.controller.*;
import jwp.controller.qna.*;
import jwp.controller.user.*;

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

public class RequestMapping {

private static final Map<String, Controller> controllers = new HashMap<>();

static {
controllers.put("/", new HomeController());
controllers.put("/user/signup", new CreateUserController());
controllers.put("/user/list", new ListUserController());
controllers.put("/user/login", new LoginController());
controllers.put("/user/logout", new LogoutController());
controllers.put("/user/update", new UpdateUserController());
controllers.put("/user/updateForm", new UpdateUserFormController());

controllers.put("/user/form", new ForwardController("/user/form.jsp"));
controllers.put("/user/loginForm", new ForwardController("/user/login.jsp"));
controllers.put("/user/loginFailed", new ForwardController("/user/loginFailed.jsp"));

controllers.put("/qna/form", new CreateQuestionFormController());
controllers.put("/qna/updateForm", new UpdateQuestionFormController());
controllers.put("/qna/update", new UpdateQuestionController());
controllers.put("/qna/create", new CreateQuestionController());
controllers.put("/qna/show", new ShowQnaController());

controllers.put("/api/qna/addAnswer", new CreateAnswerController());
}


public Controller getController(String url) {
return controllers.get(url);
}
}
37 changes: 37 additions & 0 deletions src/main/java/core/mvc/view/JsonView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package core.mvc.view;

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;
import java.util.Objects;

public class JsonView implements View{



private static Map<String, Object> createModel(HttpServletRequest request) {
Enumeration<String> names= request.getParameterNames();
Map<String, Object> model=new HashMap<>();
while(names.hasMoreElements()){
String name = names.nextElement();
model.put(name, request.getParameter(name));
}
return model;
}

@Override
public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
//req에 있는 para 가져와서 map 저장 및 json으로 변환
//ctrl+shift+alt+T = 메소드 추출
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.print(objectMapper.writeValueAsString(createModel(request)));

}
}
26 changes: 26 additions & 0 deletions src/main/java/core/mvc/view/JspView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package core.mvc.view;

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

public class JspView implements View {
private String viewName;
private static final String REDIRECT_PREFIX = "redirect:";

public JspView(String viewName) {
this.viewName=viewName;
}

@Override
public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
//viewName과 일치하는 거 보여주는 역할
if (viewName.startsWith(REDIRECT_PREFIX)) {
response.sendRedirect(viewName.substring(REDIRECT_PREFIX.length()));
return;
}
RequestDispatcher rd = request.getRequestDispatcher(viewName);
rd.forward(request, response);
}
}
Loading