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주차 미션 / 서버 4조 김재윤 #54

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 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
0f45f54
refactor: View 적용
lyouxsun Nov 1, 2024
bf928f3
refactor: ForwardController에 View 적용
lyouxsun Nov 1, 2024
29f5bd0
fix: DispatcherServlet 수정
lyouxsun Nov 1, 2024
5cbd976
.
Yun531 Nov 6, 2024
92daa03
요구사항 2
Yun531 Nov 7, 2024
b5d498a
스터디
Yun531 Nov 12, 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;
}
8 changes: 8 additions & 0 deletions src/main/java/core/mvc/AbstractController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package core.mvc;

import core.mvc.view.ModelAndView;

public interface AbstractController extends Controller{
abstract ModelAndView jspView(String url);
abstract ModelAndView 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;
}
33 changes: 33 additions & 0 deletions src/main/java/core/mvc/DispatcherServlet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package core.mvc;

import core.mvc.view.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@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() {
requestMapping = new RequestMapping();
}

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
String url = req.getRequestURI();
Controller controller = requestMapping.getController(url);
try {
ModelAndView mav = controller.execute(req, resp); //modelandview 사용으로 변경, execute()를 하면 view가 리턴 됨
mav.render(req, resp); //modelandview.render() 사용
} catch (Exception e) {
System.out.println(e.getMessage());
throw new ServletException(e.getMessage());
}
}
}
34 changes: 34 additions & 0 deletions src/main/java/core/mvc/ForwardController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package core.mvc;

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

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

public class ForwardController implements 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);
}

@Override
public ModelAndView jspView(String url) {
return new ModelAndView(new JspView(url));
}

@Override
public ModelAndView jsonView( ) {
return null;
}
}
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);
}
}
31 changes: 31 additions & 0 deletions src/main/java/core/mvc/view/JsonView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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;

public class JsonView implements View{ //req에 있는 모든 파라미터를 map 자료구조에 저장, map 자료구조에 있는 모든 데이터들을 json형식으로 변환하여 사용자에게 응답
@Override
public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { //map 자료구조에 있는 모든 데이터들을 json형식으로 변환하여 사용자에게 http resp 응답
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.print(objectMapper.writeValueAsString(model)); //model을 json으로 변환
}

// private static Map<String, Object> createModel(HttpServletRequest request) { //req에 있는 모든 파라미터를 map 자료구조에 저장후 리턴 (json으로 변환하기 위한 형식)
// 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;
// }

}
32 changes: 32 additions & 0 deletions src/main/java/core/mvc/view/JspView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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 final String viewName; //url
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 { //사용자에게 웹 페이지를 보여주는 함수
if (viewName.startsWith(REDIRECT_PREFIX)) {
response.sendRedirect(viewName.substring(REDIRECT_PREFIX.length()));
return;
}

for (Map.Entry<String, Object> entry : model.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}

RequestDispatcher rd = request.getRequestDispatcher(viewName);
rd.forward(request, response);
}
}
Loading