diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..c2e00bc4 --- /dev/null +++ b/.idea/.name @@ -0,0 +1,5 @@ +<<<<<<< Updated upstream +9 WEEK MISSION.md +======= +10 WEEK MISSION.md +>>>>>>> Stashed changes diff --git a/10 WEEK/hello/.gitignore b/10 WEEK/hello/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/10 WEEK/hello/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.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/10 WEEK/hello/build.gradle b/10 WEEK/hello/build.gradle new file mode 100644 index 00000000..e09db68d --- /dev/null +++ b/10 WEEK/hello/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.1.8' + id 'io.spring.dependency-management' version '1.1.4' +} + +group = 'com.example' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('bootBuildImage') { + builder = 'paketobuildpacks/builder-jammy-base:latest' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/10 WEEK/hello/gradle/wrapper/gradle-wrapper.jar b/10 WEEK/hello/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..d64cd491 Binary files /dev/null and b/10 WEEK/hello/gradle/wrapper/gradle-wrapper.jar differ diff --git a/10 WEEK/hello/gradle/wrapper/gradle-wrapper.properties b/10 WEEK/hello/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1af9e093 --- /dev/null +++ b/10 WEEK/hello/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/10 WEEK/hello/gradlew b/10 WEEK/hello/gradlew new file mode 100644 index 00000000..1aa94a42 --- /dev/null +++ b/10 WEEK/hello/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# 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. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# 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/HEAD/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 +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 + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +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 ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +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 + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + 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 +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +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" || "$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 + 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 + # 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 +fi + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +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. +# + +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/10 WEEK/hello/gradlew.bat b/10 WEEK/hello/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/10 WEEK/hello/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +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! +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 + +:omega diff --git a/10 WEEK/hello/settings.gradle b/10 WEEK/hello/settings.gradle new file mode 100644 index 00000000..e2ef993c --- /dev/null +++ b/10 WEEK/hello/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'hello' diff --git a/10 WEEK/hello/src/main/java/com/example/hello/HelloApplication.java b/10 WEEK/hello/src/main/java/com/example/hello/HelloApplication.java new file mode 100644 index 00000000..9b146784 --- /dev/null +++ b/10 WEEK/hello/src/main/java/com/example/hello/HelloApplication.java @@ -0,0 +1,13 @@ +package com.example.hello; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HelloApplication { + + public static void main(String[] args) { + SpringApplication.run(HelloApplication.class, args); + } + +} diff --git a/10 WEEK/hello/src/main/java/com/example/hello/controller/StudentController.java b/10 WEEK/hello/src/main/java/com/example/hello/controller/StudentController.java new file mode 100644 index 00000000..60144668 --- /dev/null +++ b/10 WEEK/hello/src/main/java/com/example/hello/controller/StudentController.java @@ -0,0 +1,61 @@ +package com.example.hello.controller; + +import com.example.hello.entity.Student; +import com.example.hello.repository.StudentRepository; +import com.example.hello.service.StudentService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.util.List; + +@Controller +@RequiredArgsConstructor +@RequestMapping("/student/students") +public class StudentController { + + private final StudentRepository studentRepository; + private final StudentService studentService; + + @GetMapping + public String students(Model model) { + List students = studentService.showAllStudents(); + model.addAttribute("students",students); + return "/student/students"; + } + + @GetMapping("/add") + public String addForm(Model model) { + return "student/studentAddForm"; + } + + @PostMapping("/add") + public String save(@ModelAttribute("student") Student student, RedirectAttributes redirectAttributes) { + Student savedStudent = studentService.addStudent(student); + redirectAttributes.addAttribute("studentId",savedStudent.getStudentCode()); + redirectAttributes.addAttribute("status",true); + return "redirect:/student/students/{studentCode}"; + } + + @GetMapping("/{studentCode}") + public String student(@PathVariable long studentCode, Model model) { + Student student = studentService.findStudent(studentCode); + model.addAttribute("student",student); + return "student/student"; + } + + @GetMapping("/{studentCode}/edit") + public String editForm(@PathVariable Long studentCode, Model model) { + Student student = studentService.findStudent(studentCode); + model.addAttribute("student",student); + return "student/studentEditForm"; + } + + @PostMapping("/{studentCode}/edit") + public String edit(@PathVariable Long studentCode, @ModelAttribute Student student) { + studentService.updateStudent(studentCode,student); + return "redirect:/student/students/{studentCode}"; + } +} diff --git a/10 WEEK/hello/src/main/java/com/example/hello/entity/Student.java b/10 WEEK/hello/src/main/java/com/example/hello/entity/Student.java new file mode 100644 index 00000000..ee00995c --- /dev/null +++ b/10 WEEK/hello/src/main/java/com/example/hello/entity/Student.java @@ -0,0 +1,19 @@ +package com.example.hello.entity; + +import lombok.Data; + +@Data +public class Student { + private String name; + private String dept; + private Long id; + private int grade; + private String studentCode; + + public Student(String name, String dept, int grade ,String studentCode) { + this.name = name; + this.dept = dept; + this.grade = grade; + this.studentCode = studentCode; + } +} diff --git a/10 WEEK/hello/src/main/java/com/example/hello/repository/StudentRepository.java b/10 WEEK/hello/src/main/java/com/example/hello/repository/StudentRepository.java new file mode 100644 index 00000000..90e5b7fb --- /dev/null +++ b/10 WEEK/hello/src/main/java/com/example/hello/repository/StudentRepository.java @@ -0,0 +1,42 @@ +package com.example.hello.repository; + +import com.example.hello.entity.Student; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Repository +public class StudentRepository { + + private static final Map store = new HashMap<>(); + private static Long sequence = 0L; + + public Student save(Student student) { + student.setId(++sequence); + store.put(student.getId(), student); + return student; + } + + public Student findById(Long id) { + return store.get(id); + } + + public List findAll() { + return new ArrayList<>(store.values()); + } + + public int findStudentCount() { + return store.size(); + } + + public void update(Long studentCode, Student updateParam) { + Student findStudent = findById(studentCode); + findStudent.setName(updateParam.getName()); + findStudent.setDept(updateParam.getDept()); + findStudent.setGrade(updateParam.getGrade()); + findStudent.setStudentCode(updateParam.getStudentCode()); + } +} diff --git a/10 WEEK/hello/src/main/java/com/example/hello/service/StudentService.java b/10 WEEK/hello/src/main/java/com/example/hello/service/StudentService.java new file mode 100644 index 00000000..44010ac1 --- /dev/null +++ b/10 WEEK/hello/src/main/java/com/example/hello/service/StudentService.java @@ -0,0 +1,32 @@ +package com.example.hello.service; + +import com.example.hello.entity.Student; +import com.example.hello.repository.StudentRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class StudentService { + + private final StudentRepository studentRepository; + + public List showAllStudents() { + return studentRepository.findAll(); + } + public Student addStudent(Student student) { + Student savedStudent = studentRepository.save(student); + return savedStudent; + } + + public Student findStudent(Long studentCode) { + Student foundStudent = studentRepository.findById(studentCode); + return foundStudent; + } + + public void updateStudent(Long studentCode, Student updateParam) { + studentRepository.update(studentCode,updateParam); + } +} diff --git a/10 WEEK/hello/src/main/resources/application.properties b/10 WEEK/hello/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/10 WEEK/hello/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/10 WEEK/hello/src/test/java/com/example/hello/HelloApplicationTests.java b/10 WEEK/hello/src/test/java/com/example/hello/HelloApplicationTests.java new file mode 100644 index 00000000..2e62e647 --- /dev/null +++ b/10 WEEK/hello/src/test/java/com/example/hello/HelloApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.hello; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class HelloApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/11 WEEK/hello/.gitignore b/11 WEEK/hello/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/11 WEEK/hello/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.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/11 WEEK/hello/build.gradle b/11 WEEK/hello/build.gradle new file mode 100644 index 00000000..e09db68d --- /dev/null +++ b/11 WEEK/hello/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.1.8' + id 'io.spring.dependency-management' version '1.1.4' +} + +group = 'com.example' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('bootBuildImage') { + builder = 'paketobuildpacks/builder-jammy-base:latest' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/11 WEEK/hello/gradle/wrapper/gradle-wrapper.jar b/11 WEEK/hello/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..d64cd491 Binary files /dev/null and b/11 WEEK/hello/gradle/wrapper/gradle-wrapper.jar differ diff --git a/11 WEEK/hello/gradle/wrapper/gradle-wrapper.properties b/11 WEEK/hello/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1af9e093 --- /dev/null +++ b/11 WEEK/hello/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/11 WEEK/hello/gradlew b/11 WEEK/hello/gradlew new file mode 100644 index 00000000..1aa94a42 --- /dev/null +++ b/11 WEEK/hello/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# 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. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# 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/HEAD/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 +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 + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +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 ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +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 + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + 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 +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +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" || "$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 + 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 + # 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 +fi + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +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. +# + +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/11 WEEK/hello/gradlew.bat b/11 WEEK/hello/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/11 WEEK/hello/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +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! +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 + +:omega diff --git a/11 WEEK/hello/settings.gradle b/11 WEEK/hello/settings.gradle new file mode 100644 index 00000000..e2ef993c --- /dev/null +++ b/11 WEEK/hello/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'hello' diff --git a/11 WEEK/hello/src/main/java/com/example/hello/HelloApplication.java b/11 WEEK/hello/src/main/java/com/example/hello/HelloApplication.java new file mode 100644 index 00000000..9b146784 --- /dev/null +++ b/11 WEEK/hello/src/main/java/com/example/hello/HelloApplication.java @@ -0,0 +1,13 @@ +package com.example.hello; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HelloApplication { + + public static void main(String[] args) { + SpringApplication.run(HelloApplication.class, args); + } + +} diff --git a/11 WEEK/hello/src/main/java/com/example/hello/controller/StudentController.java b/11 WEEK/hello/src/main/java/com/example/hello/controller/StudentController.java new file mode 100644 index 00000000..60144668 --- /dev/null +++ b/11 WEEK/hello/src/main/java/com/example/hello/controller/StudentController.java @@ -0,0 +1,61 @@ +package com.example.hello.controller; + +import com.example.hello.entity.Student; +import com.example.hello.repository.StudentRepository; +import com.example.hello.service.StudentService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.util.List; + +@Controller +@RequiredArgsConstructor +@RequestMapping("/student/students") +public class StudentController { + + private final StudentRepository studentRepository; + private final StudentService studentService; + + @GetMapping + public String students(Model model) { + List students = studentService.showAllStudents(); + model.addAttribute("students",students); + return "/student/students"; + } + + @GetMapping("/add") + public String addForm(Model model) { + return "student/studentAddForm"; + } + + @PostMapping("/add") + public String save(@ModelAttribute("student") Student student, RedirectAttributes redirectAttributes) { + Student savedStudent = studentService.addStudent(student); + redirectAttributes.addAttribute("studentId",savedStudent.getStudentCode()); + redirectAttributes.addAttribute("status",true); + return "redirect:/student/students/{studentCode}"; + } + + @GetMapping("/{studentCode}") + public String student(@PathVariable long studentCode, Model model) { + Student student = studentService.findStudent(studentCode); + model.addAttribute("student",student); + return "student/student"; + } + + @GetMapping("/{studentCode}/edit") + public String editForm(@PathVariable Long studentCode, Model model) { + Student student = studentService.findStudent(studentCode); + model.addAttribute("student",student); + return "student/studentEditForm"; + } + + @PostMapping("/{studentCode}/edit") + public String edit(@PathVariable Long studentCode, @ModelAttribute Student student) { + studentService.updateStudent(studentCode,student); + return "redirect:/student/students/{studentCode}"; + } +} diff --git a/11 WEEK/hello/src/main/java/com/example/hello/entity/Student.java b/11 WEEK/hello/src/main/java/com/example/hello/entity/Student.java new file mode 100644 index 00000000..ee00995c --- /dev/null +++ b/11 WEEK/hello/src/main/java/com/example/hello/entity/Student.java @@ -0,0 +1,19 @@ +package com.example.hello.entity; + +import lombok.Data; + +@Data +public class Student { + private String name; + private String dept; + private Long id; + private int grade; + private String studentCode; + + public Student(String name, String dept, int grade ,String studentCode) { + this.name = name; + this.dept = dept; + this.grade = grade; + this.studentCode = studentCode; + } +} diff --git a/11 WEEK/hello/src/main/java/com/example/hello/repository/StudentRepository.java b/11 WEEK/hello/src/main/java/com/example/hello/repository/StudentRepository.java new file mode 100644 index 00000000..90e5b7fb --- /dev/null +++ b/11 WEEK/hello/src/main/java/com/example/hello/repository/StudentRepository.java @@ -0,0 +1,42 @@ +package com.example.hello.repository; + +import com.example.hello.entity.Student; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Repository +public class StudentRepository { + + private static final Map store = new HashMap<>(); + private static Long sequence = 0L; + + public Student save(Student student) { + student.setId(++sequence); + store.put(student.getId(), student); + return student; + } + + public Student findById(Long id) { + return store.get(id); + } + + public List findAll() { + return new ArrayList<>(store.values()); + } + + public int findStudentCount() { + return store.size(); + } + + public void update(Long studentCode, Student updateParam) { + Student findStudent = findById(studentCode); + findStudent.setName(updateParam.getName()); + findStudent.setDept(updateParam.getDept()); + findStudent.setGrade(updateParam.getGrade()); + findStudent.setStudentCode(updateParam.getStudentCode()); + } +} diff --git a/11 WEEK/hello/src/main/java/com/example/hello/service/StudentService.java b/11 WEEK/hello/src/main/java/com/example/hello/service/StudentService.java new file mode 100644 index 00000000..44010ac1 --- /dev/null +++ b/11 WEEK/hello/src/main/java/com/example/hello/service/StudentService.java @@ -0,0 +1,32 @@ +package com.example.hello.service; + +import com.example.hello.entity.Student; +import com.example.hello.repository.StudentRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class StudentService { + + private final StudentRepository studentRepository; + + public List showAllStudents() { + return studentRepository.findAll(); + } + public Student addStudent(Student student) { + Student savedStudent = studentRepository.save(student); + return savedStudent; + } + + public Student findStudent(Long studentCode) { + Student foundStudent = studentRepository.findById(studentCode); + return foundStudent; + } + + public void updateStudent(Long studentCode, Student updateParam) { + studentRepository.update(studentCode,updateParam); + } +} diff --git a/11 WEEK/hello/src/main/resources/application.properties b/11 WEEK/hello/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/11 WEEK/hello/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/11 WEEK/hello/src/test/java/com/example/hello/HelloApplicationTests.java b/11 WEEK/hello/src/test/java/com/example/hello/HelloApplicationTests.java new file mode 100644 index 00000000..2e62e647 --- /dev/null +++ b/11 WEEK/hello/src/test/java/com/example/hello/HelloApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.hello; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class HelloApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/2 WEEK/KIM/ANSWER.md b/2 WEEK/KIM/ANSWER.md index 066e2c2a..0f8d41dc 100644 --- a/2 WEEK/KIM/ANSWER.md +++ b/2 WEEK/KIM/ANSWER.md @@ -44,8 +44,8 @@ https://agilemanifesto.org/iso/ko/manifesto.html
--- ## 주요 이론 요약 + 개방 폐쇄 원칙에 따라 수정을 지양하여 FixDiscountPolicy의 수정 대신 DiscountPolicy를 구현한 RateDiscountPolicy를 구현하여 해결하였다. 또한 의존 역전 원칙을 준수하여 인터페이스를 구현하여 생성하였고, 가격의 정률 할인이라는 하나의 기능만을 구현하여 단일 책임 원칙을 준수하였다. -Please provide a summary of your main theory here. ## ISSUE @@ -56,8 +56,53 @@ Please enter your issue details here. Please describe your solution in detail here. ## About + solid 원칙 -> single responsibility principle, open-closed principle, liskov substitution principle, interface segregation principle, dependency inversion principle 5가지 원칙의 앞 이니셜을 따서 solid원칙이라 부른다. -Please enter your personal feelings, what you learned, and what you need to learn here. + - single responsibility principle -> + 단일 책임 원칙, 하나의 요소가 하나의 책임만을 가져야 한다 -> 코드의 가독성을 높이고, 버그를 예방한다. + + - open-closed principle -> + 개방 폐쇄 원칙, 확장에는 열려있고 수정에는 닫혀 있다는 개념 -> 추상화와 다형성을 활용하여 클래스 설계한다. + + - liskov substitution principle -> + 리스코프 치환 원칙, 자식 클래스가 항상 부모 클래스를 대신 할 수 있다는 개념 -> + ex) 도형 클래스(부모) 사각형 클래스(자식) + 1) 도형은 넓이를 가진다 ===> 1) 사각형은 넓이를 가진다 + 2) 도형은 둘레를 가진다 ===> 2) 사각형은 둘레를 가진다 + 3) 도형은 각을 가진다 3) 사각형은 각을 가진다 + + 도형 클래스(부모) 원 클래스(자식) + 1) 도형은 넓이를 가진다 ===> 1) 원은 넓이를 가진다 + 2) 도형은 둘레를 가진다 ===> 2) 원은 둘레를 가진다 + 3) 도형은 각을 가진다 3) 원은 각을 가진다 + + 이때 원 클래스가 부모의 3번 메소드를 수행하지 못하므로 해당 클래스는 자식 클래스가 부모 클래스를 대체하지 못하여 리스코프 치환원칙을 준수하지 못하고 있다고 할 수 있다. 따라서 3번의 메소드를 삭제, 또는 수정하여 리스코프 치환원칙을 준수 하게끔 할 수 있다. + + - interface segregation principle -> + 인터페이스 분리 법칙, 클래스 내에 사용하지 않는 인터페이스는 구현하지 않는다, 즉 자신이 사용하지 않는 메소드에 의존하지 않는다 -> 불필요한 의존도성을 줄이고 코드의 결합도를 낮출 수 있다. + + - dependency inversion principle -> + 의존 역전의 원칙, 의존관계에 있어서 수정 가능성이 높은 것보다 낮은 것에 의존해야 한다. 객체지향 관점에서 볼 때 수정 가능성이 높은 것은 주로 구체화된 클래스들을 뜻하고, 수정 가능성이 낮은 것들은 추상클래스나 인터페이스를 뜻한다. -> 코드의 재사용성과 유연성을 향상시킬 수 있다. + + 3Week study + + DI -> Dependency Injection(의존성 주입) -> + 스프링이 다른 프레임워크와 차별화되어 제공하는 기능, 객체를 직접 생성하지 않고 외부에서 생성 후 주입시키는 방식. -> 모듈 간 결합도가 낮아지고 유연성이 높아진다. + + IOC -> Inversion of Control(제어의 역전) -> + 메소드,객체의 호출작업을 개발자가 아닌 외부에서 결정하는 것. -> 객체의 의존성을 역전시켜 객체 간의 결합도를 낮추고 유연한 코드를 작성 가능하게 하여 가독성 향상, 코드 중복 방지, 유지 보수 용이 의 장점존재. + -> 모든 의존성 객체를 스프링이 생성하여 주입시킴으로써 모든 의존성 객체들은 SingleTone Pattern 특징을 갖는다. + + Spring Container -> + 스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트로 자바 객체(bean)의 생명 주기를 관리한다. + 스프링 컨테이너는 BeanFactory, ApplicationContext 두 종류의 인터페이스로 구현되어있다. + + BeanFactory -> 빈의 생성, 관계설정 같은 제어를 담당하는 IOC 오브젝트, getBean() 메서드를 통해 빈을 인스턴스화 할 수 있다. + + ApplicationContext -> BeanFactory를 좀더 확장한 것. (주로 사용됨) + + 사용 목적(장점) -> + 객체를 컨테이너에서 생성하여 주입함으로써 객체 간의 의존성,결합도를 낮추고 캡슐화 기능을 향상시킨다. ## Question To Reader diff --git a/2 WEEK/KIM/kim_2WEEK/.gitignore b/2 WEEK/KIM/kim_2WEEK/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.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/2 WEEK/KIM/kim_2WEEK/1 week.md b/2 WEEK/KIM/kim_2WEEK/1 week.md new file mode 100644 index 00000000..283a343d --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/1 week.md @@ -0,0 +1,450 @@ +![header](https://capsule-render.vercel.app/api?type=soft&color=auto&height=150§ion=header&text=UserManagement&fontSize=90&animation=blink&align=center) + +-- +## Tech Stack +![Java](https://img.shields.io/badge/Java-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white) +## DB +![Memory](https://img.shields.io/badge/Memory-000000?style=for-the-badge&logo=memory&logoColor=white) +## ORM +![OMR](https://img.shields.io/badge/NONE-000000?style=for-the-badge&logo=NONE&logoColor=white) +## IDE +![intelliJ](https://img.shields.io/badge/IntelliJIDEA-000000?style=for-the-badge&logo=IntelliJIDEA&logoColor=white) +## TEST +![Junit5](https://img.shields.io/badge/JUnit5-25A162?style=for-the-badge&logo=JUnit5&logoColor=white) +## SCM +![GITHUB](https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white) +-- +## 요구사항 +[ 회원 ]
+회원을 가입하고 조회할 수 있다.
+회원등급 일반 / VIP 등급이 있다.
+회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)
+회원 ID (자동 생성), 회원 이름, 등급 +[ 주문과 할인 정책 ]
+회원은 상품을 주문할 수 있다.
+회원 등급에 따라 할인 정책을 적용할 수 있다.
+할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인 적용 (나중에 변경 될 수 있다.)
+할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루고 싶다. 최악의 경우 할인을 적용하지 않을 수 도 있다. (미확정)
+주문 번호 (자동 생성), 상품 이름, 상품 가격, 할인 받은 가격 + +## ANSWER + +# 비즈니스 요구사항 + +--- + +### 회원 + +- 회원을 가입하고 조회할 수 있다. +- 회원은 일반과 VIP 두 가지 등급 +- 회원 데이터는 자체 DB를 구출할 수 있고, 외부 시스템과 연동할 수 있다. [ 미확정 ] + +### 주문과 할일 정책 + +- 회원은 상품을 주문할 수 있다. +- 회원 등급에 따라 할인 정책을 적용할 수 있다. +- 할인 정책은 모든 VIP는 1000원을 할인 - 고정 금액 할인을 적용 [ 나중에 변경 될 수 있다. ] +- 할인 정책은 변경 가능성이 높다. + +## Member Domain + +![스크린샷 2023-11-11 11 27 21](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/893fb79a-4b90-486b-b534-da5b223f0cff) + +## Member Class Diagram + +![스크린샷 2023-11-11 11 28 30](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/8a388b8e-edda-4ecb-9545-7feaf3252745) + +## 회원 객체 다이어그램 + +![스크린샷 2023-11-11 11 28 36](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/83699dbd-be8f-48ff-aa25-c82ec4ee0652) + +## 회원 도메인 개발 + +--- + +### Grade + +```java +package hello.core.member; + +public enum Grade { + + BASIC, + VIP + +} +``` + +상수, enum 등은 변수명을 대문자로 사용하는 관례가 있다. + +### Member Entity + +```java +package hello.core.member; + +public class Member { + + private Long id; + private String name; + private Grade grade; + + public Member( String name, Grade grade) { + this.name = name; + this.grade = grade; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Grade getGrade() { + return grade; + } + + public void setGrade(Grade grade) { + this.grade = grade; + } +} +``` + +### Member Repository Interface + +```java +package hello.core.member; + +public interface MemberRepository { + + void save(Member member); + + Member findById(Long memberId); + +} +``` + +### Member Repository 구현체 + +```java +package hello.core.member; + +import java.util.HashMap; +import java.util.Map; + +public class MemoryMemberRepository implements MemberRepository { + + private static Map store = new HashMap<>(); + private static long SEQUENCE = 0L; + + @Override + public void save(Member member) { + member.setId(++SEQUENCE); + store.put(member.getId(),member); + } + + @Override + public Member findById(Long memberId) { + return store.get(memberId); + } +} +``` + +> 참고 : `HashMap` 은 동시성 ISSUE 가 발생할 수 있다. 이런 경우 `ConcurrentHashMap` 을 사용하자. +> + +### Member Service Interface + +```java +package hello.core.member; + +public interface MemberService { + + void join(Member member); + + Member findMember(Long memberId); + +} +``` + +### Member Service 구현체 + +```java +package hello.core.member; + +public class MemberServiceImpl implements MemberService{ + + private final MemberRepository memberRepository = new MemoryMemberRepository(); + + @Override + public void join(Member member) { + memberRepository.save(member); + } + + @Override + public Member findMember(Long memberId) { + return memberRepository.findById(memberId); + } +} +``` + +### 회원 도메인 실행과 테스트 + +회원 가입 main + +```java +package hello.core; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; + +public class MemberApp { + + public static void main(String[] args) { + + MemberService memberService = new MemberServiceImpl(); + + Member member = new Member("memberA", Grade.VIP); + + memberService.join(member); + + Member findMember = memberService.findMember(1L); + + System.out.println("member = " + member.getName()); + System.out.println("findMember = " + findMember.getName()); + + } + +} +``` + +Application logic 으로 이렇게 Test 하는 것은 좋은 방법이 아니다. JUnit Test 를 사용하자 + +### 회원 가입 테스트 + +```java +package hello.core.member; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class MemberServiceTest { + + MemberService memberService = new MemberServiceImpl(); + + @Test + void join() { + //given + Member member = new Member("memberA",Grade.VIP); + + //when + memberService.join(member); + Member findMember = memberService.findMember(1L); + + //then + assertThat(member).isEqualTo(findMember); + + } +} +``` + +# 주문과 할인 도메인 설계 + +--- + +### 주문 도메인 협력, 역할, 책임 + +![스크린샷 2023-11-11 11 35 34](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/c107fbf7-d029-4336-bb47-1082079b8fd2) + +1. 주문 생성 : 클라이언트는 주문 서비스에 주문 생성을 요청한다. +2. 회원 조회 : 할인을 위해서 회원 등급이 필요하다. 그래서 주문 서비스는 회원 저장소에서 회원을 조회한다. +3. 할인 적용 : 주문 서비스는 회원 등급에 따른 할인 여부를 할인 정책에 위임한다. +4. 주문 결과 반환 : 주문 서비스는 할인 결과를 포함한 주문 결과를 반환한다. + +### 주문 도메인 전체 + +![스크린샷 2023-11-11 11 37 21](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/f25b7df5-8930-41a9-ad03-5abf94aeb244) + + +역할과 구현을 분리해서 자유롭게 구현 객체를 조립할 수 있게 설계한다. + +### 주문 도메인 클래스 다이어그램 + +![스크린샷 2023-11-11 11 38 14](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/b52aee65-a5d0-4a11-8dae-1b25a0b1600f) + + +### 주문 도메인 객체 다이어그램1 + +![스크린샷 2023-11-11 11 38 47](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/df91550c-b8b5-47ac-a35b-ec2b468a61a4) + +### 주문 도메인 객체 다이어그램2 + +![스크린샷 2023-11-11 11 38 53](https://github.com/FX-STUDY/BE-springBasic/assets/100909578/3c353294-4ba5-4f01-9752-f873f64f3d66) + +## 주문과 할인 도메인 개발 + +--- + +### 할인 정책 Interface + +```java +package hello.core.discount; + +import hello.core.member.Member; + +public interface DiscountPolicy { + + int discount(Member member , int price); + +} +``` + +### 정액 할인 정책 구현체 + +```java +package hello.core.discount; + +import hello.core.member.Grade; +import hello.core.member.Member; + +public class FixDiscountPolicy implements DiscountPolicy{ + + private int discountFixAmount = 1000; + + @Override + public int discount(Member member, int price) { + + if (member.getGrade() == Grade.VIP) { + return discountFixAmount; + }else { + return 0; + } + + } +} +``` + +### 주문 엔티티 + +```java +package hello.core.order; + +public class Order { + + private Long memberId; + private String itemName; + private int itemPrice; + private int discountPrice; + + public Order(Long memberId, String itemName, int itemPrice, int discountPrice){ + this.memberId = memberId; + this.itemName = itemName; + this.itemPrice = itemPrice; + this.discountPrice = discountPrice; + } + + public int calculatePrice(){ + return itemPrice - discountPrice; + } + + public int getDiscountPrice(){ + return discountPrice; + } + + @Override + public String toString() { + return "Order{" + + "memberId=" + memberId + + ", itemName='" + itemName + '\'' + + ", itemPrice=" + itemPrice + + ", discountPrice=" + discountPrice + + '}'; + } +} +``` + +### 주문 서비스 인터페이스 + +```java +package hello.core.order; + +public interface OrderService { + Order createOrder(Long memberId, String itemName, int itemPrice); +} +``` + +### 주문 서비스 구현체 + +```java +package hello.core.order; + +import hello.core.discount.DiscountPolicy; +import hello.core.discount.FixDiscountPolicy; +import hello.core.member.Member; +import hello.core.member.MemberRepository; +import hello.core.member.MemoryMemberRepository; + +public class OrderServiceImpl implements OrderService{ + + private final MemberRepository memberRepository = new MemoryMemberRepository(); + private final DiscountPolicy discountPolicy = new FixDiscountPolicy(); + + @Override + public Order createOrder(Long memberId, String itemName, int itemPrice) { + Member member = memberRepository.findById(memberId); + int discountPrice = discountPolicy.discount(member,itemPrice); + return new Order(memberId, itemName, itemPrice, discountPrice); + } +} +``` + +### 주문과 할인 정책 테스트 + +```java +package hello.core.order; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.internal.matchers.Or; + +import static org.junit.jupiter.api.Assertions.*; + +class OrderServiceTest { + + MemberService memberService = new MemberServiceImpl(); + OrderService orderService = new OrderServiceImpl(); + + @Test + void createOrder() { + + Member member = new Member("memberA", Grade.VIP); + memberService.join(member); + + Order order = orderService.createOrder(member.getId(),"itemA",10000); + org.assertj.core.api.Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000); + + } +} +``` +## HOME WORK +1. 위 코드의 핵심은 무엇일까요? +2. 위 코드의 문제점은 무엇일까요? +3. 그 해결 방법은 무엇일까요? diff --git a/2 WEEK/KIM/kim_2WEEK/build.gradle b/2 WEEK/KIM/kim_2WEEK/build.gradle new file mode 100644 index 00000000..fd82e86a --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/build.gradle @@ -0,0 +1,37 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.7.11' + id 'io.spring.dependency-management' version '1.1.3' +} + +group = 'hello' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '11' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + //lombok plugin + implementation('org.projectlombok:lombok') + annotationProcessor('org.projectlombok:lombok') + + //test 환경 + testImplementation('org.projectlombok:lombok') + testAnnotationProcessor('org.projectlombok:lombok') +} + +tasks.named('bootBuildImage') { + builder = 'paketobuildpacks/builder-jammy-base:latest' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/2 WEEK/KIM/kim_2WEEK/gradle/wrapper/gradle-wrapper.jar b/2 WEEK/KIM/kim_2WEEK/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..7f93135c Binary files /dev/null and b/2 WEEK/KIM/kim_2WEEK/gradle/wrapper/gradle-wrapper.jar differ diff --git a/2 WEEK/KIM/kim_2WEEK/gradle/wrapper/gradle-wrapper.properties b/2 WEEK/KIM/kim_2WEEK/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..3fa8f862 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/2 WEEK/KIM/kim_2WEEK/gradlew b/2 WEEK/KIM/kim_2WEEK/gradlew new file mode 100644 index 00000000..1aa94a42 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# 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. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# 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/HEAD/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 +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 + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +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 ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +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 + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + 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 +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +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" || "$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 + 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 + # 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 +fi + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +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. +# + +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/2 WEEK/KIM/kim_2WEEK/gradlew.bat b/2 WEEK/KIM/kim_2WEEK/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +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! +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 + +:omega diff --git a/2 WEEK/KIM/kim_2WEEK/settings.gradle b/2 WEEK/KIM/kim_2WEEK/settings.gradle new file mode 100644 index 00000000..4d52ac57 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'core' diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/CoreApplication.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/CoreApplication.java new file mode 100644 index 00000000..5bc183f2 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/CoreApplication.java @@ -0,0 +1,13 @@ +package hello.core; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CoreApplication { + + public static void main(String[] args) { + SpringApplication.run(CoreApplication.class, args); + } + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/MemberApp.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/MemberApp.java new file mode 100644 index 00000000..e6a35724 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/MemberApp.java @@ -0,0 +1,28 @@ +package hello.core; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; + + + +public class MemberApp { + + public static void main(String[] args) { + + MemberService memberService = new MemberServiceImpl(); + + Member member = new Member("memberA", Grade.VIP); + + memberService.join(member); + + Member findMember = memberService.findMember(1L); + + System.out.println("member = " + member.getName()); + System.out.println("findMember = " + findMember.getName()); + + + } + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/OrderApp.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/OrderApp.java new file mode 100644 index 00000000..f4f577e1 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/OrderApp.java @@ -0,0 +1,24 @@ +package hello.core; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; +import hello.core.order.Order; +import hello.core.order.OrderService; +import hello.core.order.OrderServiceImpl; + +public class OrderApp { + public static void main(String[] args) { + MemberService memberService = new MemberServiceImpl(); + OrderService orderService = new OrderServiceImpl(); + + Member member = new Member("memberA", Grade.VIP); + memberService.join(member); + + Order order = orderService.createOrder(member.getId(),"itemA",100000); + + System.out.println("order = " + order); + + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/DiscountPolicy.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/DiscountPolicy.java new file mode 100644 index 00000000..2b8230ce --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/DiscountPolicy.java @@ -0,0 +1,9 @@ +package hello.core.discount; + +import hello.core.member.Member; + +public interface DiscountPolicy { + + int discount(Member member , int price); + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/FixDiscountPolicy.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/FixDiscountPolicy.java new file mode 100644 index 00000000..3e062abd --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/FixDiscountPolicy.java @@ -0,0 +1,28 @@ +package hello.core.discount; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; +import org.springframework.stereotype.Component; + +@Component("fixDiscountPolicy") +public class FixDiscountPolicy implements DiscountPolicy{ + + private int discountFixAmount = 1000; + + @Override + public int discount(long memberID, int price) { + + MemberService memberService = new MemberServiceImpl(); + + Member member = memberService.findMember(memberID); + + if (member.getGrade() == Grade.VIP) { + return discountFixAmount; + }else { + return 0; + } + + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/RateDiscountPolicy.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/RateDiscountPolicy.java new file mode 100644 index 00000000..3d3290c7 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/discount/RateDiscountPolicy.java @@ -0,0 +1,28 @@ +package hello.core.discount; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; +import org.springframework.stereotype.Component; + +//DiscountPolicy 구현하여 정률 할인정책 구현 +@Component("rateDiscountPolicy") +public class RateDiscountPolicy implements DiscountPolicy{ + + private final int discountRate = 10; + @Override + public int discount(long memberID, int price) { + + MemberService memberService = new MemberServiceImpl(); + + Member member = memberService.findMember(memberID); + + + if(member.getGrade() == Grade.VIP) { + int discountAmount = (int)(discountRate * 0.01 * price); + return discountAmount; + } + return 0; + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/Grade.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/Grade.java new file mode 100644 index 00000000..488c7490 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/Grade.java @@ -0,0 +1,8 @@ +package hello.core.member; + +public enum Grade { + + BASIC, + VIP + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/Member.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/Member.java new file mode 100644 index 00000000..570db098 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/Member.java @@ -0,0 +1,19 @@ +package hello.core.member; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Member { + + private Long id; + private String name; + private Grade grade; + + public Member( String name, Grade grade) { + this.name = name; + this.grade = grade; + } + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberRepository.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberRepository.java new file mode 100644 index 00000000..1b23df5e --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberRepository.java @@ -0,0 +1,9 @@ +package hello.core.member; + +public interface MemberRepository { + + void save(Member member); + + Member findById(Long memberId); + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberService.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberService.java new file mode 100644 index 00000000..9101fe64 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberService.java @@ -0,0 +1,9 @@ +package hello.core.member; + +public interface MemberService { + + void join(Member member); + + Member findMember(Long memberId); + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberServiceImpl.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberServiceImpl.java new file mode 100644 index 00000000..75a72c58 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemberServiceImpl.java @@ -0,0 +1,16 @@ +package hello.core.member; + +public class MemberServiceImpl implements MemberService{ + + private final MemberRepository memberRepository = new MemoryMemberRepository(); + + @Override + public void join(Member member) { + memberRepository.save(member); + } + + @Override + public Member findMember(Long memberId) { + return memberRepository.findById(memberId); + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemoryMemberRepository.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemoryMemberRepository.java new file mode 100644 index 00000000..b292af15 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/member/MemoryMemberRepository.java @@ -0,0 +1,21 @@ +package hello.core.member; + +import java.util.HashMap; +import java.util.Map; + +public class MemoryMemberRepository implements MemberRepository { + + private static Map store = new HashMap<>(); + private static long SEQUENCE = 0L; + + @Override + public void save(Member member) { + member.setId(++SEQUENCE); + store.put(member.getId(),member); + } + + @Override + public Member findById(Long memberId) { + return store.get(memberId); + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/Order.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/Order.java new file mode 100644 index 00000000..e6d5480a --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/Order.java @@ -0,0 +1,38 @@ +package hello.core.order; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Order { + private Long memberId; + private String itemName; + private int itemPrice; + private int discountPrice; + + public Order(Long memberId, String itemName, int itemPrice, int discountPrice){ + this.memberId = memberId; + this.itemName = itemName; + this.itemPrice = itemPrice; + this.discountPrice = discountPrice; + } + + /*public int calculatePrice(){ + return itemPrice - discountPrice; + } + + public int getDiscountPrice(){ + return discountPrice; + }*/ + + @Override + public String toString() { + return "Order{" + + "memberId=" + memberId + + ", itemName='" + itemName + '\'' + + ", itemPrice=" + itemPrice + + ", discountPrice=" + discountPrice + + '}'; + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/OrderService.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/OrderService.java new file mode 100644 index 00000000..c408fb95 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/OrderService.java @@ -0,0 +1,5 @@ +package hello.core.order; + +public interface OrderService { + Order createOrder(Long memberId, String itemName, int itemPrice); +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/OrderServiceImpl.java b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/OrderServiceImpl.java new file mode 100644 index 00000000..20c28b7c --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/java/hello/core/order/OrderServiceImpl.java @@ -0,0 +1,28 @@ +package hello.core.order; + +import hello.core.discount.DiscountPolicy; +import hello.core.discount.FixDiscountPolicy; +import hello.core.discount.RateDiscountPolicy; +import hello.core.member.Member; +import hello.core.member.MemberRepository; +import hello.core.member.MemoryMemberRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +public class OrderServiceImpl implements OrderService{ + @Autowired + private MemberRepository memberRepository; + @Autowired + @Qualifier("rateDiscountPolicy") + private DiscountPolicy discountPolicy; + + + @Override + public Order createOrder(Long memberID, String itemName, int itemPrice) { + Member member = memberRepository.findById(memberID); + int discountPrice = discountPolicy.discount(memberID,itemPrice); + return new Order(memberID, itemName, itemPrice, discountPrice); + } +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/main/resources/application.properties b/2 WEEK/KIM/kim_2WEEK/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/2 WEEK/KIM/kim_2WEEK/src/test/java/com/example/kim_2WEEK/Kim2WeekApplicationTests.java b/2 WEEK/KIM/kim_2WEEK/src/test/java/com/example/kim_2WEEK/Kim2WeekApplicationTests.java new file mode 100644 index 00000000..50941b0b --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/test/java/com/example/kim_2WEEK/Kim2WeekApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.kim_2WEEK; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Kim2WeekApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/CoreApplicationTests.java b/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/CoreApplicationTests.java new file mode 100644 index 00000000..90937b13 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/CoreApplicationTests.java @@ -0,0 +1,13 @@ +package hello.core; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CoreApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/member/MemberServiceTest.java b/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/member/MemberServiceTest.java new file mode 100644 index 00000000..a1e45f7c --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/member/MemberServiceTest.java @@ -0,0 +1,26 @@ +package hello.core.member; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class MemberServiceTest { + + MemberService memberService = new MemberServiceImpl(); + + @Test + void join() { + //given + Member member = new Member("memberA",Grade.VIP); + + //when + memberService.join(member); + Member findMember = memberService.findMember(1L); + + //then + assertThat(member).isEqualTo(findMember); + + } +} \ No newline at end of file diff --git a/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/order/OrderServiceTest.java b/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/order/OrderServiceTest.java new file mode 100644 index 00000000..21fbb759 --- /dev/null +++ b/2 WEEK/KIM/kim_2WEEK/src/test/java/hello/core/order/OrderServiceTest.java @@ -0,0 +1,28 @@ +package hello.core.order; + +import hello.core.member.Grade; +import hello.core.member.Member; +import hello.core.member.MemberService; +import hello.core.member.MemberServiceImpl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.internal.matchers.Or; + +import static org.junit.jupiter.api.Assertions.*; + +class OrderServiceTest { + + MemberService memberService = new MemberServiceImpl(); + OrderService orderService = new OrderServiceImpl(); + + @Test + void createOrder() { + + Member member = new Member("memberA", Grade.VIP); + memberService.join(member); + + Order order = orderService.createOrder(member.getId(),"itemA",10000); + org.assertj.core.api.Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000); + + } +} \ No newline at end of file diff --git a/4 WEEK/item-service/item-service/.gitignore b/4 WEEK/item-service/item-service/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/4 WEEK/item-service/item-service/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.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/4 WEEK/item-service/item-service/build.gradle b/4 WEEK/item-service/item-service/build.gradle new file mode 100644 index 00000000..34550a7d --- /dev/null +++ b/4 WEEK/item-service/item-service/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.1.6' + id 'io.spring.dependency-management' version '1.1.4' +} + +group = 'hello' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('bootBuildImage') { + builder = 'paketobuildpacks/builder-jammy-base:latest' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.jar b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..d64cd491 Binary files /dev/null and b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.jar differ diff --git a/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.properties b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1af9e093 --- /dev/null +++ b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/4 WEEK/item-service/item-service/gradlew b/4 WEEK/item-service/item-service/gradlew new file mode 100644 index 00000000..1aa94a42 --- /dev/null +++ b/4 WEEK/item-service/item-service/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# 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. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# 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/HEAD/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 +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 + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +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 ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +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 + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + 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 +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +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" || "$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 + 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 + # 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 +fi + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +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. +# + +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/4 WEEK/item-service/item-service/gradlew.bat b/4 WEEK/item-service/item-service/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/4 WEEK/item-service/item-service/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +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! +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 + +:omega diff --git a/4 WEEK/item-service/item-service/settings.gradle b/4 WEEK/item-service/item-service/settings.gradle new file mode 100644 index 00000000..df5bd80b --- /dev/null +++ b/4 WEEK/item-service/item-service/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'item-service' diff --git a/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java new file mode 100644 index 00000000..1311934b --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java @@ -0,0 +1,13 @@ +package hello.itemservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ItemServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(ItemServiceApplication.class, args); + } + +} diff --git a/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/controller/ItemController.java b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/controller/ItemController.java new file mode 100644 index 00000000..212a03ee --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/controller/ItemController.java @@ -0,0 +1,42 @@ +package hello.itemservice.controller; + +import hello.itemservice.item.Item; +import hello.itemservice.item.ItemRepository; +import jakarta.annotation.PostConstruct; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.List; + +@RequestMapping("/hello/item") +@Controller +public class ItemController { + private final ItemRepository itemRepository; + + public ItemController(ItemRepository itemRepository) { + this.itemRepository = itemRepository; + } + + @GetMapping("/itemList") + public String itemList(Model model) { + List itemList = itemRepository.findAllItem(); + model.addAttribute("itemList",itemList); + return "itemList"; + } + @GetMapping("/itemAddForm") + public String itemAdd() { + return "itemAddForm"; + } + @GetMapping("/itemFixForm") + public String itemFix() { + return "itemFixForm"; + } + + @PostConstruct + void init() { + itemRepository.saveItem(new Item("item1",10000,1)); + itemRepository.saveItem(new Item("item2",20000,2)); + } +} diff --git a/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/item/Item.java b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/item/Item.java new file mode 100644 index 00000000..d1928ea7 --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/item/Item.java @@ -0,0 +1,22 @@ +package hello.itemservice.item; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Item { + + private long id; + private String itemName; + private long itemPrice; + private long itemCount; + + + public Item(String itemName, long itemPrice, long itemCount) { + this.itemName = itemName; + this.itemPrice = itemPrice; + this.itemCount = itemCount; + } + +} diff --git a/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/item/ItemRepository.java b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/item/ItemRepository.java new file mode 100644 index 00000000..c979e260 --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/item/ItemRepository.java @@ -0,0 +1,32 @@ +package hello.itemservice.item; + +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Repository +public class ItemRepository { + private static final Map store = new HashMap<>(); + private static long sequence = 0L; + + public Item findById(Long id) { + return store.get(id); + } + + public void saveItem(Item item) { + item.setId(++sequence); + store.put(item.getId(),item); + } + + public List findAllItem() { + return new ArrayList<>(store.values()); + } + + public void clear() { + sequence = 0L; + store.clear(); + } +} diff --git a/4 WEEK/item-service/item-service/src/main/resources/application.properties b/4 WEEK/item-service/item-service/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/4 WEEK/item-service/item-service/src/main/resources/templates/itemAddForm.html b/4 WEEK/item-service/item-service/src/main/resources/templates/itemAddForm.html new file mode 100644 index 00000000..63d28dee --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/resources/templates/itemAddForm.html @@ -0,0 +1,29 @@ + + + + + Title + + +

상품 등록 폼

+

상품 입력

+
+
+ +
+
+ + +
+ +
+
+
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/4 WEEK/item-service/item-service/src/main/resources/templates/itemDetail.html b/4 WEEK/item-service/item-service/src/main/resources/templates/itemDetail.html new file mode 100644 index 00000000..ec9c2b9f --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/resources/templates/itemDetail.html @@ -0,0 +1,28 @@ + + + + + Title + + +

상품 상세

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + + + \ No newline at end of file diff --git a/4 WEEK/item-service/item-service/src/main/resources/templates/itemFixForm.html b/4 WEEK/item-service/item-service/src/main/resources/templates/itemFixForm.html new file mode 100644 index 00000000..bcc81d15 --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/resources/templates/itemFixForm.html @@ -0,0 +1,39 @@ + + + + + Title + + +

상품 수정 폼

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/4 WEEK/item-service/item-service/src/main/resources/templates/itemList.html b/4 WEEK/item-service/item-service/src/main/resources/templates/itemList.html new file mode 100644 index 00000000..f5293c38 --- /dev/null +++ b/4 WEEK/item-service/item-service/src/main/resources/templates/itemList.html @@ -0,0 +1,39 @@ + + + + + + Title + + +

상품 목록

+ + + + + + + + + + + + + + + + +
ID상품명가격수량
+ 회원ID + + 상품명 + 1000010
+ + \ No newline at end of file diff --git a/4 WEEK/item-service/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java b/4 WEEK/item-service/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java new file mode 100644 index 00000000..e2ded1be --- /dev/null +++ b/4 WEEK/item-service/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java @@ -0,0 +1,13 @@ +package hello.itemservice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ItemServiceApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/7 WEEK/7 WEEK MISSION.md b/7 WEEK/7 WEEK MISSION.md index fbd823ff..aa7749e2 100644 --- a/7 WEEK/7 WEEK MISSION.md +++ b/7 WEEK/7 WEEK MISSION.md @@ -37,6 +37,72 @@ spring 핵심원리 기본편은 학교에서 대부분 진행한 내용으로 read me 는 필요 시 다시 꺼내서 볼 수 있는 중요자료가 될 것 입니다. --- +## Study 요약 + +8.빈 생명주기 콜백 시작 + +db connection pool, network socket 등 시작 지점에 연결, 어플 종료 시점에 연결 해제하려면 미리 객체의 초기화,종료 작업이 필요.
+ex) 외부 네트워크의 미리 연결하는 객체 생성 시 시작 지점에 connect()를 호출하여 연결, 종료 시점에 disconnect(),close() 호출하여 연결 해제한다.
+ +스프링 빈 라이프사이클 : 객체생성 -> 의존관계 주입 (생성자 예외)
+스프링 빈은 객체를 생성, 의존관계 주입이 모두 끝난 후 사용 가능 -> 초기화 작업은 의존관계 주입이 모두 완료되고 난 이후 호출해야한다.
+스프링은 의존관계 주입이 완료되면 스프링 빈에게 콜백 메서드를 통해 초기화 시점을 알려주는 기능을 제공, 또한 스프링 컨테이너가 종료되기 직전에 소멸 콜백 제공 -> 안전하게 종료 작업 진행 가능
+ +스프링 빈의 이벤트 라이프사이클 :
+스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료
+ +"참고"-> 생성자와 초기화를 분리하여야한다(책임을 분리해야 하고, 유지보수가 용이해진다.)
+스프링의 3가지 빈 생명주기 콜백 :
+인터페이스, 설정 정보에 초기화 메서드, 종료 메서드 지정, @PostConstruct, @PreDestroy
+ +1.초기화,소멸 인터페이스 단점: 이 인터페이스는 스프링 전용 인터페이스로, 해당 코드가 스프링 전용 인터페이스에 의존한다.
+초기화, 소멸 메서드의 이름 변경 불가능
+내가 코드를 고칠 수 없는 외부 라이브러리에 적용 불가능.
+ +2.빈 등록 초기화, 소멸 메서드(@Bean(initMethod= "init메서드이름", destroyMethod="close메서드이름"))
+장점 : 메서드 이름을 자유롭게 지정 가능, 스프링 빈이 스프링 코드에 의존x, 코드가 아니라 설정 정보를 사용하여 코드를 고칠 수 없는 외부 라이브러리에서도 사용 가능
+@Bean destroyMethod는 default가 (inferred)로 등록되어 있어 close, shutdown 이름의 메서드를 자동으로 호출한다. 해당 기능을 사용하고싶지 않을때는 destroyMethod=""을 지정한다.
+ +3.@PostConstruct, @PreDestroy 사용
+init 메서드에 @PostConstruct, close 메서드에 @PreDestroy 어노테이션 사용
+장점 : 최신 스프링에서 가장 권장하는 방법, 사용방법 편리, 스프링이 아닌 다른 컨테이너에서도 동작, 컴포넌트 스캔과 잘 어울린다.
+단점 : 외부 라이브러리에 적용 x, 외부 라이브러리를 초기화 할때는 @Bean 기능 사용
+ +9.빈 스코프 + +빈 스코프 : 빈이 존재할 수 있는 범위, 기본적으로 싱글톤 스코프로 생성된다.
+ +싱글톤 : 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
+프로토타입 : 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관여하지 않는 매우 짧은 범위의 스코프
+request : 웹 요청이 들어오고 나갈때 까지 유지되는 스코프
+session : 웹 세션이 생셩되고 종료될 때 까지 유지되는 스코프
+application : 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프
+ +컴포넌트 스캔 자동등록 : @Component 위에 @Scope("prototype") 사용
+수동 등록 : @Bean 위에 @Scope("prototype") 사용
+ +싱글톤 빈 요청 : 늘 같은 인스턴스의 스프링 빈 반환.
+프로토타입 빈 요청 : 늘 새로운 프로토타입 빈을 생성하여 의존관계를 주입한다.
+프로토타입에 경우 컨테이너가 생성,의존관계 주입,초기화 까지만 담당, 즉 종료 메서드 같은 경우 컨테이너에서 @PreDestroy같은 어노테이션이 적용되지 않아 클라이언트가 직접 종료해야한다.
+싱글톤과 프로토타입 빈은 같이 쓰면 오류가 발생 할 수 있다 ->
+싱글톤 내부에서 의존관계로 프로토타입 빈을 자동주입 할 때 싱글톤 내부에서 프로토타입 빈을 내부 필드에 보관하여 원하는 대로 작동하지 않는다, 즉 프로토타입 빈이 호출할때마다 생성되지 않는다.
+ +프로토타입 스코프 싱글톤 빈과 함께 사용 시 provider로 해결 ->
+ObjectProvider 클래스에 getObject() 메서드를 사용 시 항상 새로운 프로토타입 빈이 생성된다.
+ +웹 스코프 : 웹 환경에서만 동작, 스프링이 해당 스코프의 종료시점까지 관리, 즉 종료 메서드가 호출됨.
+ +웹 스코프 종류 :
+request : Http 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, Http 요청마다 객체 생성, 관리됨
+session : Http session과 동일한 생명주기를 가짐
+application : Servlet Context와 동일한 생명주기를 가짐
+websocket : 웹 소켓과 동일한 생명주기를 가짐
+ +@Scope(value="request", proxyMode = ScopedProxyMode.TARGET_CLASS)
+적용 대상이 클래스면 TARGET_CLASS, 인터페이스면 INTERFACES 선택
+가짜 프록시 클래스를 생성, request와 상관없이 가짜 프록시 클래스를 다른 빈에 미리 주입 가능.
+가짜 프록시 객체는 요청 시 내부에서 진짜 빈을 요청하는 위임 로직 존재.
+-> 싱글톤 빈을 사용하듯이 편리하게 request 사용 가능, 진짜 객체 조회를 필요한 시점까지 지연처리
## Commit Message ROLE Header, Body, Footer는 빈 행으로 구분한다
diff --git a/9 WEEK/9 WEEK MISSION.md b/9 WEEK/9 WEEK MISSION.md index 81f85e9d..70557b96 100644 --- a/9 WEEK/9 WEEK MISSION.md +++ b/9 WEEK/9 WEEK MISSION.md @@ -35,6 +35,91 @@ Server 개발자의 기본 소양인 Spring MVC 부분 입니다.
read me 는 필요 시 다시 꺼내서 볼 수 있는 중요자료가 될 것 입니다. --- +## Study 요약 +@ServletComponentScan : 서블릿을 직접 등록해서 사용할 수 있도록 하는 기능. 메인 함수 포함한 클래스 위에 사용
+@WebServlet : 어노테이션을 제공하여 해당 어노테이션 안에 경로를 입력하면 클라이언트에서, 해당 경로를 입력할 때 알아서 톰캣서버가 찾아서 실행해준다.
+http 요청을 통해 매핑된 url이 호출 -> service() 메서드 실행
+http 요청 데이터 전달 방법 : GET, POST, HTTP message body 직접 담기
+GET : 쿼리 파라미터, 메시지 바디x, url의 쿼리 파라미터에 데이터를 포함하여 전달
+POST : content-type: application/x-www-form-urlencoded, 메시지 바디에 쿼리 파라미터 형식으로 전달
+HTTP message body에 직접 담아서 요청 : HTTP API에서 주로 사용
+@Getter,@Setter : lombok 에서 지원하는 기능으로 getter,setter 구현하지 않아도 알아서 구현해준다.
+@AfterEach : 테스트 코드에서 사용하며 각 테스트가 진행된 후마다 사용되는 메서드에 사용한다.
+@Test : JUnit에서 테스트를 진행하기 위해 사용되는 어노테이션, 여러개의 어노테이션이 있을 경우 동작순서를 보장하지 않는다.
+<%@ page contentType="text/html;charset=UTF-8" language="java" %> : 해당 줄로 시작되는 문서는 jsp문서이다.
+<%@ page import ~~ %> : 자바의 import문과 동일
+<% ~~ %> : 자바 코드 입력 가능
+<%= ~~ %> : 자바 코드 출력 가능
+mvc패턴 개요 : Model, Controller, View
+Model : 뷰에 출력할 데이터를 담아둔다, 뷰가 필요한 데이터를 모델에 담아서 전달
+View : 모델에 담겨있는 데이터를 사용하여 화면을 그리는 일을 담당.
+Controller : HTTP 요청을 받아서 파라미터를 검증, 비즈니스 로직을 실행, 뷰에 전달할 결과 데이터를 조회하여 모델에 담는다.
+FrontController 패턴 특징 : 프론트 컨트롤러 서블릿 하나로 클라이언트 요청을 받음, 프론트 컨트롤러가 요청에 맞는 컨트롤러 호출, 공통 처리 가능, 프론트 컨트롤러 제외 나머지 컨트롤러는 서블릿 사용x
+뷰 리졸버 : 컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경, 실제 물리 경로가 있는 객체 반환
+핸들러 어댑터 : 중간에 어댑터 역할을 하는 어댑터, 다양한 종류의 컨트롤러 호출하는 기능
+핸들러(컨트롤러) : 컨트롤러의 이름을 더 넓은 범위인 핸들러로 변경, 핸들러 어댑터가 존재하여 컨트롤러의 개념 뿐 아닌 어떤것이든 어댑터와 연결하여 처리 가능
+스프링 부트가 자동등록하는 핸들러 매핑 :
+0 = RequestMappinghandlerMapping : 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
+1 = BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.
+스프링 부트가 자동등록하는 핸들러 어댑터 :
+0 = RequestMappingHandlerAdapter : 어노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
+1 = HttpRequestHandlerAdapter : HttpRequestHandler에서 처리
+2 = SimpleControllerHandlerAdapter : Controller 인터페이스에서 처리
+스프링 부트가 자동등록하는 뷰 리졸버 :
+1 = BeanNameViewResolver : 빈 이름으로 뷰를 찾아서 반환.
+2 = InternalResourceViewResolver : JSP를 처리할 수 있는 뷰를 반환.
+ +@RequestMapping : 요청 정보를 매핑한다, 해당 URL이 호출되면 이 메서드가 호출된다.
+@Controller : 스프링이 자동으로 스프링 빈으로 등록, 내부에 @Component 어노테이션이 존재하여 컴포넌트 스캔의 대상이 된다.
+ModelAndView : 모델과 뷰 정보를 담아서 반환한다.
+@RestController : @Controller,@ResponseBody가 추가된 것, Json객체를 반환하기 위한 용도로 사용,@Controller는 반환 값으로 뷰를 찾고, @RestController는 반환 값을 HttpMessageBody에 바로 입력
+@RequestMapping, Http Method 구분하여 사용 : @RequestMapping(value = "url", method = RequestMethod.GET)
+위 줄과 동일하게 @GetMapping, @PostMapping 사용 가능, Put, Delete, Patch 어노테이션 모두 존재
+스프링 부트 기본 로깅 라이브러리 : SLF4J, Logback -> 통합하여 제공(SLF4J 라이브러리)
+로그 사용 장점 :
+쓰레드 정보, 클래스 이름 등 부가 정보를 볼 수 있고, 출력 모양 조정 가능
+로그 레벨에 따라 특정 서버에만 출력 등 상황에 맞게 조절 가능
+시스템 아웃 콘솔에만 출력 뿐 아니라 별도의 위치에 남길 수 있다. 파일로 남길 때는 로그 분할 가능
+성능이 System.out보다 뛰어남, 실무에서 필수 사용
+@PathVariable : 경로 변수, 받아온 값을 바로 매개변수에 대입하여 사용 가능 @PathVariable("userId")식으로 사용, 변수명이 같으면 생략 가능
+회원 관리 예시 crud 매핑 방식 :
+회원 목록 조회 : GET -> /users
+회원 등록 : POST -> /users
+회원 조회 : GET -> /users/{userId}
+회원 수정 : PATCH -> /users/{userId}
+회원 삭제 : DELETE -> /users/{userId}
+@Slf4j : log를 선언하는 코드를 자동으로 생성, log변수 사용하여 로그 사용 가능
+@RequestParam : 파라미터 이름으로 바인딩, HttpServletRequest의 request.getParameter와 동일
+@ResponseBody : View 조회를 무시하고, HTTP message body에 직접 해당 내용 입력
+@ModelAttribute :
+@RequestParam String username;
+@RequestParam int age;
+HelloData data = new HelloData();
+data.setUsername(username);
+data.setAge(age);
+해당 내용을 자동화 해준다. ->
+public String modelAttributeV1(@ModelAttribute HelloData helloData) {
+ log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
+ return "ok";
+}
+해당 예시 처럼 사용하여 객체가 생성되고 해당 객체 내에 setter 호출하여 값을 바인딩한다.
+@ResponseBody : Http 메시지 바디 정보를 조회 가능, 헤더 정보 필요 시 @RequestHeader 사용
+@RequestBody 요청 : JSON 요청 -> HTTP 메시지 컨버터 -> 객체
+@ResponseBody 응답 : 객체 -> HTTP 메시지 컨버터 -> JSON 응답
+부트스트랩 : 웹사이트를 쉽게 만들 수 있게 도와주는 HTML, CSS ,JS 프레임워크
+@RequiredArgsConstructor : final이 붙은 멤버변수만 사용해서 생성자를 자동으로 생성
+@PostConstruct : 해당 빈의 의존관계가 모두 주입된 후 초기화 용도로 사용
+타임리프 선언 :
+th:href -> 속성 변경, HTML을 그대로 볼땐 href 속성이 사용, 뷰 템플릿을 거치면 th:href의 값으로 대체되여 동적으로 변경
+리터럴 대체 문법 : |...|양식으로 사용, +사용하지 않고 문자열 사용 가능
+th:each -> 모델에 포함된 갯수만큼 반복하는 식으로 사용 가능
+th:text -> 내용 변경, 동적으로 해당 내용 변경
+th:value -> 속성 변경, value 속성을 th:value 속성으로 변경
+th:onclick -> 링크 변경, 해당 링크를 동적으로 변경
+th:action -> 속성 변경, GET,POST 등을 동적으로 변경
+새로고침 클릭 시 상품 중복 등록 버그 -> 상품 저장 후 뷰 템플릿이 아닌 상품 상세 화면으로 redirect 호출하여 해결
+ + ## Commit Message ROLE Header, Body, Footer는 빈 행으로 구분한다