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 8a72f8ce..f04c5898 100644 --- a/README.md +++ b/README.md @@ -2,146 +2,46 @@ Java Web Application Server 2022 -## 프로젝트 정보 +## 프로젝트 정보 -이 프로젝트는 우아한 테크코스 박재성님의 허가를 받아 https://github.com/woowacourse/jwp-was +이 프로젝트는 우아한 테크코스 박재성님의 허가를 받아 https://github.com/woowacourse/jwp-was 를 참고하여 작성되었습니다. ## 프로젝트 학습 내용 -### 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 \ No newline at end of file diff --git a/build.gradle b/build.gradle index a92f231c..a3dd9d8b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,33 +1,34 @@ 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' + // mysql + implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.0.32' + // jdbc + implementation 'org.springframework.boot:spring-boot-starter-jdbc' } -test { - useJUnitPlatform() -} - -repositories { - mavenCentral() +tasks.named('test') { + useJUnitPlatform() } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f..249e5832 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ 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/SpringConfig.java b/src/main/java/bejavawebserver/SpringConfig.java new file mode 100644 index 00000000..f397209d --- /dev/null +++ b/src/main/java/bejavawebserver/SpringConfig.java @@ -0,0 +1,24 @@ +//package bejavawebserver; +// +//import bejavawebserver.repository.JdbcRepository; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.sql.DataSource; +// +// +//@Configuration +//public class SpringConfig { +// private DataSource dataSource; +// +// @Autowired +// public SpringConfig(DataSource dataSource){ +// this.dataSource = dataSource; +// } +// +// @Bean +// public JdbcRepository jdbcRepository(){ +// return new JdbcRepository(dataSource); +// } +//} diff --git a/src/main/java/bejavawebserver/WebserverApplication.java b/src/main/java/bejavawebserver/WebserverApplication.java new file mode 100644 index 00000000..794dacbd --- /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..0b6d6ce3 --- /dev/null +++ b/src/main/java/bejavawebserver/controller/HomeController.java @@ -0,0 +1,12 @@ +package bejavawebserver.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HomeController { + @GetMapping("/") + public String home() { + return "redirect:/index.html"; + } +} diff --git a/src/main/java/bejavawebserver/controller/HtmlController.java b/src/main/java/bejavawebserver/controller/HtmlController.java new file mode 100644 index 00000000..11a9a6ce --- /dev/null +++ b/src/main/java/bejavawebserver/controller/HtmlController.java @@ -0,0 +1,63 @@ +package bejavawebserver.controller; + +import bejavawebserver.model.User; +import bejavawebserver.service.HtmlService; +import bejavawebserver.service.ListService; +import bejavawebserver.service.LoginService; +import bejavawebserver.service.QnaService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +@Controller +public class HtmlController { + @Autowired + HtmlService htmlService; + @Autowired + ListService listService; + @Autowired + QnaService qnaService; + + @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 (uri.equals("/index.html")) qnaService.makeQnaList(model); + + // 로그인 상태인 경우 + if (LoginService.isLogin(session)) { + return htmlService.makeLoginView(model, uri, (User) session.getAttribute(session.getId())); + } + // 로그인 상태가 아닌 경우 + if (uri.equals("/qna/form.html")) return "redirect:/user/login.html"; + 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)) { + listService.makeUserList(model); + return htmlService.makeLoginView(model, uri, (User) session.getAttribute("user")); + } + + // 로그인 상태가 아닌 경우 + return "redirect:/user/login.html"; + + } +} diff --git a/src/main/java/bejavawebserver/controller/QnaController.java b/src/main/java/bejavawebserver/controller/QnaController.java new file mode 100644 index 00000000..7a7af659 --- /dev/null +++ b/src/main/java/bejavawebserver/controller/QnaController.java @@ -0,0 +1,25 @@ +package bejavawebserver.controller; + +import bejavawebserver.model.Qna; +import bejavawebserver.model.QnaForm; +import bejavawebserver.service.QnaService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@Controller +public class QnaController { + @Autowired + QnaService qnaService; + + @PostMapping("/qna/form") + public String writeQna(QnaForm qnaForm) { + String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + qnaService.addQna(new Qna(qnaForm, time)); + return "redirect:/index.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..a0beb714 --- /dev/null +++ b/src/main/java/bejavawebserver/controller/UserController.java @@ -0,0 +1,54 @@ +package bejavawebserver.controller; + +import bejavawebserver.model.LoginForm; +import bejavawebserver.model.User; +import bejavawebserver.service.LoginService; +import bejavawebserver.service.LogoutService; +import bejavawebserver.service.SignUpService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +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 UserController { + private static final Logger logger = LoggerFactory.getLogger(UserController.class); + @Autowired + SignUpService signUpService; + @Autowired + LoginService loginService; + @Autowired + LogoutService logoutService; + + @PostMapping("/user/create") + public String signUp(User user) { + try { + signUpService.addDatabase(user); + } catch (RuntimeException r) { + logger.debug(r.getMessage()); + 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"; + } + + @GetMapping("/user/logout") + public String logout(HttpServletRequest httpServletRequest) { + HttpSession session = httpServletRequest.getSession(); + logoutService.removeSession(session); + return "redirect:/"; + } + +} 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/bejavawebserver/model/Qna.java b/src/main/java/bejavawebserver/model/Qna.java new file mode 100644 index 00000000..2ee03f3f --- /dev/null +++ b/src/main/java/bejavawebserver/model/Qna.java @@ -0,0 +1,22 @@ +package bejavawebserver.model; + +import lombok.Data; + +@Data +public class Qna { + private String writer; + private String contents; + private String time; + + public Qna(QnaForm qnaForm, String time) { + this.writer = qnaForm.getWriter(); + this.contents = qnaForm.getContents(); + this.time = time; + } + + public Qna(String writer, String contents, String time) { + this.writer = writer; + this.contents = contents; + this.time = time; + } +} diff --git a/src/main/java/bejavawebserver/model/QnaForm.java b/src/main/java/bejavawebserver/model/QnaForm.java new file mode 100644 index 00000000..f3aac0a5 --- /dev/null +++ b/src/main/java/bejavawebserver/model/QnaForm.java @@ -0,0 +1,17 @@ +package bejavawebserver.model; + +import lombok.Data; +import lombok.NonNull; + +@Data +public class QnaForm { + @NonNull + private String writer; + @NonNull + private String contents; + + public QnaForm(@NonNull String writer, @NonNull String contents) { + this.writer = writer; + this.contents = contents; + } +} diff --git a/src/main/java/model/User.java b/src/main/java/bejavawebserver/model/User.java similarity index 79% rename from src/main/java/model/User.java rename to src/main/java/bejavawebserver/model/User.java index b7abb730..7c3ccb1c 100644 --- a/src/main/java/model/User.java +++ b/src/main/java/bejavawebserver/model/User.java @@ -1,10 +1,10 @@ -package model; +package bejavawebserver.model; public class User { - private String userId; - private String password; - private String name; - private String email; + private final String userId; + private final String password; + private final String name; + private final String email; public User(String userId, String password, String name, String email) { this.userId = userId; diff --git a/src/main/java/bejavawebserver/repository/JdbcRepository.java b/src/main/java/bejavawebserver/repository/JdbcRepository.java new file mode 100644 index 00000000..ea850e27 --- /dev/null +++ b/src/main/java/bejavawebserver/repository/JdbcRepository.java @@ -0,0 +1,191 @@ +package bejavawebserver.repository; + +import bejavawebserver.model.Qna; +import bejavawebserver.model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +@Repository +public class JdbcRepository { + private static final Logger logger = LoggerFactory.getLogger(JdbcRepository.class); + private final DataSource dataSource; + + public JdbcRepository(DataSource dataSource) { + this.dataSource = dataSource; + } + + public boolean checkDuplicate(User user) { + return findUserById(user.getUserId()) != null; + } + + public void addUser(User user) { + String sql = "insert into User values(?, ?, ?, ?)"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setString(1, user.getUserId()); + pstmt.setString(2, user.getPassword()); + pstmt.setString(3, user.getName()); + pstmt.setString(4, user.getEmail()); + pstmt.executeUpdate(); + + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + + public User findUserById(String userId) { + String sql = "select * from User where user_id = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + User findUser = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setString(1, userId); + + rs = pstmt.executeQuery(); + while (rs.next()) { + findUser = new User( + rs.getString("user_id"), + rs.getString("password"), + rs.getString("name"), + rs.getString("email") + ); + } + return findUser; + + } catch (Exception e) { + logger.debug("error : {}", e.getMessage()); + return null; + } finally { + close(conn, pstmt, rs); + } + } + + public List findUserAll() { + String sql = "select * from User"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + + List userList = new ArrayList<>(); + while (rs.next()) { + User user = new User( + rs.getString("user_id"), + rs.getString("password"), + rs.getString("name"), + rs.getString("email") + ); + userList.add(user); + } + return userList; + + } catch (Exception e) { + logger.debug("error : {}", e.getMessage()); + + return null; + } finally { + close(conn, pstmt, rs); + } + } + + public List findQnaAll() { + String sql = "select * from qna order by time desc"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + + List qnaList = new ArrayList<>(); + while (rs.next()) { + Qna qna = new Qna( + rs.getString("writer"), + rs.getString("contents"), + rs.getString("time") + ); + qnaList.add(qna); + } + return qnaList; + + } catch (Exception e) { + logger.debug("error : {}", e.getMessage()); + + return null; + } finally { + close(conn, pstmt, rs); + } + } + + public void addQna(Qna qna) { + String sql = "insert into qna values(?, ?, ?)"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setString(1, qna.getWriter()); + pstmt.setString(2, qna.getContents()); + pstmt.setString(3, qna.getTime()); + pstmt.executeUpdate(); + + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + + private Connection getConnection() { + return DataSourceUtils.getConnection(dataSource); + } + + private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { + // 역순으로 닫아주어야 한다 + try { + if (pstmt != null) { + pstmt.close(); + } + if (conn != null) { + conn.close(); + } + if (rs != null) { + rs.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + +} diff --git a/src/main/java/bejavawebserver/repository/MemoryRepository.java b/src/main/java/bejavawebserver/repository/MemoryRepository.java new file mode 100644 index 00000000..c3884b9d --- /dev/null +++ b/src/main/java/bejavawebserver/repository/MemoryRepository.java @@ -0,0 +1,31 @@ +package bejavawebserver.repository; + +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 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); + users.put(user.getUserId(), user); + } + + public static User findUserById(String userId) { + return users.get(userId); + } + + public static Collection findAll() { + return users.values(); + } + + public static boolean checkDuplicate(User user) { + 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..3577723b --- /dev/null +++ b/src/main/java/bejavawebserver/service/HtmlService.java @@ -0,0 +1,27 @@ +package bejavawebserver.service; + +import bejavawebserver.controller.HtmlController; +import bejavawebserver.model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; + +@Service +public class HtmlService { + private static final Logger logger = LoggerFactory.getLogger(HtmlController.class); + + public String makeNotLoginView(Model model, String uri) { + logger.debug("현재 로그인 상태 아님"); + model.addAttribute("isLogin", false); + return uri; + } + + public 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..e9f4ce63 --- /dev/null +++ b/src/main/java/bejavawebserver/service/ListService.java @@ -0,0 +1,20 @@ +package bejavawebserver.service; + +import bejavawebserver.model.User; +import bejavawebserver.repository.JdbcRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; + +import java.util.List; + +@Service +public class ListService { + @Autowired + JdbcRepository jdbcRepository; + + public void makeUserList(Model model) { + List userList = jdbcRepository.findUserAll(); + model.addAttribute("userList", userList); + } +} diff --git a/src/main/java/bejavawebserver/service/LoginService.java b/src/main/java/bejavawebserver/service/LoginService.java new file mode 100644 index 00000000..3029c51c --- /dev/null +++ b/src/main/java/bejavawebserver/service/LoginService.java @@ -0,0 +1,30 @@ +package bejavawebserver.service; + +import bejavawebserver.model.LoginForm; +import bejavawebserver.model.User; +import bejavawebserver.repository.JdbcRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpSession; +import java.util.Objects; + +@Service +public class LoginService { + @Autowired + JdbcRepository jdbcRepository; + + public static boolean isLogin(HttpSession session) { + if (session == null) return false; + return session.getAttribute("user") != null; + } + + public boolean isLoginSuccess(LoginForm loginForm, HttpSession session) { + User user = jdbcRepository.findUserById(loginForm.getUserId()); + boolean isSuccess = Objects.equals(user.getPassword(), loginForm.getPassword()); + if (isSuccess) session.setAttribute("user", user); + return isSuccess; + } + + +} diff --git a/src/main/java/bejavawebserver/service/LogoutService.java b/src/main/java/bejavawebserver/service/LogoutService.java new file mode 100644 index 00000000..313764c0 --- /dev/null +++ b/src/main/java/bejavawebserver/service/LogoutService.java @@ -0,0 +1,12 @@ +package bejavawebserver.service; + +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpSession; + +@Service +public class LogoutService { + public void removeSession(HttpSession session) { + session.removeAttribute("user"); + } +} diff --git a/src/main/java/bejavawebserver/service/QnaService.java b/src/main/java/bejavawebserver/service/QnaService.java new file mode 100644 index 00000000..c07f1d3c --- /dev/null +++ b/src/main/java/bejavawebserver/service/QnaService.java @@ -0,0 +1,24 @@ +package bejavawebserver.service; + +import bejavawebserver.model.Qna; +import bejavawebserver.repository.JdbcRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; + +import java.util.List; + +@Service +public class QnaService { + @Autowired + JdbcRepository jdbcRepository; + + public void addQna(Qna qna) { + jdbcRepository.addQna(qna); + } + + public void makeQnaList(Model model) { + List qnaList = jdbcRepository.findQnaAll(); + model.addAttribute("qnaList", qnaList); + } +} diff --git a/src/main/java/bejavawebserver/service/SignUpService.java b/src/main/java/bejavawebserver/service/SignUpService.java new file mode 100644 index 00000000..ecee3511 --- /dev/null +++ b/src/main/java/bejavawebserver/service/SignUpService.java @@ -0,0 +1,17 @@ +package bejavawebserver.service; + +import bejavawebserver.model.User; +import bejavawebserver.repository.JdbcRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SignUpService { + @Autowired + JdbcRepository jdbcRepository; + + public void addDatabase(User user) { + if (jdbcRepository.checkDuplicate(user)) throw new RuntimeException("중복된 사용자가 있습니다."); + jdbcRepository.addUser(user); + } +} diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java deleted file mode 100644 index 51c32a57..00000000 --- a/src/main/java/controller/Controller.java +++ /dev/null @@ -1,10 +0,0 @@ -package controller; - -import http.request.HttpRequest; -import http.response.HttpResponse; - -import java.io.IOException; - -public interface Controller { - HttpResponse makeResponse(HttpRequest httpRequest) throws IOException; -} diff --git a/src/main/java/controller/StaticFileController.java b/src/main/java/controller/StaticFileController.java deleted file mode 100644 index b18ecb14..00000000 --- a/src/main/java/controller/StaticFileController.java +++ /dev/null @@ -1,35 +0,0 @@ -package controller; - -import http.request.HttpRequest; -import http.response.HttpResponse; -import http.HttpStatus; -import http.response.HttpStatusLine; -import util.HttpResponseUtils; - -import java.io.IOException; - -public class StaticFileController implements Controller { - - @Override - public HttpResponse makeResponse(HttpRequest httpRequest) throws IOException { - // ContentType를 받음 - String contentType = httpRequest.getContentType(); - - // ContentType를 통해 파일 경로 설정 - // TODO 여러 확장자에 대한 처리 필요 - // 일단은 html 확장자일 경우 /templates 그 외는 /static - String filePath = HttpResponseUtils.makeFilePath(contentType); - - // 파일 경로를 넘겨서 http response body 생성 - byte[] responseBody = HttpResponseUtils.makeBody(httpRequest.getUri(), filePath); - - // TODO 여러 HttpStatus에 대한 처리 필요 - // 일단은 200 OK 고정 박아놓음 - // 만들어진 body로 응답 객체를 만들어서 리턴 - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.OK, httpRequest.getHttpVersion())) - .setBody(responseBody) - .setContentType(contentType) - .build(); - } -} diff --git a/src/main/java/controller/UserController.java b/src/main/java/controller/UserController.java deleted file mode 100644 index 4ebb7757..00000000 --- a/src/main/java/controller/UserController.java +++ /dev/null @@ -1,62 +0,0 @@ -package controller; - -import db.Database; -import http.HttpStatus; -import http.request.HttpRequest; -import http.response.HttpResponse; -import http.response.HttpStatusLine; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import service.LogInService; -import service.SignUpService; -import util.HttpResponseUtils; - -import java.io.IOException; - -public class UserController implements Controller { - private static final Logger logger = LoggerFactory.getLogger(UserController.class); - - @Override - public HttpResponse makeResponse(HttpRequest httpRequest) throws IOException { - // Uri 받아옵시다 - String uri = httpRequest.getUri(); - - // 회원가입일 때 - if (isSignUpService(uri)) { - // user 정보 받아서 데이터베이스에 입력 - Database.addUser(SignUpService.makeUserByBody(httpRequest.getBody())); - // 302 응답이라 location만 필요하기 때문에 body랑 contentType는 없음! - return new HttpResponse.HttpResponseBuilder() - .setHttpStatusLine(new HttpStatusLine(HttpStatus.FOUND, httpRequest.getHttpVersion())) - .build(); - } - - // 로그인일 때 - if(isLoginService(uri)){ - // 성공 - if(LogInService.isLoginSuccess(httpRequest.getBody())){ - // index.html로 이동 - // HTTP 헤더의 쿠키 값을 SID = 세션 ID로 응답 - // 세션 ID는 적당한 크기의 무작위 숫자 또는 문자열 - // 서버는 세션 아이디에 해당하는 User 정보에 접근 가능해야 한다. - } - - // 실패 - // /user/login_failed.html로 이동 - - } - - //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/Database.java b/src/main/java/db/Database.java deleted file mode 100644 index ebaaeef7..00000000 --- a/src/main/java/db/Database.java +++ /dev/null @@ -1,23 +0,0 @@ -package db; - -import com.google.common.collect.Maps; -import model.User; - -import java.util.Collection; -import java.util.Map; - -public class Database { - private static Map users = Maps.newHashMap(); - - public static void addUser(User user) { - users.put(user.getUserId(), user); - } - - public static User findUserById(String userId) { - return users.get(userId); - } - - public static Collection findAll() { - return users.values(); - } -} diff --git a/src/main/java/http/HttpHeader.java b/src/main/java/http/HttpHeader.java deleted file mode 100644 index 2d191cdc..00000000 --- a/src/main/java/http/HttpHeader.java +++ /dev/null @@ -1,37 +0,0 @@ -package http; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class HttpHeader { - - private 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 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"); - } -} diff --git a/src/main/java/http/HttpStatus.java b/src/main/java/http/HttpStatus.java deleted file mode 100644 index bd1d4770..00000000 --- a/src/main/java/http/HttpStatus.java +++ /dev/null @@ -1,35 +0,0 @@ -package http; - -import java.util.Arrays; - -public enum HttpStatus { - OK(200, "OK"), - FOUND(302, "FOUND"); - - private int statusCode; - private 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 int getStatusCode() { - return statusCode; - } - - public String getStatus() { - return status; - } - - 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 6d91226b..00000000 --- a/src/main/java/http/HttpUri.java +++ /dev/null @@ -1,23 +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 String uri; - - public HttpUri(String uri) { - this.uri = uri; - } - - public String getUri() { - return uri; - } - - // uri에 . 이 있으면 정적 파일을 주면 되지 않을까? - // 다른 방법으로 판단 해야 할듯 > 고민중 - public boolean isStaticUri() { - return uri.contains("."); - } -} diff --git a/src/main/java/http/exception/NullHttpRequestException.java b/src/main/java/http/exception/NullHttpRequestException.java deleted file mode 100644 index 5ee1c867..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 01c487de..00000000 --- a/src/main/java/http/request/HttpRequest.java +++ /dev/null @@ -1,51 +0,0 @@ -package http.request; - -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 HttpRequestLine httpRequestLine; - private 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 boolean wantStatic() { - return httpRequestLine.getHttpUri().isStaticUri(); - } - - 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; - } -} diff --git a/src/main/java/http/request/HttpRequestLine.java b/src/main/java/http/request/HttpRequestLine.java deleted file mode 100644 index 1f7a5948..00000000 --- a/src/main/java/http/request/HttpRequestLine.java +++ /dev/null @@ -1,25 +0,0 @@ -package http.request; - -import http.HttpUri; - -public class HttpRequestLine { - private String method; - private HttpUri uri; - private 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 beb42a56..00000000 --- a/src/main/java/http/response/HttpResponse.java +++ /dev/null @@ -1,104 +0,0 @@ -package http.response; - -import http.HttpHeader; -import http.HttpStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class HttpResponse { - private static final Logger logger = LoggerFactory.getLogger(HttpResponse.class); - private final HttpStatusLine statusLine; - private HttpHeader header; - private byte[] body; - - private String contentType; - - private HttpResponse(HttpResponseBuilder httpResponseBuilder){ - this.statusLine = httpResponseBuilder.httpStatusLine; - this.body = httpResponseBuilder.body; - this.contentType = httpResponseBuilder.contentType; - - this.header = makeHeader(); - } - - private HttpHeader makeHeader() { - if (statusLine.checkStatus(HttpStatus.OK)) return makeResponse200Header(); - if (statusLine.checkStatus(HttpStatus.FOUND)) return makeResponse302Header(); - - // 200 302 응답 둘다 아니면? - return null; - } - - public static class HttpResponseBuilder{ - private HttpStatusLine httpStatusLine; - private byte[] body; - private String contentType; - - public HttpResponseBuilder(){} - - public HttpResponseBuilder setHttpStatusLine(HttpStatusLine httpStatusLine){ - this.httpStatusLine = httpStatusLine; - return this; - } - - public HttpResponseBuilder setBody(byte[] body){ - this.body = body; - return this; - } - - public HttpResponseBuilder setContentType(String contentType){ - this.contentType = contentType; - return this; - } - - public HttpResponse build(){ - return new HttpResponse(this); - } - - } - - private HttpHeader makeResponse200Header() { - List headerLines = new ArrayList<>(); - logger.debug("contentType: {}", contentType); - headerLines.add("Content-Type: " + contentType + ";charset=utf-8" + System.lineSeparator()); - headerLines.add("Content-Length: " + body.length + System.lineSeparator()); - return new HttpHeader(headerLines); - } - - private HttpHeader makeResponse302Header() { - List headerLines = new ArrayList<>(); - // TODO 회원 가입에 대한 리다이렉트로 첫 페이지 띄워주게 하드 코딩 했는데 나중에 확장 해야 할듯 - headerLines.add("Location: " + "/index.html" + System.lineSeparator()); - return new HttpHeader(headerLines); - } - - 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()); - } - } -} diff --git a/src/main/java/http/response/HttpStatusLine.java b/src/main/java/http/response/HttpStatusLine.java deleted file mode 100644 index d0770378..00000000 --- a/src/main/java/http/response/HttpStatusLine.java +++ /dev/null @@ -1,21 +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 boolean checkStatus(HttpStatus status){ - return this.httpStatus.equals(status); - } - - public String toStringForResponse(){ - return httpVersion + " " + httpStatus.toString() + System.lineSeparator(); - } -} diff --git a/src/main/java/service/LogInService.java b/src/main/java/service/LogInService.java deleted file mode 100644 index 88240e25..00000000 --- a/src/main/java/service/LogInService.java +++ /dev/null @@ -1,37 +0,0 @@ -package service; - -import db.Database; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import util.HttpRequestUtils; - -import java.util.Map; - -public class LogInService { - private static final Logger logger = LoggerFactory.getLogger(SignUpService.class); - - public static boolean isLoginSuccess(String body) { - Map params = HttpRequestUtils.parseQueryString(body); - - 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; - - } -} diff --git a/src/main/java/service/SignUpService.java b/src/main/java/service/SignUpService.java deleted file mode 100644 index 8e12519c..00000000 --- a/src/main/java/service/SignUpService.java +++ /dev/null @@ -1,27 +0,0 @@ -package service; - -import controller.UserController; -import model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import util.HttpRequestUtils; - -import java.util.Map; -import java.util.regex.Pattern; - -public class SignUpService{ - private static final Logger logger = LoggerFactory.getLogger(SignUpService.class); - public static User makeUserByBody(String body) { - Map params = HttpRequestUtils.parseQueryString(body); - - User user = new User( - params.get("userId"), - params.get("password"), - params.get("name"), - params.get("email")); - - logger.debug("User : {}", user); - - return user; - } -} diff --git a/src/main/java/util/HttpRequestUtils.java b/src/main/java/util/HttpRequestUtils.java deleted file mode 100644 index d0822ee6..00000000 --- a/src/main/java/util/HttpRequestUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -package util; - -import http.HttpHeader; -import http.request.HttpRequestLine; -import http.HttpUri; -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 5893c9eb..00000000 --- a/src/main/java/util/HttpResponseUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -package util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -public class HttpResponseUtils { - private static final Logger logger = LoggerFactory.getLogger(HttpResponseUtils.class); - - private static final String basePath = "./src/main/resources"; - private static final String htmlFilePath = "/templates"; - private static final String staticFilePath = "/static"; - - public static String makeFilePath(String contentType) { - if (contentType.equals("text/html")) { - return basePath + htmlFilePath; - } - return basePath + staticFilePath; - } - - public static byte[] makeBody(String httpUri, String filePath) { - logger.debug("filePath get : {}", filePath + httpUri); - try { - return Files.readAllBytes(new File(filePath + httpUri).toPath()); - } catch (IOException e) { - return " 파일을 찾지 못함 !".getBytes(); - } - } - -} diff --git a/src/main/java/webserver/ControllerHandler.java b/src/main/java/webserver/ControllerHandler.java deleted file mode 100644 index becf7473..00000000 --- a/src/main/java/webserver/ControllerHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -package webserver; - -import controller.Controller; -import controller.StaticFileController; -import controller.UserController; -import http.request.HttpRequest; - -public class ControllerHandler { - public static Controller handleController(HttpRequest httpRequest) { - //TODO httpRequest 보고 어떤 컨트롤러 써야되는지 리턴 해줘야됨 - - // 어떤 기능 (회원가입, 로그인 등) 을 원한다면? - // POST 요청일 때 - if (httpRequest.isPost()) { - // 누가 원하는지 > 누구의 컨트롤러가 필요한지 넘겨줌 - // User가 원하면 UserController - return whoWant(httpRequest.getUri()); - } - - // 정적 파일만 원한다면? ex) index.html, /user/form.html - if (httpRequest.wantStatic()) return new StaticFileController(); - - //TODO 아무것도 없으면 나중에 예외처리 - return null; - } - - // 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 b801353f..00000000 --- a/src/main/java/webserver/RequestHandler.java +++ /dev/null @@ -1,48 +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; - -import static java.util.Objects.isNull; - -public class RequestHandler implements Runnable { - private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class); - - private 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 88cce46b..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/logback.xml b/src/main/resources/logback-spring.xml similarity index 100% rename from src/main/resources/logback.xml rename to src/main/resources/logback-spring.xml diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index aa599d33..69c149d4 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -1,5 +1,6 @@ + @@ -69,14 +70,15 @@ @@ -86,38 +88,21 @@
    @@ -80,19 +82,23 @@
    -
    +
    + +
    +
    diff --git a/src/main/resources/templates/qna/show.html b/src/main/resources/templates/qna/show.html index 261ac16e..2c7a5329 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..0244618d 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 77732d3a..e6a0536a 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,18 +93,11 @@ - - 1 - javajigi - 자바지기 - javajigi@sample.net - 수정 - - - 2 - slipp - 슬립 - slipp@sample.net + + + + + 수정 diff --git a/src/main/resources/templates/user/login.html b/src/main/resources/templates/user/login.html index f843a966..5cb8a852 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..ea79c6e2 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 a3a4ee76..ffa84b2e 100644 --- a/src/main/resources/templates/user/profile.html +++ b/src/main/resources/templates/user/profile.html @@ -1,5 +1,6 @@ + @@ -68,11 +69,11 @@ diff --git a/src/test/java/HttpRequestUtilsTest.java b/src/test/java/HttpRequestUtilsTest.java deleted file mode 100644 index 748682e4..00000000 --- a/src/test/java/HttpRequestUtilsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -import http.request.HttpRequestLine; -import http.HttpUri; -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"; - @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")); - } - - String queryString = "userId=jhchoi57&" + - "password=12349865&" + - "name=%EC%B5%9C%EC%A3%BC%ED%98%95&" + - "email=jhchoi57%40gmail.com"; - - @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 f6fd15a1..00000000 --- a/src/test/java/HttpResponseUtilsTest.java +++ /dev/null @@ -1,32 +0,0 @@ -import org.junit.jupiter.api.DisplayName; -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 { - String basePath = "./src/main/resources"; - String htmlFilePath = "/templates"; - String staticFilePath = "/static"; - @Test - @DisplayName("contentType을 입력 받고 알맞는 file path 반환") - public void makeFilePath() { - String path = HttpResponseUtils.makeFilePath("text/html"); - assertThat(path).isEqualTo(basePath + htmlFilePath); - path = HttpResponseUtils.makeFilePath("text/css"); - assertThat(path).isEqualTo(basePath + staticFilePath); - } - - @Test - @DisplayName("httprequest 속의 uri와 파일 경로를 입력받아서 http response body 생성") - public void makeBody() throws IOException { - String httpUri = "/user/form.html"; - String filePath = basePath + htmlFilePath; - assertThat(HttpResponseUtils.makeBody(httpUri, filePath)) - .isEqualTo(Files.readAllBytes(new File(filePath + httpUri).toPath())); - } -} diff --git a/src/test/java/SignUpServiceTest.java b/src/test/java/SignUpServiceTest.java deleted file mode 100644 index eefc115d..00000000 --- a/src/test/java/SignUpServiceTest.java +++ /dev/null @@ -1,26 +0,0 @@ -import model.User; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import service.SignUpService; - -import static org.assertj.core.api.Assertions.assertThat; - -public class SignUpServiceTest { - @Test - @DisplayName("회원 가입 시 유저 정보들을 유저 클래스에 잘 담아 주는지 테스트") - void makeUserInfoTest() { - // given - final String uri = "/user/create?userId=jhchoi57&" + - "password=12349865&" + - "name=%EC%B5%9C%EC%A3%BC%ED%98%95&" + - "email=jhchoi57%40gmail.com"; - - // when - final User user = SignUpService.makeUserInfo(uri); - - // then - assertThat(user).usingRecursiveComparison().isEqualTo(new User( - "jhchoi57", "12349865", "최주형", "jhchoi57@gmail.com")); - } - -} 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() { + } + +} diff --git a/src/test/java/bejavawebserver/repository/JdbcRepositoryTest.java b/src/test/java/bejavawebserver/repository/JdbcRepositoryTest.java new file mode 100644 index 00000000..ffed4a42 --- /dev/null +++ b/src/test/java/bejavawebserver/repository/JdbcRepositoryTest.java @@ -0,0 +1,28 @@ +package bejavawebserver.repository; + +import bejavawebserver.model.User; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.sql.DataSource; +import java.sql.SQLException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class JdbcRepositoryTest { + @Autowired JdbcRepository jdbcRepository; + @Test + @DisplayName("데이터베이스에 유저 추가 테스트") + void addUser() throws SQLException { + // given + User user = new User("testid", "testpassword", "주형", "test@gmail.com"); + // when + jdbcRepository.addUser(user); + // then + assertThat(jdbcRepository.findUserById(user.getUserId())).usingRecursiveComparison().isEqualTo(user); + } +} \ No newline at end of file