From cc0f425a1cfe3de2908e55638639dce8a24789cb Mon Sep 17 00:00:00 2001 From: jhchoi57 <46276276+jhchoi57@users.noreply.github.com> Date: Thu, 26 Jan 2023 10:57:11 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=B5=9C=EC=A3=BC=ED=98=95]=2016=EC=9D=BC?= =?UTF-8?q?=EC=B0=A8=20PR=20(#175)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 기존 파일 삭제 * START SPRING PROJECT * FEAT : HtmlController 초기 세팅 * FEAT : SignUpService class add * FEAT : db, user model 추가 및 구현 * FEAT : Service class에 애노테이션 추가 * FEAT : 회원가입 기능 구현 * FEAT : login 기능 구현 * REFACTOR : rename db > repository * REFACTOR : rename memoryDB > memoryRepository * FEAT : 로그인을 위한 LoginForm 클래스 생성 * DOCS : README.md 추가 * DOCS : 리드미 학습내용 추가 * FIX : login 성공 시 첫 페이지로 이동 * FEAT : login 성공 시 회원가입, 로그인 버튼 삭제 thymeleaf 이용 * FEAT : html 전부 thymeleaf에 맞게 수정 * FEAT : 로그인 시 로그아웃과 개인정보 수정 버튼 생기게 수정 * FEAT : user List html 구현 * FEAT : 회원가입 중복체크 구현 * FEAT : mysql 연동 준비 --- .gitignore | 235 +++------------- README.md | 263 +++--------------- build.gradle | 38 ++- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 263 +++++++++++------- gradlew.bat | 14 +- settings.gradle | 3 +- .../bejavawebserver/WebserverApplication.java | 13 + .../controller/HomeController.java | 13 + .../controller/HtmlController.java | 54 ++++ .../controller/UserController.java | 32 +++ .../java/bejavawebserver/model/LoginForm.java | 12 + .../{ => bejavawebserver}/model/User.java | 2 +- .../repository/memoryRepository.java} | 14 +- .../bejavawebserver/service/HtmlService.java | 29 ++ .../bejavawebserver/service/ListService.java | 20 ++ .../bejavawebserver/service/LoginService.java | 22 ++ .../service/SignUpService.java | 13 + src/main/java/controller/Controller.java | 8 - src/main/java/controller/HtmlController.java | 40 --- .../java/controller/StaticFileController.java | 19 -- src/main/java/controller/UserController.java | 46 --- src/main/java/db/Session.java | 30 -- src/main/java/http/HttpHeader.java | 49 ---- src/main/java/http/HttpStatus.java | 27 -- src/main/java/http/HttpUri.java | 21 -- .../DuplicateSignUpUserException.java | 7 - .../exception/NullHttpRequestException.java | 7 - src/main/java/http/request/HttpRequest.java | 68 ----- .../java/http/request/HttpRequestLine.java | 27 -- src/main/java/http/response/HttpResponse.java | 95 ------- .../java/http/response/HttpStatusLine.java | 18 -- src/main/java/service/HtmlService.java | 34 --- src/main/java/service/ListService.java | 60 ---- src/main/java/service/LogInService.java | 67 ----- src/main/java/service/SignUpService.java | 48 ---- src/main/java/service/StaticFileService.java | 19 -- src/main/java/util/HttpRequestUtils.java | 75 ----- src/main/java/util/HttpResponseUtils.java | 39 --- .../java/webserver/ControllerHandler.java | 39 --- src/main/java/webserver/RequestHandler.java | 46 --- src/main/java/webserver/WebServer.java | 33 --- src/main/resources/application.properties | 4 + src/main/resources/templates/index.html | 10 +- src/main/resources/templates/qna/form.html | 10 +- src/main/resources/templates/qna/show.html | 10 +- src/main/resources/templates/user/form.html | 10 +- src/main/resources/templates/user/list.html | 18 +- src/main/resources/templates/user/login.html | 10 +- .../templates/user/login_failed.html | 10 +- .../resources/templates/user/profile.html | 10 +- src/test/java/HtmlServiceTest.java | 30 -- src/test/java/HttpRequestUtilsTest.java | 37 --- src/test/java/HttpResponseUtilsTest.java | 48 ---- src/test/java/ListServiceTest.java | 32 --- src/test/java/LogInServiceTest.java | 41 --- src/test/java/SignUpServiceTest.java | 48 ---- src/test/java/StaticFileServiceTest.java | 21 -- .../WebserverApplicationTests.java | 13 + 60 files changed, 543 insertions(+), 1783 deletions(-) create mode 100644 src/main/java/bejavawebserver/WebserverApplication.java create mode 100644 src/main/java/bejavawebserver/controller/HomeController.java create mode 100644 src/main/java/bejavawebserver/controller/HtmlController.java create mode 100644 src/main/java/bejavawebserver/controller/UserController.java create mode 100644 src/main/java/bejavawebserver/model/LoginForm.java rename src/main/java/{ => bejavawebserver}/model/User.java (96%) rename src/main/java/{db/Database.java => bejavawebserver/repository/memoryRepository.java} (67%) create mode 100644 src/main/java/bejavawebserver/service/HtmlService.java create mode 100644 src/main/java/bejavawebserver/service/ListService.java create mode 100644 src/main/java/bejavawebserver/service/LoginService.java create mode 100644 src/main/java/bejavawebserver/service/SignUpService.java delete mode 100644 src/main/java/controller/Controller.java delete mode 100644 src/main/java/controller/HtmlController.java delete mode 100644 src/main/java/controller/StaticFileController.java delete mode 100644 src/main/java/controller/UserController.java delete mode 100644 src/main/java/db/Session.java delete mode 100644 src/main/java/http/HttpHeader.java delete mode 100644 src/main/java/http/HttpStatus.java delete mode 100644 src/main/java/http/HttpUri.java delete mode 100644 src/main/java/http/exception/DuplicateSignUpUserException.java delete mode 100644 src/main/java/http/exception/NullHttpRequestException.java delete mode 100644 src/main/java/http/request/HttpRequest.java delete mode 100644 src/main/java/http/request/HttpRequestLine.java delete mode 100644 src/main/java/http/response/HttpResponse.java delete mode 100644 src/main/java/http/response/HttpStatusLine.java delete mode 100644 src/main/java/service/HtmlService.java delete mode 100644 src/main/java/service/ListService.java delete mode 100644 src/main/java/service/LogInService.java delete mode 100644 src/main/java/service/SignUpService.java delete mode 100644 src/main/java/service/StaticFileService.java delete mode 100644 src/main/java/util/HttpRequestUtils.java delete mode 100644 src/main/java/util/HttpResponseUtils.java delete mode 100644 src/main/java/webserver/ControllerHandler.java delete mode 100644 src/main/java/webserver/RequestHandler.java delete mode 100644 src/main/java/webserver/WebServer.java create mode 100644 src/main/resources/application.properties delete mode 100644 src/test/java/HtmlServiceTest.java delete mode 100644 src/test/java/HttpRequestUtilsTest.java delete mode 100644 src/test/java/HttpResponseUtilsTest.java delete mode 100644 src/test/java/ListServiceTest.java delete mode 100644 src/test/java/LogInServiceTest.java delete mode 100644 src/test/java/SignUpServiceTest.java delete mode 100644 src/test/java/StaticFileServiceTest.java create mode 100644 src/test/java/bejavawebserver/WebserverApplicationTests.java diff --git a/.gitignore b/.gitignore index b7fa2d85..c2065bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,204 +1,37 @@ -# Created by https://www.toptal.com/developers/gitignore/api/macos,windows,intellij+all,gradle,java -# Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows,intellij+all,gradle,java - -### Intellij+all ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij+all Patch ### -# Ignore everything but code style settings and run configurations -# that are supposed to be shared within teams. - -.idea/* - -!.idea/codeStyles -!.idea/runConfigurations - -### Java ### -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### macOS Patch ### -# iCloud generated files -*.icloud - -### Windows ### -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -### Gradle ### +HELP.md .gradle -**/build/ -!src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Avoid ignore Gradle wrappper properties -!gradle-wrapper.properties - -# Cache of project -.gradletasknamecache +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ -# Eclipse Gradle plugin generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) +### STS ### +.apt_generated .classpath - -### Gradle Patch ### -# Java heap dump -*.hprof - -# End of https://www.toptal.com/developers/gitignore/api/macos,windows,intellij+all,gradle,java +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/README.md b/README.md index 74ec11d4..f04c5898 100644 --- a/README.md +++ b/README.md @@ -2,241 +2,46 @@ Java Web Application Server 2022 -## 프로젝트 정보 +## 프로젝트 정보 -이 프로젝트는 우아한 테크코스 박재성님의 허가를 받아 https://github.com/woowacourse/jwp-was +이 프로젝트는 우아한 테크코스 박재성님의 허가를 받아 https://github.com/woowacourse/jwp-was 를 참고하여 작성되었습니다. -## 프로젝트 구조 - ├── controller - │   ├── Controller.java - │   ├── HtmlController.java - │   ├── StaticFileController.java - │   └── UserController.java - ├── db - │   ├── Database.java - │   └── Session.java - ├── http - │   ├── HttpHeader.java - │   ├── HttpStatus.java - │   ├── HttpUri.java - │   ├── exception - │   │   └── NullHttpRequestException.java - │   ├── request - │   │   ├── HttpRequest.java - │   │   └── HttpRequestLine.java - │   └── response - │   ├── HttpResponse.java - │   └── HttpStatusLine.java - ├── model - │   └── User.java - ├── service - │   ├── HtmlService.java - │   ├── ListService.java - │   ├── LogInService.java - │   ├── SignUpService.java - │   └── StaticFileService.java - ├── util - │   ├── HttpRequestUtils.java - │   └── HttpResponseUtils.java - └── webserver - ├── ControllerHandler.java - ├── RequestHandler.java - └── WebServer.java - -+ RequestHandler - + HttpRequest 클래스에 입력을 받고 받은 URI로 알맞는 컨트롤러를 골라준다. 고른 컨트롤러로 응답을 만들고 응답을 출력해준다. -+ ControllerHandler - + Post 요청인 경우를 먼저 확인 - 회원 가입과 로그인을 처리하는 UserController를 리턴 - + Html 파일 요청인 경우인지 확인 - Html파일을 처리하는 HtmlController를 리턴 - + 나머지인 경우 (정적 파일) - 정적 파일을 처리하는 StaticFileController를 리턴 -+ UserController - + HttpRequest 객체로부터 uri와 httpVersion을 받아온다. - + HttpRequest body의 query string을 파싱해서 Map 객체인 params에 넣어준다. - + 회원 가입 요청인 경우와 로그인 요청인 경우를 나누어 준다. - + 각각 params와 httpVersion을 나누어 주며 회원가입일 경우 SignUpService, 로그인일 경우 LogInService를 통해 응답을 생성해 준다. - + 생성된 응답 HttpResponse 객체를 리턴한다. -+ HtmlController - + HttpRequest 객체로부터 로그인 유저 정보, ContentType, 파일 경로, uri를 받는다. - + 유저 리스트 출력 html일 경우 ListService를 통해 응답 생성 - + index.html 로그인 상태일 경우 HtmlService를 통해 응답 생성 - + index.html 로그인 상태가 아닐 경우 정적 파일 요청이므로 StaticFileService를 통해 응답을 생성한다. - + 생성된 응답 HttpResponse 객체를 리턴한다. -+ StaticFileController - + 정적 파일들은 모두 /static 폴더 내에 있으므로 기본 파일 경로를 설정해준다. - + 설정해준 파일 경로에 HttpResquest객체로부터 받은 uri를 더해서 정적 파일 경로를 만들어준다. - + 만들어진 파일 경로로 StaticFileService를 통해 응답을 생성한다. - + 생성된 응답 HttpResponse 객체를 리턴한다. - - ## 프로젝트 학습 내용 -### 2주차 ++ lombok @Data + + 종합 선물 세트 ! + + @Getter/@Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 다 들어있음 + + @EqualsAndHashCode + + equals() 메소드와 hashCode() 메소드 자동 생성 + + hashCode() : 런타임 중 객체의 유일한 integer 값을 반환하는 함수 + + @RequiredArgsConstructor + + 초기화 되지 않은 final 필드나 @NonNull 어노테이션이 붙은 필드에 대해 생성자를 만들어 준다. + + @AllArgsConstructor, @NoArgsConstructor ++ Session method + + session.setAttribute(이름, 값) + + session.getAttribute(이름) + + 리턴 타입이 Object이므로 형 변환이 필요 ++ Thymeleaf +```HTML +
  • +
  • 로그인
  • +
  • 회원가입
  • +``` + + html 태그로 불리안, 변수 가능 + + model 객체를 통해 삽입 +```java + model.addAttribute("userName", loginUser.getName()); + model.addAttribute("isLogin", true); +``` ++ gradle dependencies + + runtimeOnly / compileOnly + + compileOnly - 컴파일 시점에 꼭 필요한 라이브러리 + + runtimeOnly - 컴파일 시점에는 필요 없지만 실행 시점에는 꼭 필요한 라이브러리 ---- - + Day 6 - + InputStream > InputStreamReader > BufferedReader로 Http Request Header 가져오기 - ``` java - try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); - ``` - + BufferedReader.readLine() 메소드를 활용해 모든 Http header 출력 - + Header의 첫 번째 라인에서 요청 URL을 추출 - + Path에 해당하는 파일을 응답하기 - ``` java - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./src/main/resources/templates/" + url).toPath()); - ``` - + 유틸 클래스 (HttpRequestUtils) 생성 및 리팩토링 - + 테스트 코드 추가 - ``` java - @Test - public void getUrl(){ - String url = HttpRequestUtils.getUrl("GET /index.html HTTP/1.1"); - assertThat(url).isEqualTo("/index.html"); - } - ``` - + 회원가입 요청 url 처리 - split 함수 활용(? split > & split > = split 처리) - + 테스트 코드 추가 - - + http request stream에 한글이 있을 경우가 있으므로 parseQueryString 메소드에서 UTF_8 형식으로 변경 - ``` java - requestParamsMap.put(requestParam[0], URLDecoder.decode(requestParam[1], StandardCharsets.UTF_8)); - ``` - --- - + Day 7 - + Refactoring : http 폴더 생성 후 필요한 클래스 생성 - + Http Request Header의 구조 - + GET /index.html HTTP/1.1 - 시작줄(method, uri, version) - + Host: localhost:8080 - 헤더 - + Connection: keep-alive - 헤더 - + .... - + .trim() 함수: 문자열의 시작과 끝 공백 제거 - --- - + Day 8 - + Entry를 활용한 May 순회 방법 - ```java - Map map = new HashMap<>(); - for (Map.Entry entry : map.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - } - ``` - + split() 메소드에 정규 표현식의 예약어 사용 - + 이스케이프 문자 사용 - ```java - split("\\?") - ``` - + Pattern.quote() 메소드 사용 - ```java - split(Pattern.quote("?")); - ``` - --------- - + Day 9 - + MIME Type - + 인코딩(Encoding): text 파일로 변환 - + 디코딩(Decoding): text 파일을 바이너리 파일로 변환 - + Type : text, image, audio, video, application - + subType : .avi, .bin, .css, .csv, .ico 등등.. - + Type/subType -> text/html, text/css .. - - + HTTP 302 FOUND response - + 회원 가입 성공 시 - 기존의 성공 메세지와 회원 가입 정보를 byte화해서 body로 넘겨주던 로직을 - 302 FOUND로 넘겨주었다 - + 302 Header - + HTTP/1.1 302 FOUND - + location: /index.html - + location은 응답코드 301, 302 리다이렉션 상태에서 위치를 지정해준다 - + Java 객체 비교 - + ==, != 연산자 - + Primitive type를 비교할 때는 value값을 비교 - + Object를 비교할 때는 메모리 주소 비교 - + equals() 사용 - + Objects.equals(a, b) 도 가능 (null check가 되어 있음) - - + Http Response 의 Status Line - + HTTP version + Status code + Status text 로 구성 - ``` - HTTP/1.1 404 NOT FOUND - ``` - - + Java Unit Test 작성 - + given/when/then 패턴으로 깔끔하게 - + 어떤 데이터가 준비되었을 때 어떤 함수를 실행하면 어떤 결과가 나와야 한다. - ```java - @Test - @DisplayName("테스트 이름") - void test() { - // given - final String str = "test string" - - // when - final String result = 테스트할클래스.method(str); - - // then - assertThat(result).isEqualTo("예상되는 결과"); - } - ``` -------------- - + Day 11 - + HTTP POST 방식 - + POST 방식은 데이터 전송을 기반으로 한 요청 메서드 - + GET 방식은 URL에 데이터를 붙여서 보내지만 POST 방식은 BODY에 데이터를 넣어 보냄 - + 그래서 POST 방식에는 Content-Type 헤더 필드가 있음 - + ex) application/x-www-form-urlencoded, text/plain, multipart/form-data - + POST Request 예시) - ``` - POST /user/create HTTP/1.1 - Host: localhost:8080 - Connection: keep-alive - Content-Length: 59 - Content-Type: application/x-www-form-urlencoded - Accept: */* - - userId=javajigi&password=password&name=%EB%B0%95%EC%9E%AC%EC%84%B1&email=javajigi%40slipp.net - ``` - + JAVA 생성 패턴 [Builder 패턴] - + 많은 Optional한 멤버 변수(파라미터)나 지속성 없는 상태 값들 처리 문제 해결 - + 구현 방법 - + 빌더 클래스를 Static Nested Class로 생성 - 관례적으로 클래스 이름 + Builder로 명명 - + 생성자는 public, 파라미터는 필수 값들 - + Optional한 값들은 속성마다 메소드로 제공, 리턴 값이 빌더 객체 자신이어야 함 - + 마지막으로 빌더 클래스 내에 build()메소드를 정의하여 최종 생성된 결과물 리턴, - builder를 통해서만 객체 생성을 하므로 생성 대상이 되는 클래스의 생성자는 private ------------ - + Day 12 - + 쿠키와 세션 - + 서버는 Set-Cookie header 값으로 상태를 유지하고 싶은 값을 클라이언트에 전송 - + 클라이언트는 받은 쿠키 값을 모든 요청의 쿠키 헤더로 서버에 전송 - + 서버는 쿠키 헤더에 따라 이전 접속자인지 확인! - ------------ - + Day 13 - + Servlet - + Java 언어로 작성된 웹 애플리케이션의 컴포넌트 - + 서버 측에서 실행되며 http 요청을 처리 - + 클라이언트의 요청을 처리하고 응답을 생성 + + + ------------- - + Day 14 - + stateful과 stateless - + stateful - + 상태 유지 : 서버가 클라이언트의 상태를 보존한다. - + 대표적으로 TCP의 3-way handshaking - + 문제점 : 해당 서버를 못쓰게 되어 다른 서버를 사용해야 할 때 발생 - 이전 서버의 정보가 없음 - + 문제점 해결 : 현업에서는 캐시 서버 Redis 사용 - + stateless - + 서버가 클라이언트의 상태를 보존하지 않음. - + 요청이 오면 바로 응답을 보내며 상태 관리는 클라이언트에서 책임을 짐. - + 대량의 트래픽이 발생했을 때에도 서버 확장을 통해 대처를 수월하게 할 수 있음. - + (stateful과 다르게 서버가 바뀌어도 정확한 응답에 문제가 없기 때문) - + 대표적으로 UDP와 HTTP - + 문제점 : 더 많은 데이터 소모 - 매번 요청할 때마다 부가정보 필요 - + wrapper class - + 기본 자료타입을 객체로 다루기 위해서 사용하는 클래스 - + git diff - + add 전과 후의 파일 내용을 비교해줌 \ No newline at end of file diff --git a/build.gradle b/build.gradle index a92f231c..b3b525f0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,33 +1,31 @@ plugins { - id 'java' - id 'idea' + id 'java' + id 'org.springframework.boot' version '2.7.8' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' } -group 'codesquad' -version '1.0-SNAPSHOT' -sourceCompatibility = 11 +group = 'com.example' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '11' repositories { - mavenCentral() + mavenCentral() } dependencies { + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.jetbrains:annotations:23.0.0' + testImplementation 'org.springframework.boot:spring-boot-starter-test' - implementation 'ch.qos.logback:logback-classic:1.2.3' - implementation 'com.google.guava:guava:29.0-jre' - implementation 'ch.qos.logback:logback-classic:1.2.3' - implementation 'com.github.jknack:handlebars:4.2.0' + // lombok 추가 + implementation 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok:1.18.22' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' - testImplementation 'org.assertj:assertj-core:3.16.1' - -} - -test { - useJUnitPlatform() + // mysql + implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.0.32' } -repositories { - mavenCentral() +tasks.named('test') { + useJUnitPlatform() } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10158 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 delta 9041 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a97150..070cb702 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 744e882e..a69d9cb6 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,101 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd32..f127cfd4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/settings.gradle b/settings.gradle index 16578da2..a5e82971 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1 @@ -rootProject.name = 'java-was-2022' - +rootProject.name = 'be-java-web-server' diff --git a/src/main/java/bejavawebserver/WebserverApplication.java b/src/main/java/bejavawebserver/WebserverApplication.java new file mode 100644 index 00000000..e15e927b --- /dev/null +++ b/src/main/java/bejavawebserver/WebserverApplication.java @@ -0,0 +1,13 @@ +package bejavawebserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WebserverApplication { + + public static void main(String[] args) { + SpringApplication.run(WebserverApplication.class, args); + } + +} diff --git a/src/main/java/bejavawebserver/controller/HomeController.java b/src/main/java/bejavawebserver/controller/HomeController.java new file mode 100644 index 00000000..285db67f --- /dev/null +++ b/src/main/java/bejavawebserver/controller/HomeController.java @@ -0,0 +1,13 @@ +package bejavawebserver.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.SessionAttribute; + +@Controller +public class HomeController { + @GetMapping("/") + public String home(){ + return "index"; + } +} diff --git a/src/main/java/bejavawebserver/controller/HtmlController.java b/src/main/java/bejavawebserver/controller/HtmlController.java new file mode 100644 index 00000000..471cc3d3 --- /dev/null +++ b/src/main/java/bejavawebserver/controller/HtmlController.java @@ -0,0 +1,54 @@ +package bejavawebserver.controller; + +import bejavawebserver.model.User; +import bejavawebserver.repository.memoryRepository; +import bejavawebserver.service.HtmlService; +import bejavawebserver.service.ListService; +import bejavawebserver.service.LoginService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +@Controller +public class HtmlController { + //@GetMapping("/index.html") + + @GetMapping(value = { + "/index.html", + "/qna/form.html", + "/qna/show.html", + "/user/form.html", + "/user/login.html", + "/user/login_failed.html", + "/user/profile.html"}) + public String indexHtml(HttpServletRequest httpServletRequest, Model model){ + HttpSession session = httpServletRequest.getSession(false); + String uri = httpServletRequest.getRequestURI(); + + // 로그인 상태인 경우 + if(LoginService.isLogin(session)) { + return HtmlService.makeLoginView(model, uri, (User)session.getAttribute("user")); + } + // 로그인 상태가 아닌 경우 + return HtmlService.makeNotLoginView(model, uri); + } + + @GetMapping("/user/list.html") + public String listHtml(HttpServletRequest httpServletRequest, Model model){ + HttpSession session = httpServletRequest.getSession(false); + String uri = httpServletRequest.getRequestURI(); + + // 로그인 상태인 경우 + if(LoginService.isLogin(session)) return ListService.makeUserList(model, uri, (User)session.getAttribute("user")); + + // 로그인 상태가 아닌 경우 + return "redirect:/user/login.html"; + + } +} diff --git a/src/main/java/bejavawebserver/controller/UserController.java b/src/main/java/bejavawebserver/controller/UserController.java new file mode 100644 index 00000000..fc2cfb1c --- /dev/null +++ b/src/main/java/bejavawebserver/controller/UserController.java @@ -0,0 +1,32 @@ +package bejavawebserver.controller; + +import bejavawebserver.model.LoginForm; +import bejavawebserver.model.User; +import bejavawebserver.service.LoginService; +import bejavawebserver.service.SignUpService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; + +import javax.servlet.http.HttpSession; + +@Controller +public class UserController { + @PostMapping("/user/create") + public String signUp(User user){ + try{ + SignUpService.addDatabase(user); + }catch (RuntimeException r){ + return "redirect:/user/form.html"; + } + return "redirect:/"; + } + + @PostMapping("/user/login") + public String login(LoginForm loginForm, HttpSession session){ + if(LoginService.isLoginSuccess(loginForm, session)){ + return "redirect:/index.html"; + } + return "redirect:/user/login_failed.html"; + } + +} diff --git a/src/main/java/bejavawebserver/model/LoginForm.java b/src/main/java/bejavawebserver/model/LoginForm.java new file mode 100644 index 00000000..9cace722 --- /dev/null +++ b/src/main/java/bejavawebserver/model/LoginForm.java @@ -0,0 +1,12 @@ +package bejavawebserver.model; + +import lombok.Data; +import lombok.NonNull; + +@Data +public class LoginForm { + @NonNull + private final String userId; + @NonNull + private final String password; +} diff --git a/src/main/java/model/User.java b/src/main/java/bejavawebserver/model/User.java similarity index 96% rename from src/main/java/model/User.java rename to src/main/java/bejavawebserver/model/User.java index 4f116754..7c3ccb1c 100644 --- a/src/main/java/model/User.java +++ b/src/main/java/bejavawebserver/model/User.java @@ -1,4 +1,4 @@ -package model; +package bejavawebserver.model; public class User { private final String userId; diff --git a/src/main/java/db/Database.java b/src/main/java/bejavawebserver/repository/memoryRepository.java similarity index 67% rename from src/main/java/db/Database.java rename to src/main/java/bejavawebserver/repository/memoryRepository.java index cb5122d6..565cfa78 100644 --- a/src/main/java/db/Database.java +++ b/src/main/java/bejavawebserver/repository/memoryRepository.java @@ -1,16 +1,16 @@ -package db; +package bejavawebserver.repository; -import com.google.common.collect.Maps; -import model.User; +import bejavawebserver.model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; +import java.util.HashMap; import java.util.Map; -public class Database { - private static final Logger logger = LoggerFactory.getLogger(Database.class); - private static final Map users = Maps.newHashMap(); +public class memoryRepository { + private static final Logger logger = LoggerFactory.getLogger(memoryRepository.class); + private static final Map users = new HashMap<>(); public static void addUser(User user) { logger.debug("Database User input : {}", user); @@ -26,6 +26,6 @@ public static Collection findAll() { } public static boolean checkDuplicate(User user) { - return users.get(user.getUserId()) == null; + return users.get(user.getUserId()) != null; } } diff --git a/src/main/java/bejavawebserver/service/HtmlService.java b/src/main/java/bejavawebserver/service/HtmlService.java new file mode 100644 index 00000000..69c94d3b --- /dev/null +++ b/src/main/java/bejavawebserver/service/HtmlService.java @@ -0,0 +1,29 @@ +package bejavawebserver.service; + +import bejavawebserver.controller.HtmlController; +import bejavawebserver.model.User; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpSession; + +@Service +public class HtmlService { + private static final Logger logger = LoggerFactory.getLogger(HtmlController.class); + public static String makeNotLoginView(Model model, String uri){ + logger.debug("현재 로그인 상태 아님"); + model.addAttribute("isLogin", false); + return uri; + } + + + public static String makeLoginView(Model model, String uri, User loginUser) { + logger.debug("현재 로그인 상태임"); + model.addAttribute("userName", loginUser.getName()); + model.addAttribute("isLogin", true); + + return uri; + } +} diff --git a/src/main/java/bejavawebserver/service/ListService.java b/src/main/java/bejavawebserver/service/ListService.java new file mode 100644 index 00000000..eed17d5a --- /dev/null +++ b/src/main/java/bejavawebserver/service/ListService.java @@ -0,0 +1,20 @@ +package bejavawebserver.service; + +import bejavawebserver.model.User; +import bejavawebserver.repository.memoryRepository; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; + +import javax.servlet.http.HttpSession; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Service +public class ListService { + public static String makeUserList(Model model, String uri, User loginUser){ + List userList = new ArrayList<>(memoryRepository.findAll()); + model.addAttribute("userList", userList); + return HtmlService.makeLoginView(model, uri, loginUser); + } +} diff --git a/src/main/java/bejavawebserver/service/LoginService.java b/src/main/java/bejavawebserver/service/LoginService.java new file mode 100644 index 00000000..2e7a9b69 --- /dev/null +++ b/src/main/java/bejavawebserver/service/LoginService.java @@ -0,0 +1,22 @@ +package bejavawebserver.service; + +import bejavawebserver.model.LoginForm; +import bejavawebserver.model.User; +import bejavawebserver.repository.memoryRepository; + +import javax.servlet.http.HttpSession; +import java.util.Objects; + +public class LoginService { + public static boolean isLoginSuccess(LoginForm loginForm, HttpSession session) { + User user = memoryRepository.findUserById(loginForm.getUserId()); + session.setAttribute("user", user); + return Objects.equals(user.getPassword(), loginForm.getPassword()); + } + + public static boolean isLogin(HttpSession session) { + return session != null; + } + + +} diff --git a/src/main/java/bejavawebserver/service/SignUpService.java b/src/main/java/bejavawebserver/service/SignUpService.java new file mode 100644 index 00000000..fa60818c --- /dev/null +++ b/src/main/java/bejavawebserver/service/SignUpService.java @@ -0,0 +1,13 @@ +package bejavawebserver.service; + +import bejavawebserver.repository.memoryRepository; +import bejavawebserver.model.User; +import org.springframework.stereotype.Service; + +@Service +public class SignUpService { + public static void addDatabase(User user) { + if(memoryRepository.checkDuplicate(user)) throw new RuntimeException("중복된 사용자가 있습니다."); + memoryRepository.addUser(user); + } +} diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java deleted file mode 100644 index 6b6c458c..00000000 --- a/src/main/java/controller/Controller.java +++ /dev/null @@ -1,8 +0,0 @@ -package controller; - -import http.request.HttpRequest; -import http.response.HttpResponse; - -public interface Controller { - HttpResponse makeResponse(HttpRequest httpRequest); -} diff --git a/src/main/java/controller/HtmlController.java b/src/main/java/controller/HtmlController.java deleted file mode 100644 index fc87ffef..00000000 --- a/src/main/java/controller/HtmlController.java +++ /dev/null @@ -1,40 +0,0 @@ -package controller; - -import db.Database; -import db.Session; -import http.request.HttpRequest; -import http.response.HttpResponse; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import service.HtmlService; -import service.ListService; -import service.StaticFileService; - -public class HtmlController implements Controller { - private static final Logger logger = LoggerFactory.getLogger(HtmlController.class); - private static final String htmlFilePath = "./src/main/resources/templates"; - - @Override - public HttpResponse makeResponse(HttpRequest httpRequest) { - //로그인한 유저 ContentType, 파일 경로, uri를 받음 - User logInUser = Database.findUserById(Session.findUserIdBySessionId(httpRequest.getCookie())); - String contentType = httpRequest.getContentType(); - String filePath = htmlFilePath + httpRequest.getUri(); - String httpVersion = httpRequest.getHttpVersion(); - - // list service - if (httpRequest.getUri().equals("/user/list.html")) - return ListService.service( - logInUser, filePath, httpVersion, contentType); - - // index.html service 로그인 O - if (httpRequest.isLogin()) - return HtmlService.service( - filePath, logInUser, httpVersion, contentType); - - // index.html service 로그인 X - return StaticFileService.service( - filePath, httpVersion, contentType); - } -} diff --git a/src/main/java/controller/StaticFileController.java b/src/main/java/controller/StaticFileController.java deleted file mode 100644 index c23410d5..00000000 --- a/src/main/java/controller/StaticFileController.java +++ /dev/null @@ -1,19 +0,0 @@ -package controller; - -import http.request.HttpRequest; -import http.response.HttpResponse; -import service.StaticFileService; - -public class StaticFileController implements Controller { - private static final String staticFilePath = "./src/main/resources/static"; - - @Override - public HttpResponse makeResponse(HttpRequest httpRequest) { - String filePath = staticFilePath + httpRequest.getUri(); - return StaticFileService.service( - filePath, - httpRequest.getHttpVersion(), - httpRequest.getContentType()); - - } -} diff --git a/src/main/java/controller/UserController.java b/src/main/java/controller/UserController.java deleted file mode 100644 index 0a40bbcf..00000000 --- a/src/main/java/controller/UserController.java +++ /dev/null @@ -1,46 +0,0 @@ -package controller; - -import http.request.HttpRequest; -import http.response.HttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import service.LogInService; -import service.SignUpService; -import util.HttpRequestUtils; - -import java.util.Map; - -public class UserController implements Controller { - private static final Logger logger = LoggerFactory.getLogger(UserController.class); - - @Override - public HttpResponse makeResponse(HttpRequest httpRequest) { - // Uri, httpVersion 받아옵시다 - String uri = httpRequest.getUri(); - String httpVersion = httpRequest.getHttpVersion(); - // body 에서 params 분리 - Map params = HttpRequestUtils.parseQueryString(httpRequest.getBody()); - - // 회원가입일 때 - if (isSignUpService(uri)) { - return SignUpService.service(params, httpVersion); - } - - // 로그인일 때 - if (isLoginService(uri)) { - return LogInService.service(params, httpVersion); - } - - //TODO 임시 코드 - return 예외처리 해야됨 - return null; - } - - public boolean isSignUpService(String uri) { - return uri.equals("/user/create"); - } - - public boolean isLoginService(String uri) { - return uri.equals("/user/login"); - } - -} diff --git a/src/main/java/db/Session.java b/src/main/java/db/Session.java deleted file mode 100644 index 8f2c5837..00000000 --- a/src/main/java/db/Session.java +++ /dev/null @@ -1,30 +0,0 @@ -package db; - -import com.google.common.collect.Maps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.Map; -import java.util.UUID; - -public class Session { - private static final Logger logger = LoggerFactory.getLogger(Session.class); - private static final Map sessions = Maps.newHashMap(); - - public static String makeSessionIdAndAddUserId(String userId) { - String sessionId = UUID.randomUUID().toString(); - logger.debug("Session User Input : userId = {}", userId + " sessionId = " + sessionId); - sessions.put(sessionId, userId); - return sessionId; - } - - public static String findUserIdBySessionId(String sessionId) { - return sessions.get(sessionId); - } - - public static Collection findAll() { - return sessions.values(); - } - -} diff --git a/src/main/java/http/HttpHeader.java b/src/main/java/http/HttpHeader.java deleted file mode 100644 index 9c165f64..00000000 --- a/src/main/java/http/HttpHeader.java +++ /dev/null @@ -1,49 +0,0 @@ -package http; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class HttpHeader { - - private final Map headers = new HashMap<>(); - - public HttpHeader(List headers) { - for (String header : headers) { - String[] splitedHeader = header.split(":"); - String key = splitedHeader[0].trim(); - String value = splitedHeader[1].trim(); - this.headers.put(key, value); - } - } - - public void addHeader(String headerKey, String headerValue) { - headers.put(headerKey, headerValue); - } - - public String toString() { - String headerString = ""; - for (Map.Entry header : headers.entrySet()) { - headerString += header.getKey() + ": " + header.getValue() + System.lineSeparator(); - } - headerString += System.lineSeparator(); - return headerString; - } - - public String getAccept() { - return headers.get("Accept"); - } - - - public String getContentLength() { - return headers.get("Content-Length"); - } - - public String getCookie() { - return headers.get("Cookie"); - } - - public String getLocation() { - return headers.get("Location"); - } -} diff --git a/src/main/java/http/HttpStatus.java b/src/main/java/http/HttpStatus.java deleted file mode 100644 index 53c78f77..00000000 --- a/src/main/java/http/HttpStatus.java +++ /dev/null @@ -1,27 +0,0 @@ -package http; - -import java.util.Arrays; - -public enum HttpStatus { - OK(200, "OK"), - FOUND(302, "FOUND"); - - private final int statusCode; - private final String status; - - HttpStatus(int statusCode, String status) { - this.statusCode = statusCode; - this.status = status; - } - - public static HttpStatus of(int statusCode) { - return Arrays.stream(HttpStatus.values()) - .filter(httpStatus -> httpStatus.statusCode == statusCode) - .findAny() - .orElseThrow(); - } - - public String toString() { - return statusCode + " " + status; - } -} diff --git a/src/main/java/http/HttpUri.java b/src/main/java/http/HttpUri.java deleted file mode 100644 index c0a90556..00000000 --- a/src/main/java/http/HttpUri.java +++ /dev/null @@ -1,21 +0,0 @@ -package http; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HttpUri { - private static final Logger logger = LoggerFactory.getLogger(HttpUri.class); - private final String uri; - - public HttpUri(String uri) { - this.uri = uri; - } - - public String getUri() { - return uri; - } - - public String getFileNameExtension() { - return uri.substring(uri.lastIndexOf(".") + 1); - } -} diff --git a/src/main/java/http/exception/DuplicateSignUpUserException.java b/src/main/java/http/exception/DuplicateSignUpUserException.java deleted file mode 100644 index 9e846c52..00000000 --- a/src/main/java/http/exception/DuplicateSignUpUserException.java +++ /dev/null @@ -1,7 +0,0 @@ -package http.exception; - -public class DuplicateSignUpUserException extends RuntimeException { - public DuplicateSignUpUserException(String message) { - super(message); - } -} diff --git a/src/main/java/http/exception/NullHttpRequestException.java b/src/main/java/http/exception/NullHttpRequestException.java deleted file mode 100644 index d69842af..00000000 --- a/src/main/java/http/exception/NullHttpRequestException.java +++ /dev/null @@ -1,7 +0,0 @@ -package http.exception; - -public class NullHttpRequestException extends RuntimeException { - public NullHttpRequestException(String message) { - super(message); - } -} diff --git a/src/main/java/http/request/HttpRequest.java b/src/main/java/http/request/HttpRequest.java deleted file mode 100644 index 16d67534..00000000 --- a/src/main/java/http/request/HttpRequest.java +++ /dev/null @@ -1,68 +0,0 @@ -package http.request; - -import db.Session; -import http.HttpHeader; -import http.exception.NullHttpRequestException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import util.HttpRequestUtils; - -import java.io.BufferedReader; -import java.io.IOException; - -public class HttpRequest { - private static final Logger logger = LoggerFactory.getLogger(HttpRequest.class); - private final HttpRequestLine httpRequestLine; - private final HttpHeader httpHeader; - private String body; - - public HttpRequest(BufferedReader br) throws IOException { - String line = br.readLine(); - if (line == null) throw new NullHttpRequestException("빈 http request !!================"); - this.httpRequestLine = HttpRequestUtils.readRequestLine(line); - this.httpHeader = HttpRequestUtils.readHeaders(br); - if (httpRequestLine.getHttpMethod().equals("POST")) this.body = HttpRequestUtils.readBody(br, httpHeader); - } - - public String getUri() { - return this.httpRequestLine.getHttpUri().getUri(); - } - - public String getContentType() { - logger.debug("Accept : {}", httpHeader.getAccept()); - return httpHeader.getAccept().split(",")[0]; - } - - public String getHttpVersion() { - return httpRequestLine.getHttpVersion(); - } - - public boolean isPost() { - //logger.debug("HTTP method : {}", httpRequestLine.getHttpMethod()); - return this.httpRequestLine.getHttpMethod().equals("POST"); - } - - public String getBody() { - return this.body; - } - - public String getFileNameExtension() { - return httpRequestLine.getHttpUri().getFileNameExtension(); - } - - public String getCookie() { - logger.debug("Cookie : {}", httpHeader.getCookie()); - String cookie = httpHeader.getCookie(); - if (cookie == null) return null; - return HttpRequestUtils.parseQueryString(httpHeader.getCookie()).get("sid"); - } - - public boolean wantHtml() { - return getFileNameExtension().equals("html"); - } - - public boolean isLogin() { - // userId가 null 이 아닌 경우 login 상태임 ! - return Session.findUserIdBySessionId(getCookie()) != null; - } -} diff --git a/src/main/java/http/request/HttpRequestLine.java b/src/main/java/http/request/HttpRequestLine.java deleted file mode 100644 index 9ba989cf..00000000 --- a/src/main/java/http/request/HttpRequestLine.java +++ /dev/null @@ -1,27 +0,0 @@ -package http.request; - -import http.HttpUri; - -public class HttpRequestLine { - private final String method; - private final HttpUri uri; - private final String version; - - public HttpRequestLine(String method, HttpUri uri, String version) { - this.method = method; - this.uri = uri; - this.version = version; - } - - public HttpUri getHttpUri() { - return this.uri; - } - - public String getHttpVersion() { - return version; - } - - public String getHttpMethod() { - return method; - } -} diff --git a/src/main/java/http/response/HttpResponse.java b/src/main/java/http/response/HttpResponse.java deleted file mode 100644 index f856b717..00000000 --- a/src/main/java/http/response/HttpResponse.java +++ /dev/null @@ -1,95 +0,0 @@ -package http.response; - -import http.HttpHeader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import util.HttpResponseUtils; - -import java.io.DataOutputStream; -import java.io.IOException; - -public class HttpResponse { - private static final Logger logger = LoggerFactory.getLogger(HttpResponse.class); - private final HttpStatusLine statusLine; - private final HttpHeader header; - private final byte[] body; - - private HttpResponse(HttpResponseBuilder httpResponseBuilder) { - this.statusLine = httpResponseBuilder.httpStatusLine; - this.body = httpResponseBuilder.body; - this.header = httpResponseBuilder.header; - } - - public byte[] getBody() { - return body; - } - - public HttpHeader getHeaders() { - return header; - } - - public void send(DataOutputStream dos) throws IOException { - responseHeader(dos); - responseBody(dos); - } - - private void responseHeader(DataOutputStream dos) { - try { - logger.debug("send : {}", statusLine.toStringForResponse()); - logger.debug("send : {}", header.toString()); - dos.writeBytes(statusLine.toStringForResponse()); - dos.writeBytes(header.toString()); - } catch (IOException e) { - logger.error(e.getMessage()); - } - } - - private void responseBody(DataOutputStream dos) { - try { - if (body != null) dos.write(body, 0, body.length); - dos.flush(); - } catch (IOException e) { - logger.error(e.getMessage()); - } - } - - public static class HttpResponseBuilder { - private HttpStatusLine httpStatusLine; - private byte[] body; - private HttpHeader header; - - public HttpResponseBuilder() { - } - - public HttpResponseBuilder setHttpStatusLine(HttpStatusLine httpStatusLine) { - this.httpStatusLine = httpStatusLine; - return this; - } - - public HttpResponseBuilder set200Header(String contentType, byte[] body) { - this.header = HttpResponseUtils.makeResponse200Header(contentType, body.length); - this.body = body; - return this; - } - - public HttpResponseBuilder set302Header(String destination) { - this.header = HttpResponseUtils.makeResponse302Header(destination); - return this; - } - - public HttpResponseBuilder setBody(byte[] body) { - this.body = body; - return this; - } - - public HttpResponseBuilder addCookie(String cookieValue) { - this.header.addHeader("Set-Cookie", "sid=" + cookieValue + "; Path=/"); - return this; - } - - public HttpResponse build() { - return new HttpResponse(this); - } - - } -} diff --git a/src/main/java/http/response/HttpStatusLine.java b/src/main/java/http/response/HttpStatusLine.java deleted file mode 100644 index 8770136b..00000000 --- a/src/main/java/http/response/HttpStatusLine.java +++ /dev/null @@ -1,18 +0,0 @@ -package http.response; - -import http.HttpStatus; - -public class HttpStatusLine { - HttpStatus httpStatus; - String httpVersion; - - public HttpStatusLine(HttpStatus status, String httpVersion) { - httpStatus = status; - this.httpVersion = httpVersion; - } - - public String toStringForResponse() { - return httpVersion + " " + httpStatus.toString() + System.lineSeparator(); - } - -} diff --git a/src/main/java/service/HtmlService.java b/src/main/java/service/HtmlService.java deleted file mode 100644 index 87e7bebd..00000000 --- a/src/main/java/service/HtmlService.java +++ /dev/null @@ -1,34 +0,0 @@ -package service; - -import http.HttpStatus; -import http.response.HttpResponse; -import http.response.HttpStatusLine; -import model.User; -import util.HttpResponseUtils; - -public class HtmlService { - public static HttpResponse service(String filePath, User logInUser, String httpVersion, String contentType) { - - // 파일 경로를 넘겨서 http response string 생성 - String responseString = new String(HttpResponseUtils.makeBody(filePath)); - byte[] responseBody = banLogInAndSignUpWhenUserLogInState(responseString, logInUser); - - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.OK, httpVersion)) - .set200Header(contentType, responseBody) - .build(); - } - - public static byte[] banLogInAndSignUpWhenUserLogInState(String responseString, User logInUser) { - return replaceHyperLinkLikeIndexHtml(responseString).replace( - "\n" + - "
  • 회원가입
  • ", - "
  • " + logInUser.getName() + "
  • ").getBytes(); - } - - public static String replaceHyperLinkLikeIndexHtml(String responseString) { - return responseString.replace( - "../user/login.html", "user/login.html").replace( - "../user/form.html", "user/form.html"); - } -} diff --git a/src/main/java/service/ListService.java b/src/main/java/service/ListService.java deleted file mode 100644 index a83ed3c5..00000000 --- a/src/main/java/service/ListService.java +++ /dev/null @@ -1,60 +0,0 @@ -package service; - -import db.Database; -import http.HttpStatus; -import http.response.HttpResponse; -import http.response.HttpStatusLine; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import util.HttpResponseUtils; - -import java.util.Collection; - -public class ListService { - private static final Logger logger = LoggerFactory.getLogger(ListService.class); - - public static HttpResponse service(User logInUser, String filePath, String httpVersion, String contentType) { - logger.debug("logInUser : {}", logInUser); - // Login check - if (logInUser != null) return logInListService(logInUser, filePath, httpVersion, contentType); - - // not Login - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.FOUND, httpVersion)) - .set302Header("/user/login.html") - .build(); - } - - public static HttpResponse logInListService(User logInUser, String filePath, String httpVersion, String contentType) { - StringBuilder stringBuilder = makeHtml(); - - // 파일 경로를 넘겨서 http response string 생성 - String responseString = new String(HttpResponseUtils.makeBody(filePath)); - String addedUserListToresponseString = responseString.replace("%userList%", stringBuilder.toString()); - byte[] responseBody = HtmlService.banLogInAndSignUpWhenUserLogInState(addedUserListToresponseString, logInUser); - - // 만들어진 body로 응답 객체를 만들어서 리턴 - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.OK, httpVersion)) - .set200Header(contentType, responseBody) - .build(); - } - - private static StringBuilder makeHtml() { - int index = 1; - Collection userList = Database.findAll(); - StringBuilder stringBuilder = new StringBuilder(); - - for (User user : userList) { - stringBuilder.append("").append(index).append("") - .append("").append(user.getUserId()).append("") - .append("").append(user.getName()).append("") - .append("").append(user.getEmail()).append("") - .append("수정"); - index++; - } - return stringBuilder; - } - -} diff --git a/src/main/java/service/LogInService.java b/src/main/java/service/LogInService.java deleted file mode 100644 index 9d065e71..00000000 --- a/src/main/java/service/LogInService.java +++ /dev/null @@ -1,67 +0,0 @@ -package service; - -import db.Database; -import db.Session; -import http.HttpStatus; -import http.response.HttpResponse; -import http.response.HttpStatusLine; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -public class LogInService { - private static final Logger logger = LoggerFactory.getLogger(LogInService.class); - - public static HttpResponse service(Map params, String httpVersion) { - // 성공 - if (isLoginSuccess(params)) { - // index.html로 이동 - // HTTP 헤더의 쿠키 값을 SID = 세션 ID로 응답 - // 세션 ID는 적당한 크기의 무작위 숫자 또는 문자열 - // 서버는 세션 아이디에 해당하는 User 정보에 접근 가능해야 한다. - String cookie = addSessionAndGetSessionID(params.get("userId")); - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.FOUND, httpVersion)) - .set302Header("/index.html") - .addCookie(cookie) - .build(); - } - - // 실패 - // /user/login_failed.html로 이동 - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.FOUND, httpVersion)) - .set302Header("/user/login_failed.html") - .build(); - } - - private static boolean isLoginSuccess(Map params) { - User tryLoginUser = Database.findUserById(params.get("userId")); - logger.debug("User : {}", tryLoginUser); - - // id가 없을 때 - if (tryLoginUser == null) { - logger.debug("User not Found !!"); - return false; - } - - // 비밀번호가 맞아서 로그인 성공 - if (tryLoginUser.getPassword().equals(params.get("password"))) { - logger.debug("Login success !!"); - return true; - } - - // 비밀번호 틀림 - logger.debug("Login failed !!"); - return false; - - } - - private static String addSessionAndGetSessionID(String userId) { - return Session.makeSessionIdAndAddUserId(userId); - } - - -} diff --git a/src/main/java/service/SignUpService.java b/src/main/java/service/SignUpService.java deleted file mode 100644 index 2a6d35e6..00000000 --- a/src/main/java/service/SignUpService.java +++ /dev/null @@ -1,48 +0,0 @@ -package service; - -import db.Database; -import http.HttpStatus; -import http.exception.DuplicateSignUpUserException; -import http.response.HttpResponse; -import http.response.HttpStatusLine; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.charset.StandardCharsets; -import java.util.Map; - -public class SignUpService { - private static final Logger logger = LoggerFactory.getLogger(SignUpService.class); - - public static User makeUserByParams(Map params) { - return new User( - params.get("userId"), - params.get("password"), - params.get("name"), - params.get("email")); - } - - public static void addDatabase(User user) { - if(Database.checkDuplicate(user)) throw new DuplicateSignUpUserException("중복된 사용자가 있습니다."); - Database.addUser(user); - } - - public static HttpResponse service(Map params, String httpVersion) { - // user 정보 받아서 데이터베이스에 입력 - try{ - SignUpService.addDatabase(SignUpService.makeUserByParams(params)); - } catch(DuplicateSignUpUserException duplicateSignUpUserException){ - logger.debug(duplicateSignUpUserException.getMessage()); - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.FOUND, httpVersion)) - .set200Header("text/html", "이미 있는 사용자 id 입니다.".getBytes(StandardCharsets.UTF_8)) - .build(); - } - // 302 응답이라 location만 필요하기 때문에 body랑 contentType는 없음! - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.FOUND, httpVersion)) - .set302Header("/index.html") - .build(); - } -} diff --git a/src/main/java/service/StaticFileService.java b/src/main/java/service/StaticFileService.java deleted file mode 100644 index 0f2d1f8f..00000000 --- a/src/main/java/service/StaticFileService.java +++ /dev/null @@ -1,19 +0,0 @@ -package service; - -import http.HttpStatus; -import http.response.HttpResponse; -import http.response.HttpStatusLine; -import util.HttpResponseUtils; - -public class StaticFileService { - public static HttpResponse service(String filePath, String httpVersion, String contentType) { - // 파일 경로를 넘겨서 http response body 생성 - byte[] responseBody = HttpResponseUtils.makeBody(filePath); - - // 만들어진 body로 응답 객체를 만들어서 리턴 - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.OK, httpVersion)) - .set200Header(contentType, responseBody) - .build(); - } -} diff --git a/src/main/java/util/HttpRequestUtils.java b/src/main/java/util/HttpRequestUtils.java deleted file mode 100644 index ea5c1cf6..00000000 --- a/src/main/java/util/HttpRequestUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -package util; - -import http.HttpHeader; -import http.HttpUri; -import http.request.HttpRequestLine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class HttpRequestUtils { - private static final Logger logger = LoggerFactory.getLogger(HttpRequestUtils.class); - - public static HttpRequestLine readRequestLine(String firstLine) { - logger.debug("Request Line: {}", firstLine); - String[] splited = firstLine.split(" "); - String method = splited[0]; - HttpUri uri = new HttpUri(checkUriNothing(splited[1])); - String version = splited[2]; - return new HttpRequestLine(method, uri, version); - } - - private static String checkUriNothing(String uri) { - // http://localhost:8080/ input 들어올 경우 uri는 "/" - if (uri.equals("/")) return "/index.html"; - return uri; - } - - public static HttpHeader readHeaders(BufferedReader br) throws IOException { - List headers = new ArrayList<>(); - String header = br.readLine(); - while (!header.equals("")) { - headers.add(header); - header = br.readLine(); - } - return new HttpHeader(headers); - } - - public static Map parseQueryString(String queryString) { - Map requestParamsMap = new HashMap<>(); - String[] userInputs = queryString.split("&"); - for (String userInput : userInputs) { - String[] requestParam = userInput.split("="); - String requestParamValue = takeValueRequestParam(requestParam); - requestParamsMap.put(requestParam[0], requestParamValue); - } - return requestParamsMap; - } - - public static String takeValueRequestParam(String[] requestParam) { - // 정보가 알맞게 들어왔는지, 빈칸은 아닌지 확인 - if (requestParam.length != 2) return null; - return URLDecoder.decode(requestParam[1], StandardCharsets.UTF_8); - } - - - public static String readBody(BufferedReader br, HttpHeader header) throws IOException { - String requestBody = readData(br, Integer.parseInt(header.getContentLength())); - logger.debug("Request Body : {}", requestBody); - return requestBody; - } - - public static String readData(BufferedReader br, int contentLength) throws IOException { - char[] body = new char[contentLength]; - br.read(body, 0, contentLength); - return String.copyValueOf(body); - } -} diff --git a/src/main/java/util/HttpResponseUtils.java b/src/main/java/util/HttpResponseUtils.java deleted file mode 100644 index 8805b2d3..00000000 --- a/src/main/java/util/HttpResponseUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package util; - -import http.HttpHeader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; - -public class HttpResponseUtils { - private static final Logger logger = LoggerFactory.getLogger(HttpResponseUtils.class); - - public static byte[] makeBody(String filePath) { - logger.debug("filePath get : {}", filePath); - try { - return Files.readAllBytes(new File(filePath).toPath()); - } catch (IOException e) { - return " 파일을 찾지 못함 !".getBytes(); - } - } - - public static HttpHeader makeResponse200Header(String contentType, int bodyLength) { - List headerLines = new ArrayList<>(); - logger.debug("contentType: {}", contentType); - headerLines.add("Content-Type: " + contentType + ";charset=utf-8" + System.lineSeparator()); - headerLines.add("Content-Length: " + bodyLength + System.lineSeparator()); - return new HttpHeader(headerLines); - } - - public static HttpHeader makeResponse302Header(String destination) { - List headerLines = new ArrayList<>(); - headerLines.add("Location: " + destination + System.lineSeparator()); - return new HttpHeader(headerLines); - } - -} diff --git a/src/main/java/webserver/ControllerHandler.java b/src/main/java/webserver/ControllerHandler.java deleted file mode 100644 index 160a504a..00000000 --- a/src/main/java/webserver/ControllerHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -package webserver; - -import controller.Controller; -import controller.HtmlController; -import controller.StaticFileController; -import controller.UserController; -import http.request.HttpRequest; - -public class ControllerHandler { - public static Controller handleController(HttpRequest httpRequest) { - //TODO httpRequest 보고 어떤 컨트롤러 써야되는지 리턴 해줘야됨 - - // POST 요청일 때 : 회원가입, 로그인 - // User의 요청이면 UserController 리턴 - if (httpRequest.isPost()) return whoWant(httpRequest.getUri()); - - // html 파일을 원한다면? - if (httpRequest.wantHtml()) return new HtmlController(); - - // 나머지 - 정적 처리 - return new StaticFileController(); - - } - - // ControllerHandler Util을 빼줘야 하나? - - public static Controller whoWant(String uri) { - // User가 원하면 UserController를 넘겨줌 - if (isUser(uri)) return new UserController(); - - //TODO 확장 : User 외에 다른 객체가 원한다면? - return null; - } - - public static boolean isUser(String uri) { - return uri.startsWith("/user"); - } - -} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java deleted file mode 100644 index 46ae0b01..00000000 --- a/src/main/java/webserver/RequestHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -package webserver; - -import controller.Controller; -import http.exception.NullHttpRequestException; -import http.request.HttpRequest; -import http.response.HttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.net.Socket; -import java.nio.charset.StandardCharsets; - -public class RequestHandler implements Runnable { - private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class); - - private final Socket connection; - - public RequestHandler(Socket connectionSocket) { - this.connection = connectionSocket; - } - - public void run() { - logger.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), - connection.getPort()); - - try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - // HttpRequest 클래스에 입력을 받는다. - HttpRequest httpRequest = new HttpRequest(new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))); - - // HttpRequest 클래스의 URI를 보고 어떤 컨트롤러가 필요한지 골라준다. - Controller controller = ControllerHandler.handleController(httpRequest); - - // 골라준 컨트롤러로 응답을 만들어 준다. - HttpResponse httpResponse = controller.makeResponse(httpRequest); - - // 만들어준 응답을 출력 - httpResponse.send(new DataOutputStream(out)); - - } catch (IOException e) { - logger.error("ERROR : {}", e.getMessage()); - } catch (NullHttpRequestException nullHttpRequestException) { - logger.error(nullHttpRequestException.getMessage()); - } - } -} diff --git a/src/main/java/webserver/WebServer.java b/src/main/java/webserver/WebServer.java deleted file mode 100644 index c07d54d6..00000000 --- a/src/main/java/webserver/WebServer.java +++ /dev/null @@ -1,33 +0,0 @@ -package webserver; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.ServerSocket; -import java.net.Socket; - -public class WebServer { - private static final Logger logger = LoggerFactory.getLogger(WebServer.class); - private static final int DEFAULT_PORT = 8080; - - public static void main(String[] args) throws Exception { - int port = 0; - if (args == null || args.length == 0) { - port = DEFAULT_PORT; - } else { - port = Integer.parseInt(args[0]); - } - - // 서버소켓을 생성한다. 웹서버는 기본적으로 8080번 포트를 사용한다. - try (ServerSocket listenSocket = new ServerSocket(port)) { - logger.info("Web Application Server started {} port.", port); - - // 클라이언트가 연결될때까지 대기한다. - Socket connection; - while ((connection = listenSocket.accept()) != null) { - Thread thread = new Thread(new RequestHandler(connection)); - thread.start(); - } - } - } -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 00000000..63a0c901 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,4 @@ +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://localhost:3306/repository?serverTimezone=UTC&characterEncoding=UTF-8 +spring.datasource.username=root +spring.datasource.password=wngud9865 diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index aa599d33..1615d17c 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -1,5 +1,6 @@ + @@ -69,14 +70,15 @@ diff --git a/src/main/resources/templates/qna/form.html b/src/main/resources/templates/qna/form.html index 39c7328d..44557a1b 100644 --- a/src/main/resources/templates/qna/form.html +++ b/src/main/resources/templates/qna/form.html @@ -1,5 +1,6 @@ + @@ -68,10 +69,11 @@ diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index 261ac16e..a045d94d 100644 --- a/src/main/resources/templates/qna/show.html +++ b/src/main/resources/templates/qna/show.html @@ -1,5 +1,6 @@ + @@ -68,10 +69,11 @@ diff --git a/src/main/resources/templates/user/form.html b/src/main/resources/templates/user/form.html index e56a3dce..bf3b0c97 100644 --- a/src/main/resources/templates/user/form.html +++ b/src/main/resources/templates/user/form.html @@ -1,5 +1,6 @@ + @@ -67,10 +68,11 @@ diff --git a/src/main/resources/templates/user/list.html b/src/main/resources/templates/user/list.html index 170940f9..bfd689bb 100644 --- a/src/main/resources/templates/user/list.html +++ b/src/main/resources/templates/user/list.html @@ -1,5 +1,6 @@ + @@ -68,10 +69,11 @@ @@ -91,7 +93,13 @@ - %userList% + + + + + + 수정 + diff --git a/src/main/resources/templates/user/login.html b/src/main/resources/templates/user/login.html index f843a966..98b95047 100644 --- a/src/main/resources/templates/user/login.html +++ b/src/main/resources/templates/user/login.html @@ -1,5 +1,6 @@ + @@ -68,10 +69,11 @@ diff --git a/src/main/resources/templates/user/login_failed.html b/src/main/resources/templates/user/login_failed.html index cd57fc9e..488abb41 100644 --- a/src/main/resources/templates/user/login_failed.html +++ b/src/main/resources/templates/user/login_failed.html @@ -1,5 +1,6 @@ + @@ -68,10 +69,11 @@ diff --git a/src/main/resources/templates/user/profile.html b/src/main/resources/templates/user/profile.html index 7f5835df..ef024bd6 100644 --- a/src/main/resources/templates/user/profile.html +++ b/src/main/resources/templates/user/profile.html @@ -1,5 +1,6 @@ + @@ -68,10 +69,11 @@ diff --git a/src/test/java/HtmlServiceTest.java b/src/test/java/HtmlServiceTest.java deleted file mode 100644 index e0e4edbd..00000000 --- a/src/test/java/HtmlServiceTest.java +++ /dev/null @@ -1,30 +0,0 @@ -import model.User; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import service.HtmlService; - -import static org.assertj.core.api.Assertions.assertThat; - -public class HtmlServiceTest { - @Test - @DisplayName("동적 html 변환 테스트") - void 동적_HTMl_변환_테스트() { - // given - String indexHtmlResponseString = "
  • 로그인
  • \n" + - "
  • 회원가입
  • "; - String HtmlInUserFolderResponseString = "
  • 로그인
  • \n" + - "
  • 회원가입
  • "; - User logInUser = new User("testid", "testpassword", "홍길동", "asdf@naver.com"); - - // when - byte[] indexHtmlReplacedString = - HtmlService.banLogInAndSignUpWhenUserLogInState(indexHtmlResponseString, logInUser); - byte[] HtmlInUserFolderReplacedString = - HtmlService.banLogInAndSignUpWhenUserLogInState(HtmlInUserFolderResponseString, logInUser); - - // then - byte[] result = ("
  • " + logInUser.getName() + "
  • ").getBytes(); - assertThat(indexHtmlReplacedString).isEqualTo(result); - assertThat(HtmlInUserFolderReplacedString).isEqualTo(result); - } -} diff --git a/src/test/java/HttpRequestUtilsTest.java b/src/test/java/HttpRequestUtilsTest.java deleted file mode 100644 index 7acdb348..00000000 --- a/src/test/java/HttpRequestUtilsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -import http.HttpUri; -import http.request.HttpRequestLine; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import util.HttpRequestUtils; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -public class HttpRequestUtilsTest { - String sampleRequestLine = "GET /index.html HTTP/1.1"; - String queryString = "userId=jhchoi57&" + - "password=12349865&" + - "name=%EC%B5%9C%EC%A3%BC%ED%98%95&" + - "email=jhchoi57%40gmail.com"; - - @Test - @DisplayName("RequestLine 입력받기 테스트") - public void readRequestLineTest() { - HttpRequestLine httpRequestLine = HttpRequestUtils.readRequestLine(sampleRequestLine); - - assertThat(httpRequestLine).usingRecursiveComparison(). - isEqualTo(new HttpRequestLine("GET", new HttpUri("/index.html"), "HTTP/1.1")); - } - - @Test - @DisplayName("queryString 파싱 테스트") - public void parseQueryStringTest() { - Map requestParamsMap = HttpRequestUtils.parseQueryString(queryString); - assertThat(requestParamsMap.get("userId")).isEqualTo("jhchoi57"); - assertThat(requestParamsMap.get("password")).isEqualTo("12349865"); - assertThat(requestParamsMap.get("name")).isEqualTo("최주형"); - assertThat(requestParamsMap.get("email")).isEqualTo("jhchoi57@gmail.com"); - } - -} diff --git a/src/test/java/HttpResponseUtilsTest.java b/src/test/java/HttpResponseUtilsTest.java deleted file mode 100644 index e017748f..00000000 --- a/src/test/java/HttpResponseUtilsTest.java +++ /dev/null @@ -1,48 +0,0 @@ -import http.HttpHeader; -import org.junit.jupiter.api.Test; -import util.HttpResponseUtils; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -import static org.assertj.core.api.Assertions.assertThat; - -public class HttpResponseUtilsTest { - - @Test - void 바디_생성_테스트() throws IOException { - // given - String filePath = "./src/main/resources/templates/index.html"; - // when - byte[] body = HttpResponseUtils.makeBody(filePath); - // then - assertThat(body.length).isEqualTo(Files.readAllBytes(new File(filePath).toPath()).length); - } - - @Test - void OK헤더_생성_테스트() { - // given - String contentType = "text/html"; - int bodyLength = 1024; - // when - HttpHeader header = HttpResponseUtils.makeResponse200Header(contentType, bodyLength); - // then - assertThat(header.toString()).isEqualTo( - "Content-Length: 1024" + System.lineSeparator() + - "Content-Type: text/html;charset=utf-8" + System.lineSeparator() + System.lineSeparator()); - } - - @Test - void FOUND헤더_생성_테스트() { - // given - String destination = "/index.html"; - // when - HttpHeader header = HttpResponseUtils.makeResponse302Header(destination); - // then - assertThat(header.toString()).isEqualTo( - "Location: /index.html" + System.lineSeparator() + System.lineSeparator()); - } - - -} diff --git a/src/test/java/ListServiceTest.java b/src/test/java/ListServiceTest.java deleted file mode 100644 index 709f8b7c..00000000 --- a/src/test/java/ListServiceTest.java +++ /dev/null @@ -1,32 +0,0 @@ -import http.response.HttpResponse; -import model.User; -import org.junit.jupiter.api.Test; -import service.ListService; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ListServiceTest { - // Given - User logInUser = new User("user1", "password", "홍길동", "jasd@email.com"); - String filePath = "src/main/resources/templates/user/list.html"; - String httpVersion = "HTTP/1.1"; - String contentType = "text/html"; - - @Test - public void 로그인상태_ListService_테스트() { - // When - HttpResponse response = ListService.logInListService(logInUser, filePath, httpVersion, contentType); - - // Then - assertThat(response.getBody()).isNotEmpty(); - } - - @Test - public void 로그인상태가아닐때_ListService_테스트() { - // When - HttpResponse response = ListService.service(null, filePath, httpVersion, contentType); - - // Then - assertThat(response.getHeaders().getLocation()).isEqualTo("/user/login.html"); - } -} diff --git a/src/test/java/LogInServiceTest.java b/src/test/java/LogInServiceTest.java deleted file mode 100644 index d8239766..00000000 --- a/src/test/java/LogInServiceTest.java +++ /dev/null @@ -1,41 +0,0 @@ -import db.Database; -import http.response.HttpResponse; -import model.User; -import org.junit.jupiter.api.Test; -import service.LogInService; -import util.HttpRequestUtils; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -public class LogInServiceTest { - @Test - void 로그인서비스_성공_테스트() { - // given - Database.addUser(new User("testUserId", "testPassword", "testName", "testEmail@naver.com")); - String body = "userId=testUserId&password=testPassword"; - Map params = HttpRequestUtils.parseQueryString(body); - - // when - HttpResponse successResponse = LogInService.service(params, "HTTP/1.1"); - - // then - assertThat(successResponse.getHeaders().getLocation()).isEqualTo("/index.html"); - } - - @Test - void 로그인서비스_실패_테스트() { - // given - Database.addUser(new User("testUserId", "testPassword", "testName", "testEmail@naver.com")); - String body = "userId=testfdadUserId&password=testasdPassword"; - Map params = HttpRequestUtils.parseQueryString(body); - - // when - HttpResponse FailResponse = LogInService.service(params, "HTTP/1.1"); - - // then - assertThat(FailResponse.getHeaders().getLocation()).isEqualTo("/user/login_failed.html"); - - } -} diff --git a/src/test/java/SignUpServiceTest.java b/src/test/java/SignUpServiceTest.java deleted file mode 100644 index 0bda0fc0..00000000 --- a/src/test/java/SignUpServiceTest.java +++ /dev/null @@ -1,48 +0,0 @@ -import db.Database; -import http.response.HttpResponse; -import model.User; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import service.SignUpService; -import util.HttpRequestUtils; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -public class SignUpServiceTest { - @Test - @DisplayName("회원 가입 시 유저 정보들을 유저 클래스에 잘 담아 주는지 테스트") - void makeUserInfoTest() { - // given - final String body = "userId=jhchoi57&" + - "password=12349865&" + - "name=%EC%B5%9C%EC%A3%BC%ED%98%95&" + - "email=jhchoi57%40gmail.com"; - final Map params = HttpRequestUtils.parseQueryString(body); - // when - final User user = SignUpService.makeUserByParams(params); - - // then - assertThat(user).usingRecursiveComparison().isEqualTo(new User( - "jhchoi57", "12349865", "최주형", "jhchoi57@gmail.com")); - } - - @Test - void 회원가입_서비스_테스트() { - // given - String body = "userId=jhchoi57&" + - "password=12349865&" + - "name=%EC%B5%9C%EC%A3%BC%ED%98%95&" + - "email=jhchoi57%40gmail.com"; - Map params = HttpRequestUtils.parseQueryString(body); - - // when - HttpResponse response = SignUpService.service(params, "HTTP/1.1"); - - // then - assertThat(response.getHeaders().getLocation()).isEqualTo("/index.html"); - assertThat(Database.findUserById("jhchoi57").getUserId()).isNotEmpty(); - } - -} diff --git a/src/test/java/StaticFileServiceTest.java b/src/test/java/StaticFileServiceTest.java deleted file mode 100644 index d5bd7e7d..00000000 --- a/src/test/java/StaticFileServiceTest.java +++ /dev/null @@ -1,21 +0,0 @@ -import http.response.HttpResponse; -import org.junit.jupiter.api.Test; -import service.StaticFileService; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -public class StaticFileServiceTest { - @Test - void 정적_파일_서비스_테스트() { - // Given - String filePath = "src/main/resources/templates/index.html"; - String httpVersion = "HTTP/1.1"; - String contentType = "text/html"; - - // When - HttpResponse response = StaticFileService.service(filePath, httpVersion, contentType); - - // Then - assertThat(response.getBody()).isNotEmpty(); - } -} diff --git a/src/test/java/bejavawebserver/WebserverApplicationTests.java b/src/test/java/bejavawebserver/WebserverApplicationTests.java new file mode 100644 index 00000000..402ad991 --- /dev/null +++ b/src/test/java/bejavawebserver/WebserverApplicationTests.java @@ -0,0 +1,13 @@ +package bejavawebserver; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class WebserverApplicationTests { + + @Test + void contextLoads() { + } + +}
  • 로그인