From 2ac47af29443c4ae5b9b029e0c1c808f07f7b99a Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 00:23:37 +0900 Subject: [PATCH 01/67] =?UTF-8?q?[chore]:=20gradle=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B0=81=EC=A2=85=20=EB=B2=84=EC=A0=84=20=EC=9D=B8=ED=94=84?= =?UTF-8?q?=EB=9F=B0=20=EA=B9=80=EC=98=81=ED=95=9C=EB=8B=98=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=EC=99=80=20=EB=8F=99=EC=9D=BC=ED=95=98=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index 15b77ef..3999c33 100644 --- a/build.gradle +++ b/build.gradle @@ -1,34 +1,22 @@ plugins { + id 'org.springframework.boot' version '2.3.1.RELEASE' + id 'io.spring.dependency-management' version '1.0.9.RELEASE' id 'java' - id 'org.springframework.boot' version '3.0.1' - id 'io.spring.dependency-management' version '1.1.0' } - group = 'com.dku' version = '0.0.1-SNAPSHOT' -sourceCompatibility = '17' - -configurations { - compileOnly { - extendsFrom annotationProcessor - } -} +sourceCompatibility = '11' repositories { mavenCentral() } - dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.security:spring-security-test' + testImplementation('org.springframework.boot:spring-boot-starter-test') { + exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' + } } - -tasks.named('test') { +test { useJUnitPlatform() -} +} \ No newline at end of file From dc5e59411d9281cbd9881c8ca57e5edef56d6fce Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 00:49:16 +0900 Subject: [PATCH 02/67] =?UTF-8?q?[feat]=20:=20welcome=20page=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springstudy/controller/HelloController.java | 15 +++++++++++++++ src/main/resources/static/index.html | 11 +++++++++++ src/main/resources/templates/hello.html | 10 ++++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/controller/HelloController.java create mode 100644 src/main/resources/static/index.html create mode 100644 src/main/resources/templates/hello.html diff --git a/src/main/java/com/dku/springstudy/controller/HelloController.java b/src/main/java/com/dku/springstudy/controller/HelloController.java new file mode 100644 index 0000000..9e57536 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/HelloController.java @@ -0,0 +1,15 @@ +package com.dku.springstudy.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HelloController { + + @GetMapping("hello") + public String hello(Model model){ + model.addAttribute("data", "hello!!"); + return "hello"; + } +} diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..fb27317 --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,11 @@ + + + + Hello + + + +Hello +hello + + diff --git a/src/main/resources/templates/hello.html b/src/main/resources/templates/hello.html new file mode 100644 index 0000000..81f8f1c --- /dev/null +++ b/src/main/resources/templates/hello.html @@ -0,0 +1,10 @@ + + + + Hello + + + +

안녕하세요. 손님

+ + \ No newline at end of file From 6c3630ad273e0e20dbd38b19cdaba065aa7e713f Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 01:16:06 +0900 Subject: [PATCH 03/67] =?UTF-8?q?[feat]=20:=20=EC=A0=95=EC=A0=81=EC=BB=A8?= =?UTF-8?q?=ED=85=90=EC=B8=A0,=20MVC=EC=99=80=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EC=97=94=EC=A7=84,=20API=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HelloController.java | 34 +++++++++++++++++++ src/main/resources/static/hello-static.html | 10 ++++++ .../resources/templates/hello-template.html | 5 +++ 3 files changed, 49 insertions(+) create mode 100644 src/main/resources/static/hello-static.html create mode 100644 src/main/resources/templates/hello-template.html diff --git a/src/main/java/com/dku/springstudy/controller/HelloController.java b/src/main/java/com/dku/springstudy/controller/HelloController.java index 9e57536..0a97a2e 100644 --- a/src/main/java/com/dku/springstudy/controller/HelloController.java +++ b/src/main/java/com/dku/springstudy/controller/HelloController.java @@ -3,6 +3,8 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; @Controller public class HelloController { @@ -12,4 +14,36 @@ public String hello(Model model){ model.addAttribute("data", "hello!!"); return "hello"; } + + @GetMapping("hello-mvc") + public String helloMvc(@RequestParam("name") String name, Model model){ + model.addAttribute("name", name); + return "hello-template"; + } + + @GetMapping("hello-spring") + @ResponseBody + public String helloString(@RequestParam("name") String name){ + return "hello"+name; + } + + @GetMapping("hello-api") + @ResponseBody + public Hello helloApi(@RequestParam("name") String name){ + Hello hello = new Hello(); + hello.setName(name); + return hello; + } + + static class Hello{ + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } } diff --git a/src/main/resources/static/hello-static.html b/src/main/resources/static/hello-static.html new file mode 100644 index 0000000..68254b2 --- /dev/null +++ b/src/main/resources/static/hello-static.html @@ -0,0 +1,10 @@ + + + + static content + + + +정적 컨텐츠 입니다. + + \ No newline at end of file diff --git a/src/main/resources/templates/hello-template.html b/src/main/resources/templates/hello-template.html new file mode 100644 index 0000000..66c25d8 --- /dev/null +++ b/src/main/resources/templates/hello-template.html @@ -0,0 +1,5 @@ + + +

hello! empty

+ + \ No newline at end of file From eccec7ba5d6fdf206912adb9e55e895b12d4c57b Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 01:30:31 +0900 Subject: [PATCH 04/67] =?UTF-8?q?[feat]=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=EA=B3=BC=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EB=A6=AC=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC(InMemory=20databa?= =?UTF-8?q?se)=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/domain/Member.java | 23 ++++++++++++ .../repository/MemberRepository.java | 13 +++++++ .../repository/MemoryMemberRepository.java | 35 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/domain/Member.java create mode 100644 src/main/java/com/dku/springstudy/repository/MemberRepository.java create mode 100644 src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java diff --git a/src/main/java/com/dku/springstudy/domain/Member.java b/src/main/java/com/dku/springstudy/domain/Member.java new file mode 100644 index 0000000..affc9a4 --- /dev/null +++ b/src/main/java/com/dku/springstudy/domain/Member.java @@ -0,0 +1,23 @@ +package com.dku.springstudy.domain; + +public class Member { + + private Long id; + private String name; + + 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; + } +} diff --git a/src/main/java/com/dku/springstudy/repository/MemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemberRepository.java new file mode 100644 index 0000000..6de1b4e --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/MemberRepository.java @@ -0,0 +1,13 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; + +import java.util.List; +import java.util.Optional; + +public interface MemberRepository { + Member save(Member member); + Optional findById(Long id); + Optional findByName(String name); + List findAll(); +} diff --git a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java new file mode 100644 index 0000000..1178b0f --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java @@ -0,0 +1,35 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; + +import java.util.*; + +public class MemoryMemberRepository implements MemberRepository{ + private static Map store = new HashMap<>(); + private static Long sequence = 0L; + + @Override + public Member save(Member member) { + member.setId(++sequence); + store.put(member.getId(),member); + return member; + } + + @Override + public Optional findById(Long id) { + return Optional.ofNullable(store.get(id)); + } + + @Override + public Optional findByName(String name) { + return store.values().stream() + .filter(member -> member.getName().equals(name)) + .findAny(); + + } + + @Override + public List findAll() { + return new ArrayList<>(store.values()); + } +} From 5ad163dc0a08e114960836686ed0e145304f2dec Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 01:46:56 +0900 Subject: [PATCH 05/67] =?UTF-8?q?[feat]=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MemoryMemberRepository.java | 4 ++ .../MemoryMemberRepositoryTest.java | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java diff --git a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java index 1178b0f..34208ee 100644 --- a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java +++ b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java @@ -32,4 +32,8 @@ public Optional findByName(String name) { public List findAll() { return new ArrayList<>(store.values()); } + + public void clearStore(){ + store.clear(); + } } diff --git a/src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java b/src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java new file mode 100644 index 0000000..bc0808f --- /dev/null +++ b/src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java @@ -0,0 +1,62 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class MemoryMemberRepositoryTest { + + MemoryMemberRepository repository = new MemoryMemberRepository(); + + @AfterEach + public void afterEach(){ + repository.clearStore(); + } + + @Test + public void save(){ + Member member = new Member(); + member.setName("spring"); + + repository.save(member); + + Member result = repository.findById(member.getId()).get(); + assertThat(member).isEqualTo(result); + } + + @Test + public void findByName(){ + Member member1 = new Member(); + member1.setName("spring1"); + repository.save(member1); + + Member member2 = new Member(); + member2.setName("spring2"); + repository.save(member2); + + Member result = repository.findByName("spring1").get(); + assertThat(result).isEqualTo(member1); + } + + @Test + public void findAll(){ + Member member1 = new Member(); + member1.setName("spring1"); + repository.save(member1); + + Member member2 = new Member(); + member2.setName("spring2"); + repository.save(member2); + + List result = repository.findAll(); + + assertThat(result.size()).isEqualTo(2); + } + +} \ No newline at end of file From c0e5106294ea9d0cb6a15b182ff2672928ac73a7 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 11:05:23 +0900 Subject: [PATCH 06/67] =?UTF-8?q?[feat]=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springstudy/service/MemberService.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/service/MemberService.java diff --git a/src/main/java/com/dku/springstudy/service/MemberService.java b/src/main/java/com/dku/springstudy/service/MemberService.java new file mode 100644 index 0000000..5b6fd3e --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/MemberService.java @@ -0,0 +1,34 @@ +package com.dku.springstudy.service; + +import com.dku.springstudy.domain.Member; +import com.dku.springstudy.repository.MemberRepository; +import com.dku.springstudy.repository.MemoryMemberRepository; + +import javax.swing.text.html.Option; +import java.util.List; +import java.util.Optional; + +public class MemberService { + private final MemberRepository memberRepository = new MemoryMemberRepository(); + + public Long join(Member member) { + validateDuplicateMember(member); // method 로 뽑기 : control + t + memberRepository.save(member); + return member.getId(); + } + + public List findMembers(){ + return memberRepository.findAll(); + } + + public Optional findOne(Long memberId){ + return memberRepository.findById(memberId); + } + + private void validateDuplicateMember(Member member) { + memberRepository.findByName(member.getName()) + .ifPresent(m -> { + throw new IllegalStateException("이미 존재하는 회원입니다."); + }); + } +} From 1a6bd44a9799bd54d05c8035fb4812125ac9b0a3 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 11:34:03 +0900 Subject: [PATCH 07/67] =?UTF-8?q?[feat]=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B5=AC=ED=98=84,=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A3=BC=EC=9E=85=EA=B3=A0=EB=A0=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springstudy/service/MemberService.java | 6 +- .../service/MemberServiceTest.java | 69 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/dku/springstudy/service/MemberServiceTest.java diff --git a/src/main/java/com/dku/springstudy/service/MemberService.java b/src/main/java/com/dku/springstudy/service/MemberService.java index 5b6fd3e..32793d8 100644 --- a/src/main/java/com/dku/springstudy/service/MemberService.java +++ b/src/main/java/com/dku/springstudy/service/MemberService.java @@ -9,7 +9,11 @@ import java.util.Optional; public class MemberService { - private final MemberRepository memberRepository = new MemoryMemberRepository(); + private final MemberRepository memberRepository; + + public MemberService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } public Long join(Member member) { validateDuplicateMember(member); // method 로 뽑기 : control + t diff --git a/src/test/java/com/dku/springstudy/service/MemberServiceTest.java b/src/test/java/com/dku/springstudy/service/MemberServiceTest.java new file mode 100644 index 0000000..8cb41fe --- /dev/null +++ b/src/test/java/com/dku/springstudy/service/MemberServiceTest.java @@ -0,0 +1,69 @@ +package com.dku.springstudy.service; + +import com.dku.springstudy.domain.Member; +import com.dku.springstudy.repository.MemoryMemberRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class MemberServiceTest { + + MemberService memberService; + MemoryMemberRepository memberRepository; + + @BeforeEach + public void beforeEach(){ + memberRepository = new MemoryMemberRepository(); + memberService = new MemberService(memberRepository); + } + + @AfterEach + public void afterEach(){ + memberRepository.clearStore(); + } + + @Test + void 회원가입(){ + //given + Member member = new Member(); + member.setName("spring"); + + //when + Long saveId = memberService.join(member); + + //then + Member findMember = memberService.findOne(saveId).get(); //option+command+v 받을 자료형 만들어줌! 좋은듯 ~ + assertThat(member.getName()).isEqualTo(findMember.getName()); + } + + @Test + public void 중복_회원_예외(){ + //given + Member member1 = new Member(); + member1.setName("spring"); + + Member member2 = new Member(); + member2.setName("spring"); + + //when + memberService.join(member1); + IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2)); + assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); + + /** + try{ + memberService.join(member2); + fail(); + }catch (IllegalStateException e){ + assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); + } + */ + } +} \ No newline at end of file From 1d9eb36a753df5438ddcb590988e44a56d7dd0cb Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 12:14:46 +0900 Subject: [PATCH 08/67] =?UTF-8?q?[feat]=20:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=8A=A4=EC=BA=94=EA=B3=BC=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EA=B4=80=EA=B3=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springstudy/controller/MemberController.java | 16 ++++++++++++++++ .../repository/MemoryMemberRepository.java | 2 ++ .../dku/springstudy/service/MemberService.java | 4 ++++ .../springstudy/service/MemberServiceTest.java | 10 +++++----- 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/controller/MemberController.java diff --git a/src/main/java/com/dku/springstudy/controller/MemberController.java b/src/main/java/com/dku/springstudy/controller/MemberController.java new file mode 100644 index 0000000..8575ddd --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/MemberController.java @@ -0,0 +1,16 @@ +package com.dku.springstudy.controller; + +import com.dku.springstudy.service.MemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Controller +public class MemberController { + + private final MemberService memberService; + + @Autowired + public MemberController(MemberService memberService){ + this.memberService = memberService; + } +} diff --git a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java index 34208ee..08025f7 100644 --- a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java +++ b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java @@ -1,9 +1,11 @@ package com.dku.springstudy.repository; import com.dku.springstudy.domain.Member; +import org.springframework.stereotype.Repository; import java.util.*; +@Repository public class MemoryMemberRepository implements MemberRepository{ private static Map store = new HashMap<>(); private static Long sequence = 0L; diff --git a/src/main/java/com/dku/springstudy/service/MemberService.java b/src/main/java/com/dku/springstudy/service/MemberService.java index 32793d8..0ef2947 100644 --- a/src/main/java/com/dku/springstudy/service/MemberService.java +++ b/src/main/java/com/dku/springstudy/service/MemberService.java @@ -3,14 +3,18 @@ import com.dku.springstudy.domain.Member; import com.dku.springstudy.repository.MemberRepository; import com.dku.springstudy.repository.MemoryMemberRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import javax.swing.text.html.Option; import java.util.List; import java.util.Optional; +@Service public class MemberService { private final MemberRepository memberRepository; + @Autowired public MemberService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } diff --git a/src/test/java/com/dku/springstudy/service/MemberServiceTest.java b/src/test/java/com/dku/springstudy/service/MemberServiceTest.java index 8cb41fe..8194f28 100644 --- a/src/test/java/com/dku/springstudy/service/MemberServiceTest.java +++ b/src/test/java/com/dku/springstudy/service/MemberServiceTest.java @@ -58,12 +58,12 @@ public void afterEach(){ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); /** - try{ + try{ memberService.join(member2); - fail(); - }catch (IllegalStateException e){ - assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); - } + fail(); + }catch (IllegalStateException e){ + assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); + } */ } } \ No newline at end of file From 9917d9843a690ee2c400d06c460f7d0aa03c9195 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 12:25:40 +0900 Subject: [PATCH 09/67] =?UTF-8?q?[feat]=20:=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A1=9C=20=EC=A7=81=EC=A0=91=20=EC=8A=A4?= =?UTF-8?q?=ED=94=84=EB=A7=81=20=EB=B9=88=20=EB=93=B1=EB=A1=9D=ED=95=98?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/SpringConfig.java | 21 +++++++++++++++++++ .../repository/MemoryMemberRepository.java | 1 - .../springstudy/service/MemberService.java | 1 - 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/SpringConfig.java diff --git a/src/main/java/com/dku/springstudy/SpringConfig.java b/src/main/java/com/dku/springstudy/SpringConfig.java new file mode 100644 index 0000000..1b133c4 --- /dev/null +++ b/src/main/java/com/dku/springstudy/SpringConfig.java @@ -0,0 +1,21 @@ +package com.dku.springstudy; + +import com.dku.springstudy.repository.MemberRepository; +import com.dku.springstudy.repository.MemoryMemberRepository; +import com.dku.springstudy.service.MemberService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringConfig { + + @Bean + public MemberService memberService(){ + return new MemberService(memberRepository()); + } + + @Bean + public MemberRepository memberRepository(){ + return new MemoryMemberRepository(); + } +} diff --git a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java index 08025f7..ac3c416 100644 --- a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java +++ b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java @@ -5,7 +5,6 @@ import java.util.*; -@Repository public class MemoryMemberRepository implements MemberRepository{ private static Map store = new HashMap<>(); private static Long sequence = 0L; diff --git a/src/main/java/com/dku/springstudy/service/MemberService.java b/src/main/java/com/dku/springstudy/service/MemberService.java index 0ef2947..d4f7b97 100644 --- a/src/main/java/com/dku/springstudy/service/MemberService.java +++ b/src/main/java/com/dku/springstudy/service/MemberService.java @@ -10,7 +10,6 @@ import java.util.List; import java.util.Optional; -@Service public class MemberService { private final MemberRepository memberRepository; From 79e80dc0fe9c261a824af66b0f50347d99523f67 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 12:46:55 +0900 Subject: [PATCH 10/67] =?UTF-8?q?[feat]=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=9B=B9=EA=B8=B0=EB=8A=A5(=ED=99=88=ED=99=94=EB=A9=B4,=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D,=20=EC=A1=B0=ED=9A=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HomeController.java | 13 +++++++++ .../controller/MemberController.java | 28 +++++++++++++++++++ .../springstudy/controller/MemberForm.java | 13 +++++++++ src/main/resources/templates/home.html | 12 ++++++++ .../templates/members/createMemberForm.html | 13 +++++++++ .../templates/members/memberList.html | 22 +++++++++++++++ 6 files changed, 101 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/controller/HomeController.java create mode 100644 src/main/java/com/dku/springstudy/controller/MemberForm.java create mode 100644 src/main/resources/templates/home.html create mode 100644 src/main/resources/templates/members/createMemberForm.html create mode 100644 src/main/resources/templates/members/memberList.html diff --git a/src/main/java/com/dku/springstudy/controller/HomeController.java b/src/main/java/com/dku/springstudy/controller/HomeController.java new file mode 100644 index 0000000..b6812d7 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/HomeController.java @@ -0,0 +1,13 @@ +package com.dku.springstudy.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HomeController { + + @GetMapping("/") + public String home(){ + return "home"; + } +} diff --git a/src/main/java/com/dku/springstudy/controller/MemberController.java b/src/main/java/com/dku/springstudy/controller/MemberController.java index 8575ddd..b08ce21 100644 --- a/src/main/java/com/dku/springstudy/controller/MemberController.java +++ b/src/main/java/com/dku/springstudy/controller/MemberController.java @@ -1,8 +1,14 @@ package com.dku.springstudy.controller; +import com.dku.springstudy.domain.Member; import com.dku.springstudy.service.MemberService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.List; @Controller public class MemberController { @@ -13,4 +19,26 @@ public class MemberController { public MemberController(MemberService memberService){ this.memberService = memberService; } + + @GetMapping("/members/new") + public String createForm(){ + return "members/createMemberForm"; + } + + @PostMapping("/members/new") + public String create(MemberForm form){ + Member member = new Member(); + member.setName(form.getName()); + + memberService.join(member); + + return "redirect:/"; + } + + @GetMapping("/members") + public String list(Model model){ + List members = memberService.findMembers(); + model.addAttribute("members",members); + return "members/memberList"; + } } diff --git a/src/main/java/com/dku/springstudy/controller/MemberForm.java b/src/main/java/com/dku/springstudy/controller/MemberForm.java new file mode 100644 index 0000000..9ee1cc1 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/MemberForm.java @@ -0,0 +1,13 @@ +package com.dku.springstudy.controller; + +public class MemberForm { + public String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html new file mode 100644 index 0000000..37aae3e --- /dev/null +++ b/src/main/resources/templates/home.html @@ -0,0 +1,12 @@ + + + +
+
+

Hello Spring

회원 기능

+

+ 회원 가입 회원 목록 +

+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/members/createMemberForm.html b/src/main/resources/templates/members/createMemberForm.html new file mode 100644 index 0000000..3d46dd5 --- /dev/null +++ b/src/main/resources/templates/members/createMemberForm.html @@ -0,0 +1,13 @@ + + + +
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/members/memberList.html b/src/main/resources/templates/members/memberList.html new file mode 100644 index 0000000..d1bf8f0 --- /dev/null +++ b/src/main/resources/templates/members/memberList.html @@ -0,0 +1,22 @@ + + + +
+
+ + + + + + + + + + + + +
#이름
+
+
+ + \ No newline at end of file From d39d64305903584c7edf3c23519a880220c319f0 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 16:53:49 +0900 Subject: [PATCH 11/67] =?UTF-8?q?[chore]=20:=20h2,=20jdbc=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ sql/ddl.sql | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 sql/ddl.sql diff --git a/build.gradle b/build.gradle index 3999c33..d6a848d 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-jdbc' + runtimeOnly 'com.h2database:h2' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } diff --git a/sql/ddl.sql b/sql/ddl.sql new file mode 100644 index 0000000..29a13f2 --- /dev/null +++ b/sql/ddl.sql @@ -0,0 +1,7 @@ +drop table if exists member CASCADE; + create table member + ( + id bigint generated by default as identity, + name varchar(255), + primary key (id) +); \ No newline at end of file From dd3825d66bbf8ba982d0ba73140b1a0f80b596c6 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 17:19:18 +0900 Subject: [PATCH 12/67] =?UTF-8?q?[feat]=20:=20jdbc=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/SpringConfig.java | 12 +- .../repository/JdbcMemberRepository.java | 167 ++++++++++++++++++ src/main/resources/application.properties | 4 +- 3 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java diff --git a/src/main/java/com/dku/springstudy/SpringConfig.java b/src/main/java/com/dku/springstudy/SpringConfig.java index 1b133c4..039d634 100644 --- a/src/main/java/com/dku/springstudy/SpringConfig.java +++ b/src/main/java/com/dku/springstudy/SpringConfig.java @@ -1,14 +1,23 @@ package com.dku.springstudy; +import com.dku.springstudy.repository.JdbcMemberRepository; import com.dku.springstudy.repository.MemberRepository; import com.dku.springstudy.repository.MemoryMemberRepository; import com.dku.springstudy.service.MemberService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.sql.DataSource; + @Configuration public class SpringConfig { + private final DataSource dataSource; + + public SpringConfig(DataSource dataSource) { + this.dataSource = dataSource; + } + @Bean public MemberService memberService(){ return new MemberService(memberRepository()); @@ -16,6 +25,7 @@ public MemberService memberService(){ @Bean public MemberRepository memberRepository(){ - return new MemoryMemberRepository(); + //return new MemoryMemberRepository(); + return new JdbcMemberRepository(dataSource); } } diff --git a/src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java b/src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java new file mode 100644 index 0000000..743e356 --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java @@ -0,0 +1,167 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; +import org.springframework.jdbc.datasource.DataSourceUtils; + +import javax.sql.DataSource; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class JdbcMemberRepository implements MemberRepository{ + private final DataSource dataSource; + + public JdbcMemberRepository(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public Member save(Member member) { + String sql = "insert into member(name) values(?)"; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); + + pstmt.setString(1, member.getName()); + + pstmt.executeUpdate(); + rs = pstmt.getGeneratedKeys(); + + if (rs.next()) { + member.setId(rs.getLong(1)); + } else { + throw new SQLException("id 조회 실패"); + } + return member; + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + + @Override + public Optional findById(Long id) { + String sql = "select * from member where id = ?"; + + Connection conn = null; + PreparedStatement pstmt = null; + + ResultSet rs = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setLong(1, id); + + rs = pstmt.executeQuery(); + + if (rs.next()) { + Member member = new Member(); + member.setId(rs.getLong("id")); + member.setName(rs.getString("name")); + return Optional.of(member); + } else { + return Optional.empty(); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + + @Override + public List findAll() { + String sql = "select * from member"; + + Connection conn = null; + PreparedStatement pstmt = null; + + ResultSet rs = null; + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + rs = pstmt.executeQuery(); + + List members = new ArrayList<>(); + while (rs.next()) { + Member member = new Member(); + member.setId(rs.getLong("id")); + member.setName(rs.getString("name")); + members.add(member); + } + return members; + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + + @Override + public Optional findByName(String name) { + String sql = "select * from member where name = ?"; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + conn = getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setString(1, name); + + rs = pstmt.executeQuery(); + + if (rs.next()) { + Member member = new Member(); + member.setId(rs.getLong("id")); + member.setName(rs.getString("name")); + return Optional.of(member); + } + return Optional.empty(); + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + close(conn, pstmt, rs); + } + } + + private Connection getConnection() { + return DataSourceUtils.getConnection(dataSource); + } + + private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { + try { + if (rs != null) { + rs.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + try { + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + try { + if (conn != null) { + close(conn); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void close(Connection conn) throws SQLException { + DataSourceUtils.releaseConnection(conn, dataSource); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..f7b65c4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,3 @@ - +spring.datasource.url=jdbc:h2:tcp://localhost/~/test +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa \ No newline at end of file From ffc1a40f354ba10097b2b60a5237855b0b12e54b Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 17:39:39 +0900 Subject: [PATCH 13/67] =?UTF-8?q?[test]=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=8A=A4=ED=94=84=EB=A7=81=20?= =?UTF-8?q?=ED=86=B5=ED=95=A9=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MemberServiceIntegrationTest.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java diff --git a/src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java b/src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java new file mode 100644 index 0000000..7e3fb0b --- /dev/null +++ b/src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java @@ -0,0 +1,53 @@ +package com.dku.springstudy.service; + +import com.dku.springstudy.domain.Member; +import com.dku.springstudy.repository.MemberRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@Transactional +@SpringBootTest +public class MemberServiceIntegrationTest { + + @Autowired + MemberService memberService; + + @Autowired + MemberRepository memberRepository; + + @Test + public void 회원가입() throws Exception { + + //Given + Member member = new Member(); + member.setName("hello"); + + //When + Long saveId = memberService.join(member); + + //Then + Member findMember = memberRepository.findById(saveId).get(); + assertEquals(member.getName(), findMember.getName()); + } + + @Test + public void 중복_회원_예외() throws Exception { + //Given + Member member1 = new Member(); + member1.setName("spring"); + Member member2 = new Member(); + member2.setName("spring"); + + //When + memberService.join(member1); + IllegalStateException e = assertThrows(IllegalStateException.class,() -> memberService.join(member2));//예외가 발생해야 한다. + + assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); + } +} From b45495f84bf37da86da69702fef8d59b323aa3fc Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 17:54:42 +0900 Subject: [PATCH 14/67] =?UTF-8?q?[feat]=20:=20=EC=8A=A4=ED=94=84=EB=A7=81?= =?UTF-8?q?=20JdbcTemplate=20=ED=9A=8C=EC=9B=90=20=EB=A6=AC=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/SpringConfig.java | 4 +- .../JdbcTemplateMemberRepository.java | 61 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java diff --git a/src/main/java/com/dku/springstudy/SpringConfig.java b/src/main/java/com/dku/springstudy/SpringConfig.java index 039d634..af8b70f 100644 --- a/src/main/java/com/dku/springstudy/SpringConfig.java +++ b/src/main/java/com/dku/springstudy/SpringConfig.java @@ -1,6 +1,7 @@ package com.dku.springstudy; import com.dku.springstudy.repository.JdbcMemberRepository; +import com.dku.springstudy.repository.JdbcTemplateMemberRepository; import com.dku.springstudy.repository.MemberRepository; import com.dku.springstudy.repository.MemoryMemberRepository; import com.dku.springstudy.service.MemberService; @@ -26,6 +27,7 @@ public MemberService memberService(){ @Bean public MemberRepository memberRepository(){ //return new MemoryMemberRepository(); - return new JdbcMemberRepository(dataSource); + //return new JdbcMemberRepository(dataSource); + return new JdbcTemplateMemberRepository(dataSource); } } diff --git a/src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java b/src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java new file mode 100644 index 0000000..ad45c68 --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java @@ -0,0 +1,61 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class JdbcTemplateMemberRepository implements MemberRepository{ + private final JdbcTemplate jdbcTemplate; + + //생성자가 1개일 경우 @Autowired 생략 가능 + public JdbcTemplateMemberRepository(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public Member save(Member member) { + SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate); + jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id"); + + Map parameters = new HashMap<>(); + parameters.put("name", member.getName()); + + Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters)); + member.setId(key.longValue()); + return member; + } + + @Override + public Optional findById(Long id) { + List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id); + return result.stream().findAny(); + } + + @Override + public List findAll() { + return jdbcTemplate.query("select * from member", memberRowMapper()); + } + + @Override + public Optional findByName(String name) { + List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name); + return result.stream().findAny(); + } + + private RowMapper memberRowMapper() { + return (rs, rowNum) -> { + Member member = new Member(); + member.setId(rs.getLong("id")); + member.setName(rs.getString("name")); + return member; + }; + } +} From 0babe65d74c5e598c7d815be167adc2aa8c4ad25 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 18:02:30 +0900 Subject: [PATCH 15/67] =?UTF-8?q?[chore]=20:=20jpa=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++- src/main/resources/application.properties | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d6a848d..c86bb60 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-jdbc' + //implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.h2database:h2' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f7b65c4..d01e763 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,6 @@ spring.datasource.url=jdbc:h2:tcp://localhost/~/test spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.username=sa \ No newline at end of file +spring.datasource.username=sa + +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=none From 562848af36ac127c26ece6e45643199a1af77dcc Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 21:03:40 +0900 Subject: [PATCH 16/67] =?UTF-8?q?[feat]=20:=20jpa=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC,=20=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=EB=A7=A4=ED=95=91,=20=ED=8A=B8=EB=9E=9C=EC=9E=AD=EC=85=98=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/SpringConfig.java | 21 ++++++---- .../com/dku/springstudy/domain/Member.java | 7 ++++ .../repository/JpaMemberRepository.java | 41 +++++++++++++++++++ .../springstudy/service/MemberService.java | 2 + 4 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java diff --git a/src/main/java/com/dku/springstudy/SpringConfig.java b/src/main/java/com/dku/springstudy/SpringConfig.java index af8b70f..d4d1e8f 100644 --- a/src/main/java/com/dku/springstudy/SpringConfig.java +++ b/src/main/java/com/dku/springstudy/SpringConfig.java @@ -1,24 +1,28 @@ package com.dku.springstudy; -import com.dku.springstudy.repository.JdbcMemberRepository; -import com.dku.springstudy.repository.JdbcTemplateMemberRepository; -import com.dku.springstudy.repository.MemberRepository; -import com.dku.springstudy.repository.MemoryMemberRepository; +import com.dku.springstudy.repository.*; import com.dku.springstudy.service.MemberService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.persistence.EntityManager; import javax.sql.DataSource; @Configuration public class SpringConfig { - private final DataSource dataSource; + private EntityManager em; - public SpringConfig(DataSource dataSource) { - this.dataSource = dataSource; + public SpringConfig(EntityManager em) { + this.em = em; } + //private final DataSource dataSource; + + //public SpringConfig(DataSource dataSource) { + //this.dataSource = dataSource; + // } + @Bean public MemberService memberService(){ return new MemberService(memberRepository()); @@ -28,6 +32,7 @@ public MemberService memberService(){ public MemberRepository memberRepository(){ //return new MemoryMemberRepository(); //return new JdbcMemberRepository(dataSource); - return new JdbcTemplateMemberRepository(dataSource); + //return new JdbcTemplateMemberRepository(dataSource); + return new JpaMemberRepository(em); } } diff --git a/src/main/java/com/dku/springstudy/domain/Member.java b/src/main/java/com/dku/springstudy/domain/Member.java index affc9a4..41d5faf 100644 --- a/src/main/java/com/dku/springstudy/domain/Member.java +++ b/src/main/java/com/dku/springstudy/domain/Member.java @@ -1,7 +1,14 @@ package com.dku.springstudy.domain; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity public class Member { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; diff --git a/src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java b/src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java new file mode 100644 index 0000000..623b581 --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java @@ -0,0 +1,41 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; + +import javax.persistence.EntityManager; +import java.util.List; +import java.util.Optional; + +public class JpaMemberRepository implements MemberRepository{ + + private final EntityManager em; + + public JpaMemberRepository(EntityManager em) { + this.em = em; + } + + @Override + public Member save(Member member) { + em.persist(member); + return member; + } + + @Override + public Optional findById(Long id) { + Member member = em.find(Member.class, id); + return Optional.ofNullable(member); + } + + @Override + public Optional findByName(String name) { + List result = em.createQuery("select m from Member m where m.name = :name", Member.class) + .setParameter("name",name) + .getResultList(); + return result.stream().findAny(); + } + + @Override + public List findAll() { + return em.createQuery("select m from Member m",Member.class).getResultList(); + } +} diff --git a/src/main/java/com/dku/springstudy/service/MemberService.java b/src/main/java/com/dku/springstudy/service/MemberService.java index d4f7b97..2a7b54a 100644 --- a/src/main/java/com/dku/springstudy/service/MemberService.java +++ b/src/main/java/com/dku/springstudy/service/MemberService.java @@ -5,11 +5,13 @@ import com.dku.springstudy.repository.MemoryMemberRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.swing.text.html.Option; import java.util.List; import java.util.Optional; +@Transactional public class MemberService { private final MemberRepository memberRepository; From 5339920eaad7759a2f0a2a84ddf625ec35664595 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 21:26:27 +0900 Subject: [PATCH 17/67] [feat] : spring data jpa --- .../com/dku/springstudy/SpringConfig.java | 45 ++++++++++++------- .../SpringDataJpaMemberRepository.java | 14 ++++++ 2 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java diff --git a/src/main/java/com/dku/springstudy/SpringConfig.java b/src/main/java/com/dku/springstudy/SpringConfig.java index d4d1e8f..2f35efb 100644 --- a/src/main/java/com/dku/springstudy/SpringConfig.java +++ b/src/main/java/com/dku/springstudy/SpringConfig.java @@ -2,6 +2,7 @@ import com.dku.springstudy.repository.*; import com.dku.springstudy.service.MemberService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,28 +12,38 @@ @Configuration public class SpringConfig { - private EntityManager em; + private final MemberRepository memberRepository; - public SpringConfig(EntityManager em) { - this.em = em; + @Autowired //생략가능 + public SpringConfig(MemberRepository memberRepository) { + this.memberRepository = memberRepository; } - //private final DataSource dataSource; - - //public SpringConfig(DataSource dataSource) { - //this.dataSource = dataSource; - // } + /** + * private EntityManager em; + *

+ * public SpringConfig(EntityManager em) { + * this.em = em; + * } + *

+ * private final DataSource dataSource; + *

+ * public SpringConfig(DataSource dataSource) { + * this.dataSource = dataSource; + * } + */ @Bean - public MemberService memberService(){ - return new MemberService(memberRepository()); + public MemberService memberService() { + return new MemberService(memberRepository); } - @Bean - public MemberRepository memberRepository(){ - //return new MemoryMemberRepository(); - //return new JdbcMemberRepository(dataSource); - //return new JdbcTemplateMemberRepository(dataSource); - return new JpaMemberRepository(em); - } + /** + @Bean public MemberRepository memberRepository(){ + //return new MemoryMemberRepository(); + //return new JdbcMemberRepository(dataSource); + //return new JdbcTemplateMemberRepository(dataSource); + return new JpaMemberRepository(em); + } + */ } diff --git a/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java b/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java new file mode 100644 index 0000000..dde6f2a --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java @@ -0,0 +1,14 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.domain.Member; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository { + + @Override + Optional findByName(String name); +} From c7887efccb724a662623565912def2efbc6aee84 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 17 Jan 2023 22:21:35 +0900 Subject: [PATCH 18/67] =?UTF-8?q?[feat]=20:=20=EC=9A=94=EC=B2=AD=EB=90=9C?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98=ED=96=89=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EB=BD=91=EA=B8=B0(=EA=B3=B5=ED=86=B5=EA=B4=80?= =?UTF-8?q?=EC=8B=AC=EC=82=AC=ED=95=AD)=20aop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/aop/TimeTraceAop.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/aop/TimeTraceAop.java diff --git a/src/main/java/com/dku/springstudy/aop/TimeTraceAop.java b/src/main/java/com/dku/springstudy/aop/TimeTraceAop.java new file mode 100644 index 0000000..d4481da --- /dev/null +++ b/src/main/java/com/dku/springstudy/aop/TimeTraceAop.java @@ -0,0 +1,27 @@ +package com.dku.springstudy.aop; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +@Component +@Aspect +public class TimeTraceAop { + + @Around("execution(* com.dku.springstudy..*(..))") + public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{ + + long start = System.currentTimeMillis(); + + System.out.println("START: " + joinPoint.toString()); + try{ + return joinPoint.proceed(); // 다음 메서드로 실행 + } finally { + long finish = System.currentTimeMillis(); + long timeMs = finish - start; + + System.out.println("END: " + joinPoint.toString()+ " " + timeMs + "ms"); + } + } +} From 220fc1d82e101c89f09e3275ab50d926ee377687 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Wed, 18 Jan 2023 01:19:42 +0900 Subject: [PATCH 19/67] =?UTF-8?q?[refactor]=20:=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springstudy/repository/SpringDataJpaMemberRepository.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java b/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java index dde6f2a..b930797 100644 --- a/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java +++ b/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java @@ -6,7 +6,6 @@ import java.util.Optional; -@Repository public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository { @Override From f0028c9cc68f50e99ff398d33d024865933b6ace Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Wed, 18 Jan 2023 10:47:39 +0900 Subject: [PATCH 20/67] =?UTF-8?q?[docs]=20:=20README.md=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..46843ea --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +### 이번 주에 학습에 투자한 시간 +- 1월 17일 화요일
+[인프런]   [김영한강사님]  스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 해당강의 다 들었습니다. + +


+ +### 학습 하면서 좋았던 점과 아쉬웠던 점 + +#### 좋았던 점 +- 인터페이스를 활용한 다형성이 만들수 있는 계방 폐쇄의 원칙을 알게 되어 좋았습니다. +- 공통관심사 처리를 하기 위해 aop 를 사용하는 점을 알게 되었습니다. +- 이 강의를 무료로 들을수 있는 점이 좋았습니다 + +#### 아쉬웠던 점 +- 없습니다. + +#### 어려웠던 점 +- 요청과 응답시 데이터의 Content-Type 에 따라 어떤 종류의 HttpMessageConverter 사용되는지 동작원리는 어떻게 되는지 더 깊게 알고 싶어 졌습니다. +- 그냥 사용하기에만 급급했던 자바의 람다기능, stream -> map -> filter -> Collectors.toList() 기능들을 좀 더 알아보아야 할 거 같습니다. +- 테스트 코드에서의 @Transactional 롤백현상이 pk에는 적용되지 않는 점을 어떤 방법이 효율적으로 해결할 수 있을지 고민을 하게 되었습니다. +- 통합테스트가 뭔지 코드를 통해 더 알아보아야 할거 같습니다.(저는 그냥 controller layer 에서 @SpringBootTest 붙히면 끝인줄만 알았습니다) +- jdbc 강의부분 에서는 자바활용 ㅂㄱㅅ 교수님 중간고사가 생각나서 ptsd 가 잠시 왔습니다. 🥲🥲 + +
+ +### 스터디 개선되었으면 하는 점 +- 개선점이라기 보다는 저번에 깃 강의 해주신 것처럼 멘토님들께서 특정 주제에 관하여 이해하기 쉬운 코드로 구글미트에서 짧게 설명해주는 것도 좋을것 같습니다. (2주에 1번 ??) +

+- 예를 들면 자바의 고급문법(람다, stream, 리스트, 제네릭, 자료구조, 등), 지연로딩과 즉시로딩 차이점, jpa n+1문제와 해결법, 등 \ No newline at end of file From a39dd725a8e81a12fe4950789c9a8504c1235eed Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 24 Jan 2023 01:21:34 +0900 Subject: [PATCH 21/67] =?UTF-8?q?[remove]:=202=EC=A3=BC=EC=B0=A8=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=9C=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/SpringConfig.java | 49 ----- .../com/dku/springstudy/aop/TimeTraceAop.java | 27 --- .../controller/HelloController.java | 49 ----- .../controller/HomeController.java | 13 -- .../controller/MemberController.java | 44 ----- .../springstudy/controller/MemberForm.java | 13 -- .../com/dku/springstudy/domain/Member.java | 30 ---- .../repository/JdbcMemberRepository.java | 167 ------------------ .../JdbcTemplateMemberRepository.java | 61 ------- .../repository/JpaMemberRepository.java | 41 ----- .../repository/MemberRepository.java | 13 -- .../repository/MemoryMemberRepository.java | 40 ----- .../SpringDataJpaMemberRepository.java | 13 -- .../springstudy/service/MemberService.java | 43 ----- .../MemoryMemberRepositoryTest.java | 62 ------- .../service/MemberServiceIntegrationTest.java | 53 ------ .../service/MemberServiceTest.java | 69 -------- 17 files changed, 787 deletions(-) delete mode 100644 src/main/java/com/dku/springstudy/SpringConfig.java delete mode 100644 src/main/java/com/dku/springstudy/aop/TimeTraceAop.java delete mode 100644 src/main/java/com/dku/springstudy/controller/HelloController.java delete mode 100644 src/main/java/com/dku/springstudy/controller/HomeController.java delete mode 100644 src/main/java/com/dku/springstudy/controller/MemberController.java delete mode 100644 src/main/java/com/dku/springstudy/controller/MemberForm.java delete mode 100644 src/main/java/com/dku/springstudy/domain/Member.java delete mode 100644 src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java delete mode 100644 src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java delete mode 100644 src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java delete mode 100644 src/main/java/com/dku/springstudy/repository/MemberRepository.java delete mode 100644 src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java delete mode 100644 src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java delete mode 100644 src/main/java/com/dku/springstudy/service/MemberService.java delete mode 100644 src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java delete mode 100644 src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java delete mode 100644 src/test/java/com/dku/springstudy/service/MemberServiceTest.java diff --git a/src/main/java/com/dku/springstudy/SpringConfig.java b/src/main/java/com/dku/springstudy/SpringConfig.java deleted file mode 100644 index 2f35efb..0000000 --- a/src/main/java/com/dku/springstudy/SpringConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dku.springstudy; - -import com.dku.springstudy.repository.*; -import com.dku.springstudy.service.MemberService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManager; -import javax.sql.DataSource; - -@Configuration -public class SpringConfig { - - private final MemberRepository memberRepository; - - @Autowired //생략가능 - public SpringConfig(MemberRepository memberRepository) { - this.memberRepository = memberRepository; - } - - /** - * private EntityManager em; - *

- * public SpringConfig(EntityManager em) { - * this.em = em; - * } - *

- * private final DataSource dataSource; - *

- * public SpringConfig(DataSource dataSource) { - * this.dataSource = dataSource; - * } - */ - - @Bean - public MemberService memberService() { - return new MemberService(memberRepository); - } - - /** - @Bean public MemberRepository memberRepository(){ - //return new MemoryMemberRepository(); - //return new JdbcMemberRepository(dataSource); - //return new JdbcTemplateMemberRepository(dataSource); - return new JpaMemberRepository(em); - } - */ -} diff --git a/src/main/java/com/dku/springstudy/aop/TimeTraceAop.java b/src/main/java/com/dku/springstudy/aop/TimeTraceAop.java deleted file mode 100644 index d4481da..0000000 --- a/src/main/java/com/dku/springstudy/aop/TimeTraceAop.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dku.springstudy.aop; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.stereotype.Component; - -@Component -@Aspect -public class TimeTraceAop { - - @Around("execution(* com.dku.springstudy..*(..))") - public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{ - - long start = System.currentTimeMillis(); - - System.out.println("START: " + joinPoint.toString()); - try{ - return joinPoint.proceed(); // 다음 메서드로 실행 - } finally { - long finish = System.currentTimeMillis(); - long timeMs = finish - start; - - System.out.println("END: " + joinPoint.toString()+ " " + timeMs + "ms"); - } - } -} diff --git a/src/main/java/com/dku/springstudy/controller/HelloController.java b/src/main/java/com/dku/springstudy/controller/HelloController.java deleted file mode 100644 index 0a97a2e..0000000 --- a/src/main/java/com/dku/springstudy/controller/HelloController.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dku.springstudy.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -public class HelloController { - - @GetMapping("hello") - public String hello(Model model){ - model.addAttribute("data", "hello!!"); - return "hello"; - } - - @GetMapping("hello-mvc") - public String helloMvc(@RequestParam("name") String name, Model model){ - model.addAttribute("name", name); - return "hello-template"; - } - - @GetMapping("hello-spring") - @ResponseBody - public String helloString(@RequestParam("name") String name){ - return "hello"+name; - } - - @GetMapping("hello-api") - @ResponseBody - public Hello helloApi(@RequestParam("name") String name){ - Hello hello = new Hello(); - hello.setName(name); - return hello; - } - - static class Hello{ - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } -} diff --git a/src/main/java/com/dku/springstudy/controller/HomeController.java b/src/main/java/com/dku/springstudy/controller/HomeController.java deleted file mode 100644 index b6812d7..0000000 --- a/src/main/java/com/dku/springstudy/controller/HomeController.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dku.springstudy.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class HomeController { - - @GetMapping("/") - public String home(){ - return "home"; - } -} diff --git a/src/main/java/com/dku/springstudy/controller/MemberController.java b/src/main/java/com/dku/springstudy/controller/MemberController.java deleted file mode 100644 index b08ce21..0000000 --- a/src/main/java/com/dku/springstudy/controller/MemberController.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dku.springstudy.controller; - -import com.dku.springstudy.domain.Member; -import com.dku.springstudy.service.MemberService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; - -import java.util.List; - -@Controller -public class MemberController { - - private final MemberService memberService; - - @Autowired - public MemberController(MemberService memberService){ - this.memberService = memberService; - } - - @GetMapping("/members/new") - public String createForm(){ - return "members/createMemberForm"; - } - - @PostMapping("/members/new") - public String create(MemberForm form){ - Member member = new Member(); - member.setName(form.getName()); - - memberService.join(member); - - return "redirect:/"; - } - - @GetMapping("/members") - public String list(Model model){ - List members = memberService.findMembers(); - model.addAttribute("members",members); - return "members/memberList"; - } -} diff --git a/src/main/java/com/dku/springstudy/controller/MemberForm.java b/src/main/java/com/dku/springstudy/controller/MemberForm.java deleted file mode 100644 index 9ee1cc1..0000000 --- a/src/main/java/com/dku/springstudy/controller/MemberForm.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dku.springstudy.controller; - -public class MemberForm { - public String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/src/main/java/com/dku/springstudy/domain/Member.java b/src/main/java/com/dku/springstudy/domain/Member.java deleted file mode 100644 index 41d5faf..0000000 --- a/src/main/java/com/dku/springstudy/domain/Member.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dku.springstudy.domain; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -@Entity -public class Member { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private String name; - - 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; - } -} diff --git a/src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java b/src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java deleted file mode 100644 index 743e356..0000000 --- a/src/main/java/com/dku/springstudy/repository/JdbcMemberRepository.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; -import org.springframework.jdbc.datasource.DataSourceUtils; - -import javax.sql.DataSource; -import java.sql.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -public class JdbcMemberRepository implements MemberRepository{ - private final DataSource dataSource; - - public JdbcMemberRepository(DataSource dataSource) { - this.dataSource = dataSource; - } - - @Override - public Member save(Member member) { - String sql = "insert into member(name) values(?)"; - - Connection conn = null; - PreparedStatement pstmt = null; - ResultSet rs = null; - - try { - conn = getConnection(); - pstmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); - - pstmt.setString(1, member.getName()); - - pstmt.executeUpdate(); - rs = pstmt.getGeneratedKeys(); - - if (rs.next()) { - member.setId(rs.getLong(1)); - } else { - throw new SQLException("id 조회 실패"); - } - return member; - } catch (Exception e) { - throw new IllegalStateException(e); - } finally { - close(conn, pstmt, rs); - } - } - - @Override - public Optional findById(Long id) { - String sql = "select * from member where id = ?"; - - Connection conn = null; - PreparedStatement pstmt = null; - - ResultSet rs = null; - try { - conn = getConnection(); - pstmt = conn.prepareStatement(sql); - pstmt.setLong(1, id); - - rs = pstmt.executeQuery(); - - if (rs.next()) { - Member member = new Member(); - member.setId(rs.getLong("id")); - member.setName(rs.getString("name")); - return Optional.of(member); - } else { - return Optional.empty(); - } - } catch (Exception e) { - throw new IllegalStateException(e); - } finally { - close(conn, pstmt, rs); - } - } - - @Override - public List findAll() { - String sql = "select * from member"; - - Connection conn = null; - PreparedStatement pstmt = null; - - ResultSet rs = null; - try { - conn = getConnection(); - pstmt = conn.prepareStatement(sql); - rs = pstmt.executeQuery(); - - List members = new ArrayList<>(); - while (rs.next()) { - Member member = new Member(); - member.setId(rs.getLong("id")); - member.setName(rs.getString("name")); - members.add(member); - } - return members; - } catch (Exception e) { - throw new IllegalStateException(e); - } finally { - close(conn, pstmt, rs); - } - } - - @Override - public Optional findByName(String name) { - String sql = "select * from member where name = ?"; - - Connection conn = null; - PreparedStatement pstmt = null; - ResultSet rs = null; - - try { - conn = getConnection(); - pstmt = conn.prepareStatement(sql); - pstmt.setString(1, name); - - rs = pstmt.executeQuery(); - - if (rs.next()) { - Member member = new Member(); - member.setId(rs.getLong("id")); - member.setName(rs.getString("name")); - return Optional.of(member); - } - return Optional.empty(); - } catch (Exception e) { - throw new IllegalStateException(e); - } finally { - close(conn, pstmt, rs); - } - } - - private Connection getConnection() { - return DataSourceUtils.getConnection(dataSource); - } - - private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) { - try { - if (rs != null) { - rs.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - try { - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - try { - if (conn != null) { - close(conn); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - - private void close(Connection conn) throws SQLException { - DataSourceUtils.releaseConnection(conn, dataSource); - } -} diff --git a/src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java b/src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java deleted file mode 100644 index ad45c68..0000000 --- a/src/main/java/com/dku/springstudy/repository/JdbcTemplateMemberRepository.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.simple.SimpleJdbcInsert; - -import javax.sql.DataSource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public class JdbcTemplateMemberRepository implements MemberRepository{ - private final JdbcTemplate jdbcTemplate; - - //생성자가 1개일 경우 @Autowired 생략 가능 - public JdbcTemplateMemberRepository(DataSource dataSource) { - jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Override - public Member save(Member member) { - SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate); - jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id"); - - Map parameters = new HashMap<>(); - parameters.put("name", member.getName()); - - Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters)); - member.setId(key.longValue()); - return member; - } - - @Override - public Optional findById(Long id) { - List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id); - return result.stream().findAny(); - } - - @Override - public List findAll() { - return jdbcTemplate.query("select * from member", memberRowMapper()); - } - - @Override - public Optional findByName(String name) { - List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name); - return result.stream().findAny(); - } - - private RowMapper memberRowMapper() { - return (rs, rowNum) -> { - Member member = new Member(); - member.setId(rs.getLong("id")); - member.setName(rs.getString("name")); - return member; - }; - } -} diff --git a/src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java b/src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java deleted file mode 100644 index 623b581..0000000 --- a/src/main/java/com/dku/springstudy/repository/JpaMemberRepository.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; - -import javax.persistence.EntityManager; -import java.util.List; -import java.util.Optional; - -public class JpaMemberRepository implements MemberRepository{ - - private final EntityManager em; - - public JpaMemberRepository(EntityManager em) { - this.em = em; - } - - @Override - public Member save(Member member) { - em.persist(member); - return member; - } - - @Override - public Optional findById(Long id) { - Member member = em.find(Member.class, id); - return Optional.ofNullable(member); - } - - @Override - public Optional findByName(String name) { - List result = em.createQuery("select m from Member m where m.name = :name", Member.class) - .setParameter("name",name) - .getResultList(); - return result.stream().findAny(); - } - - @Override - public List findAll() { - return em.createQuery("select m from Member m",Member.class).getResultList(); - } -} diff --git a/src/main/java/com/dku/springstudy/repository/MemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemberRepository.java deleted file mode 100644 index 6de1b4e..0000000 --- a/src/main/java/com/dku/springstudy/repository/MemberRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; - -import java.util.List; -import java.util.Optional; - -public interface MemberRepository { - Member save(Member member); - Optional findById(Long id); - Optional findByName(String name); - List findAll(); -} diff --git a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java b/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java deleted file mode 100644 index ac3c416..0000000 --- a/src/main/java/com/dku/springstudy/repository/MemoryMemberRepository.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; -import org.springframework.stereotype.Repository; - -import java.util.*; - -public class MemoryMemberRepository implements MemberRepository{ - private static Map store = new HashMap<>(); - private static Long sequence = 0L; - - @Override - public Member save(Member member) { - member.setId(++sequence); - store.put(member.getId(),member); - return member; - } - - @Override - public Optional findById(Long id) { - return Optional.ofNullable(store.get(id)); - } - - @Override - public Optional findByName(String name) { - return store.values().stream() - .filter(member -> member.getName().equals(name)) - .findAny(); - - } - - @Override - public List findAll() { - return new ArrayList<>(store.values()); - } - - public void clearStore(){ - store.clear(); - } -} diff --git a/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java b/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java deleted file mode 100644 index b930797..0000000 --- a/src/main/java/com/dku/springstudy/repository/SpringDataJpaMemberRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository { - - @Override - Optional findByName(String name); -} diff --git a/src/main/java/com/dku/springstudy/service/MemberService.java b/src/main/java/com/dku/springstudy/service/MemberService.java deleted file mode 100644 index 2a7b54a..0000000 --- a/src/main/java/com/dku/springstudy/service/MemberService.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dku.springstudy.service; - -import com.dku.springstudy.domain.Member; -import com.dku.springstudy.repository.MemberRepository; -import com.dku.springstudy.repository.MemoryMemberRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.swing.text.html.Option; -import java.util.List; -import java.util.Optional; - -@Transactional -public class MemberService { - private final MemberRepository memberRepository; - - @Autowired - public MemberService(MemberRepository memberRepository) { - this.memberRepository = memberRepository; - } - - public Long join(Member member) { - validateDuplicateMember(member); // method 로 뽑기 : control + t - memberRepository.save(member); - return member.getId(); - } - - public List findMembers(){ - return memberRepository.findAll(); - } - - public Optional findOne(Long memberId){ - return memberRepository.findById(memberId); - } - - private void validateDuplicateMember(Member member) { - memberRepository.findByName(member.getName()) - .ifPresent(m -> { - throw new IllegalStateException("이미 존재하는 회원입니다."); - }); - } -} diff --git a/src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java b/src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java deleted file mode 100644 index bc0808f..0000000 --- a/src/test/java/com/dku/springstudy/repository/MemoryMemberRepositoryTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.dku.springstudy.repository; - -import com.dku.springstudy.domain.Member; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; - -class MemoryMemberRepositoryTest { - - MemoryMemberRepository repository = new MemoryMemberRepository(); - - @AfterEach - public void afterEach(){ - repository.clearStore(); - } - - @Test - public void save(){ - Member member = new Member(); - member.setName("spring"); - - repository.save(member); - - Member result = repository.findById(member.getId()).get(); - assertThat(member).isEqualTo(result); - } - - @Test - public void findByName(){ - Member member1 = new Member(); - member1.setName("spring1"); - repository.save(member1); - - Member member2 = new Member(); - member2.setName("spring2"); - repository.save(member2); - - Member result = repository.findByName("spring1").get(); - assertThat(result).isEqualTo(member1); - } - - @Test - public void findAll(){ - Member member1 = new Member(); - member1.setName("spring1"); - repository.save(member1); - - Member member2 = new Member(); - member2.setName("spring2"); - repository.save(member2); - - List result = repository.findAll(); - - assertThat(result.size()).isEqualTo(2); - } - -} \ No newline at end of file diff --git a/src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java b/src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java deleted file mode 100644 index 7e3fb0b..0000000 --- a/src/test/java/com/dku/springstudy/service/MemberServiceIntegrationTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dku.springstudy.service; - -import com.dku.springstudy.domain.Member; -import com.dku.springstudy.repository.MemberRepository; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -@Transactional -@SpringBootTest -public class MemberServiceIntegrationTest { - - @Autowired - MemberService memberService; - - @Autowired - MemberRepository memberRepository; - - @Test - public void 회원가입() throws Exception { - - //Given - Member member = new Member(); - member.setName("hello"); - - //When - Long saveId = memberService.join(member); - - //Then - Member findMember = memberRepository.findById(saveId).get(); - assertEquals(member.getName(), findMember.getName()); - } - - @Test - public void 중복_회원_예외() throws Exception { - //Given - Member member1 = new Member(); - member1.setName("spring"); - Member member2 = new Member(); - member2.setName("spring"); - - //When - memberService.join(member1); - IllegalStateException e = assertThrows(IllegalStateException.class,() -> memberService.join(member2));//예외가 발생해야 한다. - - assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); - } -} diff --git a/src/test/java/com/dku/springstudy/service/MemberServiceTest.java b/src/test/java/com/dku/springstudy/service/MemberServiceTest.java deleted file mode 100644 index 8194f28..0000000 --- a/src/test/java/com/dku/springstudy/service/MemberServiceTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.dku.springstudy.service; - -import com.dku.springstudy.domain.Member; -import com.dku.springstudy.repository.MemoryMemberRepository; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Optional; - -import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; - -class MemberServiceTest { - - MemberService memberService; - MemoryMemberRepository memberRepository; - - @BeforeEach - public void beforeEach(){ - memberRepository = new MemoryMemberRepository(); - memberService = new MemberService(memberRepository); - } - - @AfterEach - public void afterEach(){ - memberRepository.clearStore(); - } - - @Test - void 회원가입(){ - //given - Member member = new Member(); - member.setName("spring"); - - //when - Long saveId = memberService.join(member); - - //then - Member findMember = memberService.findOne(saveId).get(); //option+command+v 받을 자료형 만들어줌! 좋은듯 ~ - assertThat(member.getName()).isEqualTo(findMember.getName()); - } - - @Test - public void 중복_회원_예외(){ - //given - Member member1 = new Member(); - member1.setName("spring"); - - Member member2 = new Member(); - member2.setName("spring"); - - //when - memberService.join(member1); - IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2)); - assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); - - /** - try{ - memberService.join(member2); - fail(); - }catch (IllegalStateException e){ - assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); - } - */ - } -} \ No newline at end of file From faf82a91f52a110b3165f28c46cc7f6a3db086f7 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 24 Jan 2023 01:33:27 +0900 Subject: [PATCH 22/67] =?UTF-8?q?[remove]:=202=EC=A3=BC=EC=B0=A8=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=9C=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=82=AD=EC=A0=9C(=ED=83=80=EC=9E=84=EB=A6=AC?= =?UTF-8?q?=ED=94=84=20=ED=8C=8C=EC=9D=BC=EB=93=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/static/hello-static.html | 10 --------- src/main/resources/static/index.html | 11 ---------- .../resources/templates/hello-template.html | 5 ----- src/main/resources/templates/hello.html | 10 --------- src/main/resources/templates/home.html | 12 ---------- .../templates/members/createMemberForm.html | 13 ----------- .../templates/members/memberList.html | 22 ------------------- 7 files changed, 83 deletions(-) delete mode 100644 src/main/resources/static/hello-static.html delete mode 100644 src/main/resources/static/index.html delete mode 100644 src/main/resources/templates/hello-template.html delete mode 100644 src/main/resources/templates/hello.html delete mode 100644 src/main/resources/templates/home.html delete mode 100644 src/main/resources/templates/members/createMemberForm.html delete mode 100644 src/main/resources/templates/members/memberList.html diff --git a/src/main/resources/static/hello-static.html b/src/main/resources/static/hello-static.html deleted file mode 100644 index 68254b2..0000000 --- a/src/main/resources/static/hello-static.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - static content - - - -정적 컨텐츠 입니다. - - \ No newline at end of file diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html deleted file mode 100644 index fb27317..0000000 --- a/src/main/resources/static/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Hello - - - -Hello -hello - - diff --git a/src/main/resources/templates/hello-template.html b/src/main/resources/templates/hello-template.html deleted file mode 100644 index 66c25d8..0000000 --- a/src/main/resources/templates/hello-template.html +++ /dev/null @@ -1,5 +0,0 @@ - - -

hello! empty

- - \ No newline at end of file diff --git a/src/main/resources/templates/hello.html b/src/main/resources/templates/hello.html deleted file mode 100644 index 81f8f1c..0000000 --- a/src/main/resources/templates/hello.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Hello - - - -

안녕하세요. 손님

- - \ No newline at end of file diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html deleted file mode 100644 index 37aae3e..0000000 --- a/src/main/resources/templates/home.html +++ /dev/null @@ -1,12 +0,0 @@ - - - -
-
-

Hello Spring

회원 기능

-

- 회원 가입 회원 목록 -

-
- - \ No newline at end of file diff --git a/src/main/resources/templates/members/createMemberForm.html b/src/main/resources/templates/members/createMemberForm.html deleted file mode 100644 index 3d46dd5..0000000 --- a/src/main/resources/templates/members/createMemberForm.html +++ /dev/null @@ -1,13 +0,0 @@ - - - -
-
-
- -
-
-
- - \ No newline at end of file diff --git a/src/main/resources/templates/members/memberList.html b/src/main/resources/templates/members/memberList.html deleted file mode 100644 index d1bf8f0..0000000 --- a/src/main/resources/templates/members/memberList.html +++ /dev/null @@ -1,22 +0,0 @@ - - - -
-
- - - - - - - - - - - - -
#이름
-
-
- - \ No newline at end of file From d80bcb7a9e811faf21435aea0ea26b74471b354d Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 24 Jan 2023 01:39:48 +0900 Subject: [PATCH 23/67] =?UTF-8?q?[chore]:=20=EC=8A=A4=ED=94=84=EB=A7=81=20?= =?UTF-8?q?=EC=8B=9C=ED=81=90=EB=A6=AC=ED=8B=B0,=20JWT=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++-- sql/ddl.sql | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 sql/ddl.sql diff --git a/build.gradle b/build.gradle index c86bb60..91f16d5 100644 --- a/build.gradle +++ b/build.gradle @@ -11,9 +11,9 @@ repositories { mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1' + implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' - //implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.h2database:h2' testImplementation('org.springframework.boot:spring-boot-starter-test') { diff --git a/sql/ddl.sql b/sql/ddl.sql deleted file mode 100644 index 29a13f2..0000000 --- a/sql/ddl.sql +++ /dev/null @@ -1,7 +0,0 @@ -drop table if exists member CASCADE; - create table member - ( - id bigint generated by default as identity, - name varchar(255), - primary key (id) -); \ No newline at end of file From 28c472e4e17fda726004caed2140116d96079409 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 24 Jan 2023 01:51:38 +0900 Subject: [PATCH 24/67] =?UTF-8?q?[feat]:=20swagger=20api=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=9E=90=EB=8F=99=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ .../config/swagger/SwaggerConfig.java | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java diff --git a/build.gradle b/build.gradle index 91f16d5..4267ff4 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' + implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' runtimeOnly 'com.h2database:h2' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' diff --git a/src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java b/src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java new file mode 100644 index 0000000..431f9a6 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java @@ -0,0 +1,34 @@ +package com.dku.springstudy.config.swagger; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + private ApiInfo commonInfo(){ + return new ApiInfoBuilder() + .title("CarrotMarket API") + .version("1.0") + .build(); + } + + @Bean + public Docket allApi(){ + return new Docket(DocumentationType.SWAGGER_2) + .groupName("USER") + .useDefaultResponseMessages(false) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + .apiInfo(commonInfo()); + } +} From ed5167ab9f32fea448a4e2146b75b73c8f0706a4 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 24 Jan 2023 11:49:19 +0900 Subject: [PATCH 25/67] =?UTF-8?q?[feat]:=20=EC=9D=91=EB=8B=B5=20DTO=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=ED=86=B5=EC=9D=BC=EC=8B=9C=ED=82=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ src/main/java/com/dku/springstudy/dto/ResponseDTO.java | 9 +++++++++ 2 files changed, 12 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/dto/ResponseDTO.java diff --git a/build.gradle b/build.gradle index 4267ff4..8615b20 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' diff --git a/src/main/java/com/dku/springstudy/dto/ResponseDTO.java b/src/main/java/com/dku/springstudy/dto/ResponseDTO.java new file mode 100644 index 0000000..7180d6d --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/ResponseDTO.java @@ -0,0 +1,9 @@ +package com.dku.springstudy.dto; + +import lombok.Data; + +@Data +public class ResponseDTO { + private int status; + private T data; +} From 1e2618d62549bddecc5223645628aee2bb4f69e9 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 01:09:56 +0900 Subject: [PATCH 26/67] =?UTF-8?q?[docs]:README.md=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 46843ea..3e47a59 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,18 @@ -### 이번 주에 학습에 투자한 시간 -- 1월 17일 화요일
-[인프런]   [김영한강사님]  스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 해당강의 다 들었습니다. +> 당근마켓 backend server project -
- -### 학습 하면서 좋았던 점과 아쉬웠던 점 - -#### 좋았던 점 -- 인터페이스를 활용한 다형성이 만들수 있는 계방 폐쇄의 원칙을 알게 되어 좋았습니다. -- 공통관심사 처리를 하기 위해 aop 를 사용하는 점을 알게 되었습니다. -- 이 강의를 무료로 들을수 있는 점이 좋았습니다 - -#### 아쉬웠던 점 -- 없습니다. - -#### 어려웠던 점 -- 요청과 응답시 데이터의 Content-Type 에 따라 어떤 종류의 HttpMessageConverter 사용되는지 동작원리는 어떻게 되는지 더 깊게 알고 싶어 졌습니다. -- 그냥 사용하기에만 급급했던 자바의 람다기능, stream -> map -> filter -> Collectors.toList() 기능들을 좀 더 알아보아야 할 거 같습니다. -- 테스트 코드에서의 @Transactional 롤백현상이 pk에는 적용되지 않는 점을 어떤 방법이 효율적으로 해결할 수 있을지 고민을 하게 되었습니다. -- 통합테스트가 뭔지 코드를 통해 더 알아보아야 할거 같습니다.(저는 그냥 controller layer 에서 @SpringBootTest 붙히면 끝인줄만 알았습니다) -- jdbc 강의부분 에서는 자바활용 ㅂㄱㅅ 교수님 중간고사가 생각나서 ptsd 가 잠시 왔습니다. 🥲🥲 +

+ + + + +


-### 스터디 개선되었으면 하는 점 -- 개선점이라기 보다는 저번에 깃 강의 해주신 것처럼 멘토님들께서 특정 주제에 관하여 이해하기 쉬운 코드로 구글미트에서 짧게 설명해주는 것도 좋을것 같습니다. (2주에 1번 ??) -

-- 예를 들면 자바의 고급문법(람다, stream, 리스트, 제네릭, 자료구조, 등), 지연로딩과 즉시로딩 차이점, jpa n+1문제와 해결법, 등 \ No newline at end of file +### 1주차 + +> 1. 회원가입 및 로그인 기능 +- 요구사항 분석 +- 도메인 모델 및 테이블 설계 고민 +- JWT 구현 및 테스트 코드 작성 +- 이메일 인증하기 \ No newline at end of file From bff7014bc74818cf77c69c5776bd1e6f8688d3de Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 01:26:29 +0900 Subject: [PATCH 27/67] =?UTF-8?q?[feat]:=20User=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dku/springstudy/model/Role.java | 5 +++ .../java/com/dku/springstudy/model/User.java | 39 +++++++++++++++++++ .../repository/UserRepository.java | 7 ++++ 3 files changed, 51 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/model/Role.java create mode 100644 src/main/java/com/dku/springstudy/model/User.java create mode 100644 src/main/java/com/dku/springstudy/repository/UserRepository.java diff --git a/src/main/java/com/dku/springstudy/model/Role.java b/src/main/java/com/dku/springstudy/model/Role.java new file mode 100644 index 0000000..d5da4fb --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/Role.java @@ -0,0 +1,5 @@ +package com.dku.springstudy.model; + +public enum Role { + USER,ADMIN +} diff --git a/src/main/java/com/dku/springstudy/model/User.java b/src/main/java/com/dku/springstudy/model/User.java new file mode 100644 index 0000000..c5733a5 --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/User.java @@ -0,0 +1,39 @@ +package com.dku.springstudy.model; + +import lombok.*; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; + +@NoArgsConstructor @AllArgsConstructor +@Getter @Builder +@Table(name = "Users", uniqueConstraints = {@UniqueConstraint(columnNames = "email")}) +@Entity +public class User { + + @Id + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid",strategy = "uuid") + @Column(name = "user_id") + private String id; + + @Column(nullable = false) + private String username; + + @Column(nullable = false) + private String email; + @Column(nullable = false) + private String password; + + private String profileImageUrl; + + @Setter + private String token; + + @Column(nullable = false) + private String phoneNumber; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private Role role; +} diff --git a/src/main/java/com/dku/springstudy/repository/UserRepository.java b/src/main/java/com/dku/springstudy/repository/UserRepository.java new file mode 100644 index 0000000..d72bc5c --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/UserRepository.java @@ -0,0 +1,7 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { +} From 44bacdfe1fa35e6a3aa12f38079244aa4fa185c3 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 01:36:46 +0900 Subject: [PATCH 28/67] =?UTF-8?q?[feat]:=20yml=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20X?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c2065bc..649136d 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ out/ ### VS Code ### .vscode/ + +*.yml From 38b107acc7a9200d8d95b41d6d01421b1039b08a Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 11:36:33 +0900 Subject: [PATCH 29/67] =?UTF-8?q?[chore]:=20=EB=A1=AC=EB=B3=B5=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=8A=A4=ED=94=84=EB=A7=81=20=EB=B6=80?= =?UTF-8?q?=ED=8A=B8=20=EB=B2=84=EC=A0=84=20=EC=98=AC=EB=A6=AC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8615b20..4ce6c51 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,22 @@ plugins { - id 'org.springframework.boot' version '2.3.1.RELEASE' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'org.springframework.boot' version '2.7.4' + id 'io.spring.dependency-management' version '1.0.14.RELEASE' id 'java' } group = 'com.dku' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + repositories { mavenCentral() } + dependencies { implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1' implementation 'org.springframework.boot:spring-boot-starter-security' @@ -25,6 +32,7 @@ dependencies { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } } + test { useJUnitPlatform() } \ No newline at end of file From fde437c8a54cf35baeee36ba58ec230746c699b0 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 11:39:19 +0900 Subject: [PATCH 30/67] =?UTF-8?q?[feat]:=20SecurityFilterChain=20=EC=88=98?= =?UTF-8?q?=EB=8F=99=EC=9C=BC=EB=A1=9C=20=EC=8A=A4=ED=94=84=EB=A7=81=20?= =?UTF-8?q?=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/config/AppConfig.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/AppConfig.java diff --git a/src/main/java/com/dku/springstudy/config/AppConfig.java b/src/main/java/com/dku/springstudy/config/AppConfig.java new file mode 100644 index 0000000..ab46605 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/AppConfig.java @@ -0,0 +1,41 @@ +package com.dku.springstudy.config; + +import com.dku.springstudy.config.security.jwt.JwtAuthenticationFilter; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.filter.CorsFilter; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class AppConfig { + + private final JwtAuthenticationFilter jwtAuthenticationFilter; + + @Bean + public PasswordEncoder passwordEncoder(){ + return PasswordEncoderFactories.createDelegatingPasswordEncoder(); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ + return http + .csrf().disable() + .httpBasic().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .authorizeRequests() + .antMatchers("/account/sign-up", "/account/login").permitAll() + .anyRequest().authenticated() + .and() + .addFilterAfter(jwtAuthenticationFilter, CorsFilter.class) + .build(); + } +} From 1441cfc37ac016706e2ed06bf96f7e535929f1ec Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 11:42:34 +0900 Subject: [PATCH 31/67] =?UTF-8?q?[feat]:=20User=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?&=20UserRepository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/dku/springstudy/model/User.java | 3 +++ .../java/com/dku/springstudy/repository/UserRepository.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/com/dku/springstudy/model/User.java b/src/main/java/com/dku/springstudy/model/User.java index c5733a5..ccb41c7 100644 --- a/src/main/java/com/dku/springstudy/model/User.java +++ b/src/main/java/com/dku/springstudy/model/User.java @@ -22,6 +22,7 @@ public class User { @Column(nullable = false) private String email; + @Column(nullable = false) private String password; @@ -33,6 +34,8 @@ public class User { @Column(nullable = false) private String phoneNumber; + private String nickname; + @Column(nullable = false) @Enumerated(EnumType.STRING) private Role role; diff --git a/src/main/java/com/dku/springstudy/repository/UserRepository.java b/src/main/java/com/dku/springstudy/repository/UserRepository.java index d72bc5c..7568e38 100644 --- a/src/main/java/com/dku/springstudy/repository/UserRepository.java +++ b/src/main/java/com/dku/springstudy/repository/UserRepository.java @@ -3,5 +3,9 @@ import com.dku.springstudy.model.User; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface UserRepository extends JpaRepository { + boolean existsByEmail(String email); + Optional findByEmail(String email); } From 2b726dad4ff8c76abcda0495d8b88768b1864e0d Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 11:43:59 +0900 Subject: [PATCH 32/67] =?UTF-8?q?[feat]:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dku/springstudy/dto/LoginRequest.java | 9 +++++++++ .../java/com/dku/springstudy/dto/SignUpRequest.java | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/dto/LoginRequest.java create mode 100644 src/main/java/com/dku/springstudy/dto/SignUpRequest.java diff --git a/src/main/java/com/dku/springstudy/dto/LoginRequest.java b/src/main/java/com/dku/springstudy/dto/LoginRequest.java new file mode 100644 index 0000000..21b9b21 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/LoginRequest.java @@ -0,0 +1,9 @@ +package com.dku.springstudy.dto; + +import lombok.Data; + +@Data +public class LoginRequest { + private String email; + private String password; +} diff --git a/src/main/java/com/dku/springstudy/dto/SignUpRequest.java b/src/main/java/com/dku/springstudy/dto/SignUpRequest.java new file mode 100644 index 0000000..5dce2d2 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/SignUpRequest.java @@ -0,0 +1,12 @@ +package com.dku.springstudy.dto; + +import lombok.Data; + +@Data +public class SignUpRequest { + private final String email; + private final String password; + private final String username; + private final String phoneNumber; + private final String nickname; +} From 01bc87bdfeb1c59a5d7aa519fdcfc70937b64749 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 13:42:46 +0900 Subject: [PATCH 33/67] =?UTF-8?q?[feat]:=20JWT=20payload=20=EC=97=90=20?= =?UTF-8?q?=EB=93=A4=EC=96=B4=EA=B0=88=20subject=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/security/jwt/Subject.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/security/jwt/Subject.java diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java b/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java new file mode 100644 index 0000000..771adc2 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java @@ -0,0 +1,26 @@ +package com.dku.springstudy.config.security.jwt; + +import lombok.Getter; + +@Getter +public class Subject { + private final String userId; + private final String email; + private final String nickname; + private final String type; + + public Subject(String userId, String email, String nickname, String type) { + this.userId = userId; + this.email = email; + this.nickname = nickname; + this.type = type; + } + + public static Subject atk(String userId, String email, String nickname) { + return new Subject(userId, email, nickname, "ATK"); + } + + public static Subject rtk(String userId, String email, String nickname) { + return new Subject(userId, email, nickname, "RTK"); + } +} From a4704e37399522c5681e8ec6770b02a18bbe8868 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 14:29:55 +0900 Subject: [PATCH 34/67] =?UTF-8?q?[feat]:=20JWT=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20JWT=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/jwt/JwtAuthenticationFilter.java | 97 +++++++++++++++++++ .../config/security/jwt/JwtProvider.java | 77 +++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java create mode 100644 src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java new file mode 100644 index 0000000..beac40f --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java @@ -0,0 +1,97 @@ +package com.dku.springstudy.config.security.jwt; + +import com.dku.springstudy.dto.ResponseDTO; +import com.dku.springstudy.exception.Message; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Date; + +@Slf4j +@Component +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtProvider jwtProvider; + private final ObjectMapper objectMapper; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + try { + // 요청에서 토큰 가져오기 + String token = parseBearerToken(request); + log.info("Filter is running..."); + + if (token != null && !token.equalsIgnoreCase("null")) { + // userId 가져오기. 위조된 경우 예외 처리된다. + Claims claims = jwtProvider.validateAndGetUserId(token); + String userId = claims.getSubject(); + String userRole = (String) claims.get("ROLE"); + Date expiration = claims.getExpiration(); + log.info("Authenticated user ID : " + userId); + log.info("Authenticated expiration : " + expiration); + + AbstractAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userId, // 인증된 사용자의 정보. 문자열이 아니어도 아무것이나 넣을 수 있다. 보통 UserDetails 오브젝트를 넣음 + null, + AuthorityUtils.createAuthorityList(userRole)); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); + securityContext.setAuthentication(authentication); + SecurityContextHolder.setContext(securityContext); + } + + filterChain.doFilter(request, response); + } catch (ExpiredJwtException e) { + logger.error("Could not set user authentication in security context {}", e); + jwtExceptionHandler(response, Message.JWT_TOKEN_EXPIRED); + } catch (UnsupportedJwtException e) { + logger.error("Could not set user authentication in security context {}", e); + jwtExceptionHandler(response, Message.JWT_UNSUPPORTED); + } catch (MalformedJwtException e) { + logger.error("Could not set user authentication in security context {}", e); + jwtExceptionHandler(response, Message.JWT_MALFORMED); + } catch (SignatureException e) { + logger.error("Could not set user authentication in security context {}", e); + jwtExceptionHandler(response, Message.JWT_SIGNATURE); + } catch (IllegalArgumentException e) { + logger.error("Could not set user authentication in security context {}", e); + jwtExceptionHandler(response, Message.JWT_ILLEGAL_ARGUMENT); + } + } + private String parseBearerToken(HttpServletRequest request){ + String bearerToken = request.getHeader("Authorization"); + + if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")){ + return bearerToken.substring(7); + } + return null; + } + + private void jwtExceptionHandler(HttpServletResponse response, String message) throws IOException{ + ResponseDTO dto = new ResponseDTO<>(HttpStatus.UNAUTHORIZED.value(), message); + response.setStatus(HttpStatus.FORBIDDEN.value()); + response.setCharacterEncoding("UTF-8"); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + + objectMapper.writeValue(response.getWriter(), dto); + } +} \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java new file mode 100644 index 0000000..5ef4658 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java @@ -0,0 +1,77 @@ +package com.dku.springstudy.config.security.jwt; + +import com.dku.springstudy.dto.TokenResponse; +import com.dku.springstudy.dto.UserResponse; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Base64; +import java.util.Date; + +@Component +@RequiredArgsConstructor +public class JwtProvider { + + private final ObjectMapper objectMapper; + + @Value("${jwt.key}") + private String key; + + @Value("${jwt.live.atk}") + private Long atkLive; + + @PostConstruct + protected void init() { + key = Base64.getEncoder().encodeToString(key.getBytes()); + } + + public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonProcessingException { + Subject atkSubject = Subject.atk( + userResponse.getUserId(), + userResponse.getEmail(), + userResponse.getNickname()); + String atk = createToken(atkSubject, atkLive); + return new TokenResponse(atk, null); + } + + private String createToken(Subject subject, Long tokenLive) throws JsonProcessingException { + String subjectStr = objectMapper.writeValueAsString(subject); + Claims claims = Jwts.claims().setSubject(subjectStr); + Date date = new Date(); + return Jwts.builder() + .setSubject(claims.getId()) + .setClaims(claims) + .setIssuedAt(date) + .setExpiration(new Date(date.getTime() + tokenLive)) + .signWith(SignatureAlgorithm.HS256, key) + .compact(); + } + + + public Claims validateAndGetUserId(String token){ + Claims claims = Jwts.parser() + .setSigningKey(key) + .parseClaimsJws(token) + .getBody(); + return claims; // 사용자의 아이디 리턴 + } + + public boolean isValidToken(String token) { + try { + Jwts.parser() + .setSigningKey(key) + .parseClaimsJws(token) + .getBody(); + return true; + }catch (Exception e){ + return false; + } + } +} From 2d556a0b00a58f70c7d10b7e15a1170d2d8b27a8 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 14:38:21 +0900 Subject: [PATCH 35/67] =?UTF-8?q?[feat]:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20&=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserController.java | 35 +++++++++++ .../com/dku/springstudy/dto/ResponseDTO.java | 6 ++ .../dku/springstudy/dto/TokenResponse.java | 9 +++ .../com/dku/springstudy/dto/UserResponse.java | 26 ++++++++ .../java/com/dku/springstudy/model/User.java | 1 + .../dku/springstudy/service/UserService.java | 62 +++++++++++++++++++ 6 files changed, 139 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/controller/UserController.java create mode 100644 src/main/java/com/dku/springstudy/dto/TokenResponse.java create mode 100644 src/main/java/com/dku/springstudy/dto/UserResponse.java create mode 100644 src/main/java/com/dku/springstudy/service/UserService.java diff --git a/src/main/java/com/dku/springstudy/controller/UserController.java b/src/main/java/com/dku/springstudy/controller/UserController.java new file mode 100644 index 0000000..7868438 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/UserController.java @@ -0,0 +1,35 @@ +package com.dku.springstudy.controller; + +import com.dku.springstudy.config.security.jwt.JwtProvider; +import com.dku.springstudy.dto.*; +import com.dku.springstudy.service.UserService; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class UserController { + + private final UserService userService; + private final JwtProvider jwtProvider; + + @PostMapping("/account/sign-up") + @ApiOperation(value = "회원가입", notes = "SignUpRequest 객체로 받아 유저를 등록합니다.") + public ResponseDTO signUp(@RequestBody SignUpRequest signUpRequest){ + userService.signUp(signUpRequest); + return new ResponseDTO<>(HttpStatus.OK.value(), signUpRequest); + } + + @PostMapping("/account/login") + @ApiOperation(value = "로그인", notes = "LoginRequest 객체로 email과 password를 받아 로그인을 진행하고, access token과 refresh token을 리턴합니다.") + public ResponseDTO login(@RequestBody LoginRequest loginRequest) throws JsonProcessingException { + UserResponse userResponse = userService.login(loginRequest); + TokenResponse tokens = jwtProvider.createTokensByLogin(userResponse); + return new ResponseDTO<>(HttpStatus.OK.value(), tokens); + } +} diff --git a/src/main/java/com/dku/springstudy/dto/ResponseDTO.java b/src/main/java/com/dku/springstudy/dto/ResponseDTO.java index 7180d6d..90856eb 100644 --- a/src/main/java/com/dku/springstudy/dto/ResponseDTO.java +++ b/src/main/java/com/dku/springstudy/dto/ResponseDTO.java @@ -1,8 +1,14 @@ package com.dku.springstudy.dto; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class ResponseDTO { private int status; private T data; diff --git a/src/main/java/com/dku/springstudy/dto/TokenResponse.java b/src/main/java/com/dku/springstudy/dto/TokenResponse.java new file mode 100644 index 0000000..28a12a6 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/TokenResponse.java @@ -0,0 +1,9 @@ +package com.dku.springstudy.dto; + +import lombok.Data; + +@Data +public class TokenResponse { + private final String atk; + private final String rtk; +} diff --git a/src/main/java/com/dku/springstudy/dto/UserResponse.java b/src/main/java/com/dku/springstudy/dto/UserResponse.java new file mode 100644 index 0000000..f749dc0 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/UserResponse.java @@ -0,0 +1,26 @@ +package com.dku.springstudy.dto; + +import com.dku.springstudy.model.User; +import lombok.Data; + +@Data +public class UserResponse { + private final String userId; + + private final String email; + + private final String nickname; + + public UserResponse(String userId, String email, String nickname) { + this.userId = userId; + this.email = email; + this.nickname = nickname; + } + + public static UserResponse of(User user) { + return new UserResponse( + user.getId(), + user.getEmail(), + user.getNickname()); + } +} diff --git a/src/main/java/com/dku/springstudy/model/User.java b/src/main/java/com/dku/springstudy/model/User.java index ccb41c7..0d04fd6 100644 --- a/src/main/java/com/dku/springstudy/model/User.java +++ b/src/main/java/com/dku/springstudy/model/User.java @@ -29,6 +29,7 @@ public class User { private String profileImageUrl; @Setter + @Lob private String token; @Column(nullable = false) diff --git a/src/main/java/com/dku/springstudy/service/UserService.java b/src/main/java/com/dku/springstudy/service/UserService.java new file mode 100644 index 0000000..50ace99 --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/UserService.java @@ -0,0 +1,62 @@ +package com.dku.springstudy.service; + +import com.dku.springstudy.config.security.jwt.JwtProvider; +import com.dku.springstudy.dto.LoginRequest; +import com.dku.springstudy.dto.SignUpRequest; +import com.dku.springstudy.dto.UserResponse; +import com.dku.springstudy.model.Role; +import com.dku.springstudy.model.User; +import com.dku.springstudy.repository.UserRepository; +import com.fasterxml.jackson.core.JsonProcessingException; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class UserService { + + private final JwtProvider jwtProvider; + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + + @Transactional + public void signUp(SignUpRequest signUpRequest){ + + boolean isExist = userRepository.existsByEmail(signUpRequest.getEmail()); + if(isExist){ + throw new IllegalStateException("이미 존재하는 이메일입니다."); + } + + String encodedPassword = passwordEncoder.encode(signUpRequest.getPassword()); + User user = User.builder() + .username(signUpRequest.getUsername()) + .email(signUpRequest.getEmail()) + .password(encodedPassword) + .phoneNumber(signUpRequest.getPhoneNumber()) + .nickname(signUpRequest.getNickname()) + .role(Role.USER) + .build(); + + userRepository.save(user); + } + + @Transactional + public UserResponse login(LoginRequest loginRequest) throws JsonProcessingException { + User user = userRepository.findByEmail(loginRequest.getEmail()) + .orElseThrow(() -> new IllegalStateException("아이디 혹은 비밀번호를 확인하세요.")); + + boolean matches = passwordEncoder.matches(loginRequest.getPassword(), user.getPassword()); + if(!matches){ + throw new IllegalStateException("아이디 혹은 비밀번호를 확인하세요."); + } + + UserResponse userResponse = UserResponse.of(user); + final String token = jwtProvider.createTokensByLogin(userResponse).getAtk(); + user.setToken(token); + + return UserResponse.of(user); + } +} From ae966eba8c688b57712dc42e7efd4c63642c836b Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 16:34:59 +0900 Subject: [PATCH 36/67] =?UTF-8?q?[fix]:=20JWT=20=ED=86=A0=ED=81=B0=20claim?= =?UTF-8?q?=20=EC=97=90=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/jwt/JwtAuthenticationFilter.java | 6 ++---- .../config/security/jwt/JwtProvider.java | 6 ++++-- .../springstudy/config/security/jwt/Subject.java | 14 +++++++++----- .../java/com/dku/springstudy/dto/UserResponse.java | 8 ++++++-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java index beac40f..9a1d027 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java @@ -41,10 +41,9 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse log.info("Filter is running..."); if (token != null && !token.equalsIgnoreCase("null")) { - // userId 가져오기. 위조된 경우 예외 처리된다. Claims claims = jwtProvider.validateAndGetUserId(token); - String userId = claims.getSubject(); - String userRole = (String) claims.get("ROLE"); + String userId = (String) claims.get("userId"); + String userRole = (String) claims.get("role"); Date expiration = claims.getExpiration(); log.info("Authenticated user ID : " + userId); log.info("Authenticated expiration : " + expiration); @@ -58,7 +57,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse securityContext.setAuthentication(authentication); SecurityContextHolder.setContext(securityContext); } - filterChain.doFilter(request, response); } catch (ExpiredJwtException e) { logger.error("Could not set user authentication in security context {}", e); diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java index 5ef4658..dc116b7 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java @@ -36,7 +36,8 @@ public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonP Subject atkSubject = Subject.atk( userResponse.getUserId(), userResponse.getEmail(), - userResponse.getNickname()); + userResponse.getNickname(), + userResponse.getRole()); String atk = createToken(atkSubject, atkLive); return new TokenResponse(atk, null); } @@ -47,7 +48,8 @@ private String createToken(Subject subject, Long tokenLive) throws JsonProcessin Date date = new Date(); return Jwts.builder() .setSubject(claims.getId()) - .setClaims(claims) + .claim("userId", subject.getUserId()) + .claim("role",subject.getRole().name()) .setIssuedAt(date) .setExpiration(new Date(date.getTime() + tokenLive)) .signWith(SignatureAlgorithm.HS256, key) diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java b/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java index 771adc2..c42c3c7 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/Subject.java @@ -1,5 +1,6 @@ package com.dku.springstudy.config.security.jwt; +import com.dku.springstudy.model.Role; import lombok.Getter; @Getter @@ -9,18 +10,21 @@ public class Subject { private final String nickname; private final String type; - public Subject(String userId, String email, String nickname, String type) { + private final Role role; + + public Subject(String userId, String email, String nickname, String type, Role role) { this.userId = userId; this.email = email; this.nickname = nickname; this.type = type; + this.role = role; } - public static Subject atk(String userId, String email, String nickname) { - return new Subject(userId, email, nickname, "ATK"); + public static Subject atk(String userId, String email, String nickname, Role role) { + return new Subject(userId, email, nickname, "ATK", Role.USER); } - public static Subject rtk(String userId, String email, String nickname) { - return new Subject(userId, email, nickname, "RTK"); + public static Subject rtk(String userId, String email, String nickname, Role role) { + return new Subject(userId, email, nickname, "RTK", Role.USER); } } diff --git a/src/main/java/com/dku/springstudy/dto/UserResponse.java b/src/main/java/com/dku/springstudy/dto/UserResponse.java index f749dc0..4dcdea6 100644 --- a/src/main/java/com/dku/springstudy/dto/UserResponse.java +++ b/src/main/java/com/dku/springstudy/dto/UserResponse.java @@ -1,5 +1,6 @@ package com.dku.springstudy.dto; +import com.dku.springstudy.model.Role; import com.dku.springstudy.model.User; import lombok.Data; @@ -10,17 +11,20 @@ public class UserResponse { private final String email; private final String nickname; + private Role role = Role.USER; - public UserResponse(String userId, String email, String nickname) { + public UserResponse(String userId, String email, String nickname, Role role) { this.userId = userId; this.email = email; this.nickname = nickname; + this.role = role; } public static UserResponse of(User user) { return new UserResponse( user.getId(), user.getEmail(), - user.getNickname()); + user.getNickname(), + user.getRole()); } } From 6a01a361ddbd5b8726a6a335bba984527f526cd3 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 16:37:02 +0900 Subject: [PATCH 37/67] =?UTF-8?q?[feat]:=20=ED=95=84=ED=84=B0=EB=8B=A8?= =?UTF-8?q?=EA=B3=84=EC=97=90=EC=84=9C=EC=9D=98=20JWT=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/config/AppConfig.java | 6 +++ .../jwt/CustomAuthenticationEntryPoint.java | 42 +++++++++++++++++++ .../springstudy/exception/JwtTokenError.java | 12 ++++++ .../dku/springstudy/exception/Message.java | 9 ++++ 4 files changed, 69 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java create mode 100644 src/main/java/com/dku/springstudy/exception/JwtTokenError.java create mode 100644 src/main/java/com/dku/springstudy/exception/Message.java diff --git a/src/main/java/com/dku/springstudy/config/AppConfig.java b/src/main/java/com/dku/springstudy/config/AppConfig.java index ab46605..24089d2 100644 --- a/src/main/java/com/dku/springstudy/config/AppConfig.java +++ b/src/main/java/com/dku/springstudy/config/AppConfig.java @@ -1,5 +1,6 @@ package com.dku.springstudy.config; +import com.dku.springstudy.config.security.jwt.CustomAuthenticationEntryPoint; import com.dku.springstudy.config.security.jwt.JwtAuthenticationFilter; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; @@ -18,6 +19,7 @@ public class AppConfig { private final JwtAuthenticationFilter jwtAuthenticationFilter; + private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; @Bean public PasswordEncoder passwordEncoder(){ @@ -29,9 +31,13 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ return http .csrf().disable() .httpBasic().disable() + .exceptionHandling() + .authenticationEntryPoint(customAuthenticationEntryPoint) + .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() + .antMatchers("/i/**").access("hasRole('ADMIN')") .antMatchers("/account/sign-up", "/account/login").permitAll() .anyRequest().authenticated() .and() diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java b/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java new file mode 100644 index 0000000..b94c433 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java @@ -0,0 +1,42 @@ +package com.dku.springstudy.config.security.jwt; + +import com.dku.springstudy.exception.JwtTokenError; +import com.dku.springstudy.exception.Message; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Getter +@Component +public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { + + private final ObjectMapper objectMapper; + + public CustomAuthenticationEntryPoint(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException { + String exceptionMessage = (String) request.getAttribute("exception"); + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + JwtTokenError jwtTokenError = new JwtTokenError(exceptionMessage, HttpStatus.UNAUTHORIZED); + String res = this.convertObjectToJson(jwtTokenError); + response.getWriter().print(res); + } + + private String convertObjectToJson(Object object) throws JsonProcessingException { + return object == null ? null : objectMapper.writeValueAsString(object); + } +} diff --git a/src/main/java/com/dku/springstudy/exception/JwtTokenError.java b/src/main/java/com/dku/springstudy/exception/JwtTokenError.java new file mode 100644 index 0000000..aab80d9 --- /dev/null +++ b/src/main/java/com/dku/springstudy/exception/JwtTokenError.java @@ -0,0 +1,12 @@ +package com.dku.springstudy.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public class JwtTokenError { + private String message; + private HttpStatus status; +} diff --git a/src/main/java/com/dku/springstudy/exception/Message.java b/src/main/java/com/dku/springstudy/exception/Message.java new file mode 100644 index 0000000..2fbed7d --- /dev/null +++ b/src/main/java/com/dku/springstudy/exception/Message.java @@ -0,0 +1,9 @@ +package com.dku.springstudy.exception; + +public class Message { + public static final String JWT_TOKEN_EXPIRED = "JWT 토큰이 만료되었습니다."; + public static final String JWT_UNSUPPORTED = "지원하지 않는 JWT 토큰입니다."; + public static final String JWT_MALFORMED = "올바른 JWT 토큰의 형태가 아닙니다."; + public static final String JWT_SIGNATURE = "올바른 SIGNATURE가 아닙니다."; + public static final String JWT_ILLEGAL_ARGUMENT = "잘못된 정보를 넣었습니다."; +} \ No newline at end of file From 1f81df551f962cf4bbcbcb0a016201312790b70d Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 17:48:05 +0900 Subject: [PATCH 38/67] =?UTF-8?q?[chore]:=20SMPT=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EC=9D=98=EC=A1=B4=EC=84=B1=20?= =?UTF-8?q?=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 4ce6c51..df2fdb6 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' + implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.1' developmentOnly 'org.springframework.boot:spring-boot-devtools' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' From 3fd9d898213aa011d04684e3c5fa40c10f0d1ca9 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 21:41:19 +0900 Subject: [PATCH 39/67] =?UTF-8?q?[feat]:=20SMPT=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dku/springstudy/config/MailConfig.java | 43 +++++++++ .../controller/MailController.java | 25 ++++++ .../java/com/dku/springstudy/dto/MailDTO.java | 8 ++ .../dku/springstudy/service/MailService.java | 15 ++++ .../springstudy/service/MailServiceImpl.java | 89 +++++++++++++++++++ 5 files changed, 180 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/MailConfig.java create mode 100644 src/main/java/com/dku/springstudy/controller/MailController.java create mode 100644 src/main/java/com/dku/springstudy/dto/MailDTO.java create mode 100644 src/main/java/com/dku/springstudy/service/MailService.java create mode 100644 src/main/java/com/dku/springstudy/service/MailServiceImpl.java diff --git a/src/main/java/com/dku/springstudy/config/MailConfig.java b/src/main/java/com/dku/springstudy/config/MailConfig.java new file mode 100644 index 0000000..71a8e28 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/MailConfig.java @@ -0,0 +1,43 @@ +package com.dku.springstudy.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; + +@Configuration +public class MailConfig{ + @Value("${mail.host}") + private String host; + + @Value("${mail.id}") + private String id; + + @Value("${mail.password}") + private String password; + + @Bean + public JavaMailSender javaMailService() { + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + javaMailSender.setHost(host); + javaMailSender.setUsername(id); + javaMailSender.setPassword(password); + javaMailSender.setPort(465); + javaMailSender.setJavaMailProperties(getMailProperties()); + return javaMailSender; + } + + private Properties getMailProperties() { + Properties properties = new Properties(); + properties.setProperty("mail.transport.protocol", "smtp"); + properties.setProperty("mail.smtp.auth", "true"); + properties.setProperty("mail.smtp.starttls.enable", "true"); + properties.setProperty("mail.debug", "true"); + properties.setProperty("mail.smtp.ssl.trust","smtp.naver.com"); + properties.setProperty("mail.smtp.ssl.enable","true"); + return properties; + } +} diff --git a/src/main/java/com/dku/springstudy/controller/MailController.java b/src/main/java/com/dku/springstudy/controller/MailController.java new file mode 100644 index 0000000..e3b59e1 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/MailController.java @@ -0,0 +1,25 @@ +package com.dku.springstudy.controller; + +import com.dku.springstudy.service.MailServiceImpl; +import com.dku.springstudy.dto.MailDTO; +import com.dku.springstudy.dto.ResponseDTO; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@RestController +@RequiredArgsConstructor +public class MailController { + private final MailServiceImpl mailService; + @PostMapping("/account/mailCheck") + @ApiOperation(value = "이메일 인증", notes = "이메일 인증을 진행합니다.") + public ResponseDTO mailConfirm(@RequestBody MailDTO mailDTO) throws Exception { + String email = mailDTO.getEmail(); + String code = mailService.sendSimpleMessage(email); + log.info("인증코드 : "+code); + return new ResponseDTO<>(HttpStatus.OK.value(), code); + } +} diff --git a/src/main/java/com/dku/springstudy/dto/MailDTO.java b/src/main/java/com/dku/springstudy/dto/MailDTO.java new file mode 100644 index 0000000..5c94f97 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/MailDTO.java @@ -0,0 +1,8 @@ +package com.dku.springstudy.dto; + +import lombok.Data; + +@Data +public class MailDTO { + private String email; +} diff --git a/src/main/java/com/dku/springstudy/service/MailService.java b/src/main/java/com/dku/springstudy/service/MailService.java new file mode 100644 index 0000000..17e8fac --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/MailService.java @@ -0,0 +1,15 @@ +package com.dku.springstudy.service; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.UnsupportedEncodingException; + +public interface MailService { + MimeMessage createMessage(String to) throws MessagingException, UnsupportedEncodingException; + + // 랜덤 인증 코드 전송 + String createKey(); + + // 메일 발송 + String sendSimpleMessage(String to) throws Exception; +} diff --git a/src/main/java/com/dku/springstudy/service/MailServiceImpl.java b/src/main/java/com/dku/springstudy/service/MailServiceImpl.java new file mode 100644 index 0000000..1dc9d90 --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/MailServiceImpl.java @@ -0,0 +1,89 @@ +package com.dku.springstudy.service; + +import java.io.UnsupportedEncodingException; +import java.util.Random; + +import javax.mail.MessagingException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMessage.RecipientType; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.MailException; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class MailServiceImpl implements MailService { + private final JavaMailSender mailSender; + + @Value("${mail.email}") + private String email; + + @Value("${mail.name}") + private String name; + + private String confirmNumber; // 인증번호 + + // 메일 내용 작성 + @Override + public MimeMessage createMessage(String receiver) throws MessagingException, UnsupportedEncodingException { + + MimeMessage message = mailSender.createMimeMessage(); + message.addRecipients(RecipientType.TO, receiver); //받는사람 + message.setSubject("당근마켓 회원가입 이메일 인증"); + + String msgg = ""; + msgg += "
"; + msgg += "

안녕하세요

"; + msgg += "

당근 마켓 서지현입니다.

"; + msgg += "
"; + msgg += "

아래 코드를 회원가입 창으로 돌아가 입력해주세요

"; + msgg += "
"; + msgg += "
"; + msgg += "

"; + msgg += "

회원가입 인증 코드입니다.

"; + msgg += "
"; + msgg += "CODE : "; + msgg += confirmNumber + "

"; + msgg += "
"; + message.setText(msgg, "utf-8", "html"); + message.setFrom(new InternetAddress(email,name));// 보내는 사람 + return message; + } + @Override + public String createKey() { + StringBuffer key = new StringBuffer(); + Random random = new Random(); + + for (int i = 0; i < 8; i++) { + int index = random.nextInt(3); + switch (index) { + case 0: + key.append((char) ((int) (random.nextInt(26)) + 97)); //소문자 + break; + case 1: + key.append((char) ((int) (random.nextInt(26)) + 65)); //대문자 + break; + case 2: + key.append((random.nextInt(10))); //숫자 + break; + } + } + return key.toString(); + } + @Override + public String sendSimpleMessage(String receiver) throws Exception { + confirmNumber = createKey(); + + MimeMessage message = createMessage(receiver); // 메일 발송 + try { + mailSender.send(message); + } catch (MailException es) { + throw new IllegalArgumentException(); + } + return confirmNumber; + } +} \ No newline at end of file From 57c31437433b23496db6c73304288dc4588bfd5f Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 21:48:28 +0900 Subject: [PATCH 40/67] =?UTF-8?q?[rename]:=20=ED=8C=8C=EC=9D=BC=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/config/{ => security}/AppConfig.java | 4 ++-- .../config/{swagger => security}/SwaggerConfig.java | 3 +-- .../config/security/jwt/CustomAuthenticationEntryPoint.java | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) rename src/main/java/com/dku/springstudy/config/{ => security}/AppConfig.java (94%) rename src/main/java/com/dku/springstudy/config/{swagger => security}/SwaggerConfig.java (96%) diff --git a/src/main/java/com/dku/springstudy/config/AppConfig.java b/src/main/java/com/dku/springstudy/config/security/AppConfig.java similarity index 94% rename from src/main/java/com/dku/springstudy/config/AppConfig.java rename to src/main/java/com/dku/springstudy/config/security/AppConfig.java index 24089d2..fb67415 100644 --- a/src/main/java/com/dku/springstudy/config/AppConfig.java +++ b/src/main/java/com/dku/springstudy/config/security/AppConfig.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.config; +package com.dku.springstudy.config.security; import com.dku.springstudy.config.security.jwt.CustomAuthenticationEntryPoint; import com.dku.springstudy.config.security.jwt.JwtAuthenticationFilter; @@ -38,7 +38,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ .and() .authorizeRequests() .antMatchers("/i/**").access("hasRole('ADMIN')") - .antMatchers("/account/sign-up", "/account/login").permitAll() + .antMatchers("/account/**").permitAll() .anyRequest().authenticated() .and() .addFilterAfter(jwtAuthenticationFilter, CorsFilter.class) diff --git a/src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java b/src/main/java/com/dku/springstudy/config/security/SwaggerConfig.java similarity index 96% rename from src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java rename to src/main/java/com/dku/springstudy/config/security/SwaggerConfig.java index 431f9a6..afc8de1 100644 --- a/src/main/java/com/dku/springstudy/config/swagger/SwaggerConfig.java +++ b/src/main/java/com/dku/springstudy/config/security/SwaggerConfig.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.config.swagger; +package com.dku.springstudy.config.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -19,7 +19,6 @@ private ApiInfo commonInfo(){ .version("1.0") .build(); } - @Bean public Docket allApi(){ return new Docket(DocumentationType.SWAGGER_2) diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java b/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java index b94c433..63b7cbd 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/CustomAuthenticationEntryPoint.java @@ -1,7 +1,6 @@ package com.dku.springstudy.config.security.jwt; import com.dku.springstudy.exception.JwtTokenError; -import com.dku.springstudy.exception.Message; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Getter; From e36257d1b5972dbbacadf5a0530b51dd47512cbe Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 27 Jan 2023 22:08:05 +0900 Subject: [PATCH 41/67] =?UTF-8?q?[add]:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EA=B8=B0=EB=B3=B8=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/dku/springstudy/service/UserService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/dku/springstudy/service/UserService.java b/src/main/java/com/dku/springstudy/service/UserService.java index 50ace99..5b13fbf 100644 --- a/src/main/java/com/dku/springstudy/service/UserService.java +++ b/src/main/java/com/dku/springstudy/service/UserService.java @@ -36,6 +36,7 @@ public void signUp(SignUpRequest signUpRequest){ .email(signUpRequest.getEmail()) .password(encodedPassword) .phoneNumber(signUpRequest.getPhoneNumber()) + .profileImageUrl("https://user-images.githubusercontent.com/79920930/215020145-7d548f6e-a45e-4041-913c-24a16081a07a.jpg") .nickname(signUpRequest.getNickname()) .role(Role.USER) .build(); From f5be1b095587a7d3588e9e91114f4cf0dda17146 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Sat, 28 Jan 2023 01:31:45 +0900 Subject: [PATCH 42/67] =?UTF-8?q?[chore]:=20redis=20=EB=A9=94=EB=AA=A8?= =?UTF-8?q?=EB=A6=AC=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index df2fdb6..9ee407e 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ dependencies { implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.1' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' developmentOnly 'org.springframework.boot:spring-boot-devtools' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' From 32498869831d27d41f0ebd6467deeea4b1d96c66 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Sat, 28 Jan 2023 13:31:00 +0900 Subject: [PATCH 43/67] =?UTF-8?q?[chore]:=20redis=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=8A=A4=ED=94=84=EB=A7=81=20=EB=B9=88=20?= =?UTF-8?q?=EC=88=98=EB=8F=99=EC=84=A4=EC=A0=95=20&=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20CRUD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/security/RedisConfig.java | 36 +++++++++++++++++++ .../springstudy/config/security/RedisDao.java | 31 ++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/security/RedisConfig.java create mode 100644 src/main/java/com/dku/springstudy/config/security/RedisDao.java diff --git a/src/main/java/com/dku/springstudy/config/security/RedisConfig.java b/src/main/java/com/dku/springstudy/config/security/RedisConfig.java new file mode 100644 index 0000000..56685d1 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/RedisConfig.java @@ -0,0 +1,36 @@ +package com.dku.springstudy.config.security; + + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableRedisRepositories +public class RedisConfig { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private int port; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(host, port); + } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + return redisTemplate; + } +} \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/config/security/RedisDao.java b/src/main/java/com/dku/springstudy/config/security/RedisDao.java new file mode 100644 index 0000000..ec88786 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/RedisDao.java @@ -0,0 +1,31 @@ +package com.dku.springstudy.config.security; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +@Component +public class RedisDao { + + private final RedisTemplate redisTemplate; + + public RedisDao(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + public void setValues(String key, String data, Duration duration) { + ValueOperations values = redisTemplate.opsForValue(); + values.set(key, data, duration); + } + + public String getValues(String key) { + ValueOperations values = redisTemplate.opsForValue(); + return values.get(key); + } + + public void deleteValues(String key) { + redisTemplate.delete(key); + } +} \ No newline at end of file From 6851e06e80ce4e7688d169878cca5806d32592fd Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Sat, 28 Jan 2023 13:32:03 +0900 Subject: [PATCH 44/67] =?UTF-8?q?[feat]:=20access=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9E=AC=EB=B0=9C=EA=B8=89=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/jwt/JwtAuthenticationFilter.java | 5 +++ .../config/security/jwt/JwtProvider.java | 37 +++++++++++++++++-- .../controller/UserController.java | 16 ++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java index 9a1d027..87b0a38 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtAuthenticationFilter.java @@ -42,6 +42,11 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse if (token != null && !token.equalsIgnoreCase("null")) { Claims claims = jwtProvider.validateAndGetUserId(token); + String requestURI = request.getRequestURI(); + System.out.println(claims); + if (claims.get("type").equals("RTK") && !requestURI.equals("/account/reissue")) { + throw new JwtException("토큰을 확인하세요."); + } String userId = (String) claims.get("userId"); String userRole = (String) claims.get("role"); Date expiration = claims.getExpiration(); diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java index dc116b7..553bee7 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java @@ -1,5 +1,6 @@ package com.dku.springstudy.config.security.jwt; +import com.dku.springstudy.config.security.RedisDao; import com.dku.springstudy.dto.TokenResponse; import com.dku.springstudy.dto.UserResponse; import com.fasterxml.jackson.core.JsonProcessingException; @@ -12,13 +13,15 @@ import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; +import java.time.Duration; import java.util.Base64; import java.util.Date; +import java.util.Objects; @Component @RequiredArgsConstructor public class JwtProvider { - + private final RedisDao redisDao; private final ObjectMapper objectMapper; @Value("${jwt.key}") @@ -27,12 +30,17 @@ public class JwtProvider { @Value("${jwt.live.atk}") private Long atkLive; + @Value("${jwt.live.rtk}") + private Long rtkLive; + @PostConstruct protected void init() { key = Base64.getEncoder().encodeToString(key.getBytes()); } - public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonProcessingException { + public TokenResponse reissueAtk(UserResponse userResponse) throws JsonProcessingException { + String rtkInRedis = redisDao.getValues(userResponse.getEmail()); + if (Objects.isNull(rtkInRedis)) throw new IllegalStateException("인증 정보가 만료되었습니다."); Subject atkSubject = Subject.atk( userResponse.getUserId(), userResponse.getEmail(), @@ -41,28 +49,51 @@ public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonP String atk = createToken(atkSubject, atkLive); return new TokenResponse(atk, null); } + public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonProcessingException { + Subject atkSubject = Subject.atk( + userResponse.getUserId(), + userResponse.getEmail(), + userResponse.getNickname(), + userResponse.getRole()); + Subject rtkSubject = Subject.rtk( + userResponse.getUserId(), + userResponse.getEmail(), + userResponse.getNickname(), + userResponse.getRole()); + String atk = createToken(atkSubject, atkLive); + String rtk = createToken(rtkSubject, rtkLive); + redisDao.setValues(userResponse.getEmail(), rtk, Duration.ofMillis(rtkLive)); + return new TokenResponse(atk, rtk); + } private String createToken(Subject subject, Long tokenLive) throws JsonProcessingException { String subjectStr = objectMapper.writeValueAsString(subject); Claims claims = Jwts.claims().setSubject(subjectStr); Date date = new Date(); + System.out.println(subject.getType()); return Jwts.builder() .setSubject(claims.getId()) .claim("userId", subject.getUserId()) + .claim("email",subject.getEmail()) .claim("role",subject.getRole().name()) + .claim("type",subject.getType()) .setIssuedAt(date) .setExpiration(new Date(date.getTime() + tokenLive)) .signWith(SignatureAlgorithm.HS256, key) .compact(); } + public Subject getSubject(String atk) throws JsonProcessingException { + String subjectStr = Jwts.parser().setSigningKey(key).parseClaimsJws(atk).getBody().getSubject(); + return objectMapper.readValue(subjectStr, Subject.class); + } public Claims validateAndGetUserId(String token){ Claims claims = Jwts.parser() .setSigningKey(key) .parseClaimsJws(token) .getBody(); - return claims; // 사용자의 아이디 리턴 + return claims; } public boolean isValidToken(String token) { diff --git a/src/main/java/com/dku/springstudy/controller/UserController.java b/src/main/java/com/dku/springstudy/controller/UserController.java index 7868438..6684b6c 100644 --- a/src/main/java/com/dku/springstudy/controller/UserController.java +++ b/src/main/java/com/dku/springstudy/controller/UserController.java @@ -2,19 +2,27 @@ import com.dku.springstudy.config.security.jwt.JwtProvider; import com.dku.springstudy.dto.*; +import com.dku.springstudy.model.User; +import com.dku.springstudy.repository.UserRepository; import com.dku.springstudy.service.UserService; import com.fasterxml.jackson.core.JsonProcessingException; import io.swagger.annotations.ApiOperation; +import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.util.Optional; + @RestController @RequiredArgsConstructor public class UserController { + private final UserRepository userRepository; private final UserService userService; private final JwtProvider jwtProvider; @@ -32,4 +40,12 @@ public ResponseDTO login(@RequestBody LoginRequest loginRequest) throws JsonP TokenResponse tokens = jwtProvider.createTokensByLogin(userResponse); return new ResponseDTO<>(HttpStatus.OK.value(), tokens); } + + @GetMapping("/account/reissue") + @ApiOperation(value = "access토큰 재발급", notes = "access 토큰이 만료된 경우 refresh 토큰을 이용하여 access 토큰을 갱신합니다.") + public TokenResponse reissue(@AuthenticationPrincipal String userId) throws JsonProcessingException { + User user = userRepository.findById(userId).orElseThrow(()->new IllegalStateException("오류 : 유저없음")); + UserResponse userResponse = UserResponse.of(user); + return jwtProvider.reissueAtk(userResponse); + } } From e78f1320f4cc084a832f32451aecc69724b2f7e1 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Sat, 28 Jan 2023 13:43:07 +0900 Subject: [PATCH 45/67] =?UTF-8?q?[docs]:=20README.md=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e47a59..5d2c974 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,13 @@ - 요구사항 분석 - 도메인 모델 및 테이블 설계 고민 - JWT 구현 및 테스트 코드 작성 -- 이메일 인증하기 \ No newline at end of file +- 이메일 인증하기 + +
+
+ +## 개발 기록 + +- 회원가입 & 로그인 API 구현 ```commit``` : [2d556a0](https://github.com/ji-hyeon97/Spring-JPA-study/commit/2d556a0b00a58f70c7d10b7e15a1170d2d8b27a8) +- SMPT 이메일 인증 API 구현 ```commit``` : [3fd9d89](https://github.com/ji-hyeon97/Spring-JPA-study/commit/3fd9d898213aa011d04684e3c5fa40c10f0d1ca9) +- access 토큰 재발급 API 구현 ```commit``` : [6851e06](https://github.com/ji-hyeon97/Spring-JPA-study/commit/6851e06e80ce4e7688d169878cca5806d32592fd) \ No newline at end of file From c0631095ba16eb6105d74044ff646301338881fc Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Sun, 29 Jan 2023 22:37:59 +0900 Subject: [PATCH 46/67] =?UTF-8?q?[refactor]:=20access=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=20=EC=9E=AC=EB=B0=9C=EA=B8=89=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dku/springstudy/controller/UserController.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dku/springstudy/controller/UserController.java b/src/main/java/com/dku/springstudy/controller/UserController.java index 6684b6c..eaa4701 100644 --- a/src/main/java/com/dku/springstudy/controller/UserController.java +++ b/src/main/java/com/dku/springstudy/controller/UserController.java @@ -6,6 +6,7 @@ import com.dku.springstudy.repository.UserRepository; import com.dku.springstudy.service.UserService; import com.fasterxml.jackson.core.JsonProcessingException; +import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -43,9 +44,10 @@ public ResponseDTO login(@RequestBody LoginRequest loginRequest) throws JsonP @GetMapping("/account/reissue") @ApiOperation(value = "access토큰 재발급", notes = "access 토큰이 만료된 경우 refresh 토큰을 이용하여 access 토큰을 갱신합니다.") - public TokenResponse reissue(@AuthenticationPrincipal String userId) throws JsonProcessingException { + public ResponseDTO reissue(@AuthenticationPrincipal String userId) throws JsonProcessingException { User user = userRepository.findById(userId).orElseThrow(()->new IllegalStateException("오류 : 유저없음")); UserResponse userResponse = UserResponse.of(user); - return jwtProvider.reissueAtk(userResponse); + TokenResponse tokens = jwtProvider.reissueAtk(userResponse); + return new ResponseDTO<>(HttpStatus.OK.value(),tokens); } } From 3089c8c502590831ee32f10e3b6f6a0d11629018 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Mon, 30 Jan 2023 12:32:04 +0900 Subject: [PATCH 47/67] =?UTF-8?q?[chore]:=20AWS=20S3=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 9ee407e..53e7511 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.1' implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.12.349' developmentOnly 'org.springframework.boot:spring-boot-devtools' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' From f733619670acf8d888f033fafed4f581f44891b2 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Mon, 30 Jan 2023 12:34:48 +0900 Subject: [PATCH 48/67] =?UTF-8?q?[feat]:=20=EA=B0=9C=EC=9D=B8=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=20API=20=EA=B5=AC=ED=98=84(?= =?UTF-8?q?=EB=8B=89=EB=84=A4=EC=9E=84,=20=ED=9A=8C=EC=9B=90=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dku/springstudy/config/AwsS3Config.java | 30 +++++++++++ .../controller/UserController.java | 20 +++++-- .../springstudy/dto/UserImageChangeDTO.java | 11 ++++ .../dto/UserInformationChangeResponseDTO.java | 11 ++++ .../java/com/dku/springstudy/model/User.java | 5 ++ .../dku/springstudy/service/S3Service.java | 52 +++++++++++++++++++ .../dku/springstudy/service/UserService.java | 21 ++++++-- 7 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/config/AwsS3Config.java create mode 100644 src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java create mode 100644 src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java create mode 100644 src/main/java/com/dku/springstudy/service/S3Service.java diff --git a/src/main/java/com/dku/springstudy/config/AwsS3Config.java b/src/main/java/com/dku/springstudy/config/AwsS3Config.java new file mode 100644 index 0000000..332fb91 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/AwsS3Config.java @@ -0,0 +1,30 @@ +package com.dku.springstudy.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AwsS3Config { + @Value("${spring.cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${spring.cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${spring.cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3Client amazonS3Client() { + BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey); + return (AmazonS3Client) AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCreds)) + .build(); + } +} diff --git a/src/main/java/com/dku/springstudy/controller/UserController.java b/src/main/java/com/dku/springstudy/controller/UserController.java index eaa4701..2e7dea0 100644 --- a/src/main/java/com/dku/springstudy/controller/UserController.java +++ b/src/main/java/com/dku/springstudy/controller/UserController.java @@ -4,6 +4,7 @@ import com.dku.springstudy.dto.*; import com.dku.springstudy.model.User; import com.dku.springstudy.repository.UserRepository; +import com.dku.springstudy.service.S3Service; import com.dku.springstudy.service.UserService; import com.fasterxml.jackson.core.JsonProcessingException; import io.swagger.annotations.Api; @@ -12,11 +13,11 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import javax.mail.Multipart; +import java.io.IOException; import java.util.Optional; @RestController @@ -26,6 +27,7 @@ public class UserController { private final UserRepository userRepository; private final UserService userService; private final JwtProvider jwtProvider; + private final S3Service s3Service; @PostMapping("/account/sign-up") @ApiOperation(value = "회원가입", notes = "SignUpRequest 객체로 받아 유저를 등록합니다.") @@ -50,4 +52,14 @@ public ResponseDTO reissue(@AuthenticationPrincipal String userId) throws Jso TokenResponse tokens = jwtProvider.reissueAtk(userResponse); return new ResponseDTO<>(HttpStatus.OK.value(),tokens); } + + @PutMapping("/change/image") + @ApiOperation(value = "회원정보 수정", notes = "프로필 이미지와 닉네임을 변경 할 수 있습니다.") + public ResponseDTO changePersonalInformation(@AuthenticationPrincipal String userId, UserImageChangeDTO userImageChangeDTO, + @RequestPart("file") MultipartFile file) throws IOException { + String imgPath = s3Service.upload(file); + userImageChangeDTO.setImageUrl(imgPath); + UserInformationChangeResponseDTO userResponse = userService.changeImageAndNickname(userId, userImageChangeDTO); + return new ResponseDTO<>(HttpStatus.OK.value(), userResponse); + } } diff --git a/src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java b/src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java new file mode 100644 index 0000000..eeb77f1 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java @@ -0,0 +1,11 @@ +package com.dku.springstudy.dto; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class UserImageChangeDTO { + private String imageUrl; + private String nickname; +} diff --git a/src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java b/src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java new file mode 100644 index 0000000..0600973 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java @@ -0,0 +1,11 @@ +package com.dku.springstudy.dto; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class UserInformationChangeResponseDTO { + private String imageUrl; + private String nickname; +} diff --git a/src/main/java/com/dku/springstudy/model/User.java b/src/main/java/com/dku/springstudy/model/User.java index 0d04fd6..e414e72 100644 --- a/src/main/java/com/dku/springstudy/model/User.java +++ b/src/main/java/com/dku/springstudy/model/User.java @@ -40,4 +40,9 @@ public class User { @Column(nullable = false) @Enumerated(EnumType.STRING) private Role role; + + public void changeProfileImageAndNickname(String url, String nickname){ + this.profileImageUrl = url; + this.nickname = nickname; + } } diff --git a/src/main/java/com/dku/springstudy/service/S3Service.java b/src/main/java/com/dku/springstudy/service/S3Service.java new file mode 100644 index 0000000..d115ae6 --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/S3Service.java @@ -0,0 +1,52 @@ +package com.dku.springstudy.service; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.PutObjectRequest; +import lombok.NoArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.PostConstruct; +import java.io.IOException; + +@Service +@NoArgsConstructor +public class S3Service { + private AmazonS3 s3Client; + + @Value("${spring.cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${spring.cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${spring.cloud.aws.s3.bucket}") + private String bucket; + + @Value("${spring.cloud.aws.region.static}") + private String region; + + @PostConstruct + public void setS3Client() { + AWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey); + + s3Client = AmazonS3ClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .withRegion(this.region) + .build(); + } + + public String upload(MultipartFile file) throws IOException { + String fileName = file.getOriginalFilename(); + + s3Client.putObject(new PutObjectRequest(bucket, fileName, file.getInputStream(), null) + .withCannedAcl(CannedAccessControlList.PublicRead)); + return s3Client.getUrl(bucket, fileName).toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/service/UserService.java b/src/main/java/com/dku/springstudy/service/UserService.java index 5b13fbf..466a6c6 100644 --- a/src/main/java/com/dku/springstudy/service/UserService.java +++ b/src/main/java/com/dku/springstudy/service/UserService.java @@ -1,14 +1,13 @@ package com.dku.springstudy.service; import com.dku.springstudy.config.security.jwt.JwtProvider; -import com.dku.springstudy.dto.LoginRequest; -import com.dku.springstudy.dto.SignUpRequest; -import com.dku.springstudy.dto.UserResponse; +import com.dku.springstudy.dto.*; import com.dku.springstudy.model.Role; import com.dku.springstudy.model.User; import com.dku.springstudy.repository.UserRepository; import com.fasterxml.jackson.core.JsonProcessingException; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,4 +59,20 @@ public UserResponse login(LoginRequest loginRequest) throws JsonProcessingExcept return UserResponse.of(user); } + + @Transactional + public UserInformationChangeResponseDTO changeImageAndNickname(@AuthenticationPrincipal String userId, UserImageChangeDTO userImageChangeDTO){ + User user = userRepository.findById(userId).orElseThrow(()-> new IllegalStateException("오류 : 없는 사용자 입니다.")); + String newImage = userImageChangeDTO.getImageUrl(); + String newNickname = userImageChangeDTO.getNickname(); + + user.changeProfileImageAndNickname(newImage,newNickname); + + UserInformationChangeResponseDTO userResponse = UserInformationChangeResponseDTO.builder(). + imageUrl(userImageChangeDTO.getImageUrl()) + .nickname(userImageChangeDTO.getNickname()) + .build(); + + return userResponse; + } } From ec9f4648080aa68c2cad96a6840e6d42cb0985a5 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Mon, 30 Jan 2023 13:01:16 +0900 Subject: [PATCH 49/67] =?UTF-8?q?[docs]:=20README.md=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5d2c974..e1de20b 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,43 @@ > 당근마켓 backend server project

- - - - + + + + + + + + + + + + + + +


### 1주차 -> 1. 회원가입 및 로그인 기능 +> 회원가입 및 로그인 기능 - 요구사항 분석 - 도메인 모델 및 테이블 설계 고민 - JWT 구현 및 테스트 코드 작성 - 이메일 인증하기
+ +### 2주차 + +> 초기 도메인 모델 및 테이블 설계 구현 +- 상품 등록, 수정, 삭제 기능 +- 마이페이지(회원 수정 기능) + +
+
## 개발 기록 From 3cee14c725cf427dd37aeeee6eeb3939178eca0c Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 31 Jan 2023 00:22:42 +0900 Subject: [PATCH 50/67] =?UTF-8?q?[feat]:=20=EC=B4=88=EA=B8=B0=20ERD=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dku/springstudy/model/Board.java | 35 +++++++++++++++++++ .../com/dku/springstudy/model/Category.java | 25 +++++++++++++ .../com/dku/springstudy/model/Images.java | 30 ++++++++++++++++ .../com/dku/springstudy/model/ItemStatus.java | 5 +++ .../java/com/dku/springstudy/model/Items.java | 26 ++++++++++++++ .../java/com/dku/springstudy/model/Likes.java | 24 +++++++++++++ 6 files changed, 145 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/model/Board.java create mode 100644 src/main/java/com/dku/springstudy/model/Category.java create mode 100644 src/main/java/com/dku/springstudy/model/Images.java create mode 100644 src/main/java/com/dku/springstudy/model/ItemStatus.java create mode 100644 src/main/java/com/dku/springstudy/model/Items.java create mode 100644 src/main/java/com/dku/springstudy/model/Likes.java diff --git a/src/main/java/com/dku/springstudy/model/Board.java b/src/main/java/com/dku/springstudy/model/Board.java new file mode 100644 index 0000000..919e41a --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/Board.java @@ -0,0 +1,35 @@ +package com.dku.springstudy.model; + +import lombok.*; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter @Builder +@Entity +public class Board { + @Id @GeneratedValue + @Column(name = "board_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @OneToMany(mappedBy = "board",cascade = CascadeType.ALL) + private List likes = new ArrayList<>(); + + @OneToMany(mappedBy = "board",cascade = CascadeType.ALL) + private List item = new ArrayList<>(); + private String title; + @Lob + private String introduction; + + @Enumerated(EnumType.STRING) + private Category category; + + private int price; +} diff --git a/src/main/java/com/dku/springstudy/model/Category.java b/src/main/java/com/dku/springstudy/model/Category.java new file mode 100644 index 0000000..d040b94 --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/Category.java @@ -0,0 +1,25 @@ +package com.dku.springstudy.model; + +import com.fasterxml.jackson.annotation.JsonCreator; + +public enum Category { + DIGITAL_DEVICE("디지털기기"), HOME_APPLIANCE("생활가전"), FURNITURE_INTERIOR("가구/인테리어"), + BABY_PRODUCTS("유아용품"), LIFE_PROCESSED_FOOD("생활/가공식품"), CHILDREN_BOOKS("유아도서"), WOMEN_CLOTHING("여성의류"), + MEN_CLOTHING_STUFF("남성패션/잡화"), GAMES_HOBBY("게임/취미"), BEAUTY("뷰티/미용"), COMPANION_ANIMAL_STUFF("반려동물용품"), + BOOK_TICKET_MUSIC("도서/티켓/음반"), OTHER_USED_ITEMS("기타중고물품"), USED_CAR("중고차"); + + @JsonCreator + public static Category from(String s) { + return Category.valueOf(s.toUpperCase()); + } + + private final String label; + + Category(String label) { + this.label = label; + } + + public String label() { + return label; + } +} diff --git a/src/main/java/com/dku/springstudy/model/Images.java b/src/main/java/com/dku/springstudy/model/Images.java new file mode 100644 index 0000000..ad044e0 --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/Images.java @@ -0,0 +1,30 @@ +package com.dku.springstudy.model; + +import lombok.*; + +import javax.persistence.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@Builder +@Entity +public class Images { + + @Id @GeneratedValue + @Column(name = "image_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "board_id") + private Board board; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Items item; + +} diff --git a/src/main/java/com/dku/springstudy/model/ItemStatus.java b/src/main/java/com/dku/springstudy/model/ItemStatus.java new file mode 100644 index 0000000..7192f6d --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/ItemStatus.java @@ -0,0 +1,5 @@ +package com.dku.springstudy.model; + +public enum ItemStatus { + SELLING,RESERVING,COMPLETE +} diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java new file mode 100644 index 0000000..806c3c2 --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -0,0 +1,26 @@ +package com.dku.springstudy.model; + +import lombok.*; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@Builder +@Entity +public class Items { + + @Id @GeneratedValue + @Column(name = "item_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "board_id") + private Board board; + + private ItemStatus itemStatus; + +} diff --git a/src/main/java/com/dku/springstudy/model/Likes.java b/src/main/java/com/dku/springstudy/model/Likes.java new file mode 100644 index 0000000..23763cd --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/Likes.java @@ -0,0 +1,24 @@ +package com.dku.springstudy.model; + +import lombok.*; + +import javax.persistence.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter @Builder +@Entity +public class Likes { + + @Id @GeneratedValue + @Column(name = "likes_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "board_id") + private Board board; +} From 949b49c555e0961882a43d3064db8693dda823a9 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 31 Jan 2023 00:40:45 +0900 Subject: [PATCH 51/67] =?UTF-8?q?[rename]:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/security/jwt/JwtProvider.java | 12 ++++++------ .../springstudy/controller/UserController.java | 18 +++++++----------- ...{LoginRequest.java => LoginRequestDTO.java} | 2 +- ...ignUpRequest.java => SignUpRequestDTO.java} | 2 +- ...kenResponse.java => TokensResponseDTO.java} | 2 +- ...va => UserInformationChangeRequestDTO.java} | 2 +- ...{UserResponse.java => UserResponseDTO.java} | 8 ++++---- .../dku/springstudy/service/UserService.java | 10 +++++----- 8 files changed, 26 insertions(+), 30 deletions(-) rename src/main/java/com/dku/springstudy/dto/{LoginRequest.java => LoginRequestDTO.java} (79%) rename src/main/java/com/dku/springstudy/dto/{SignUpRequest.java => SignUpRequestDTO.java} (88%) rename src/main/java/com/dku/springstudy/dto/{TokenResponse.java => TokensResponseDTO.java} (78%) rename src/main/java/com/dku/springstudy/dto/{UserImageChangeDTO.java => UserInformationChangeRequestDTO.java} (76%) rename src/main/java/com/dku/springstudy/dto/{UserResponse.java => UserResponseDTO.java} (72%) diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java index 553bee7..a9f5e88 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java @@ -1,8 +1,8 @@ package com.dku.springstudy.config.security.jwt; import com.dku.springstudy.config.security.RedisDao; -import com.dku.springstudy.dto.TokenResponse; -import com.dku.springstudy.dto.UserResponse; +import com.dku.springstudy.dto.TokensResponseDTO; +import com.dku.springstudy.dto.UserResponseDTO; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.Claims; @@ -38,7 +38,7 @@ protected void init() { key = Base64.getEncoder().encodeToString(key.getBytes()); } - public TokenResponse reissueAtk(UserResponse userResponse) throws JsonProcessingException { + public TokensResponseDTO reissueAtk(UserResponseDTO userResponse) throws JsonProcessingException { String rtkInRedis = redisDao.getValues(userResponse.getEmail()); if (Objects.isNull(rtkInRedis)) throw new IllegalStateException("인증 정보가 만료되었습니다."); Subject atkSubject = Subject.atk( @@ -47,9 +47,9 @@ public TokenResponse reissueAtk(UserResponse userResponse) throws JsonProcessing userResponse.getNickname(), userResponse.getRole()); String atk = createToken(atkSubject, atkLive); - return new TokenResponse(atk, null); + return new TokensResponseDTO(atk, null); } - public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonProcessingException { + public TokensResponseDTO createTokensByLogin(UserResponseDTO userResponse) throws JsonProcessingException { Subject atkSubject = Subject.atk( userResponse.getUserId(), userResponse.getEmail(), @@ -63,7 +63,7 @@ public TokenResponse createTokensByLogin(UserResponse userResponse) throws JsonP String atk = createToken(atkSubject, atkLive); String rtk = createToken(rtkSubject, rtkLive); redisDao.setValues(userResponse.getEmail(), rtk, Duration.ofMillis(rtkLive)); - return new TokenResponse(atk, rtk); + return new TokensResponseDTO(atk, rtk); } private String createToken(Subject subject, Long tokenLive) throws JsonProcessingException { diff --git a/src/main/java/com/dku/springstudy/controller/UserController.java b/src/main/java/com/dku/springstudy/controller/UserController.java index 2e7dea0..65467d2 100644 --- a/src/main/java/com/dku/springstudy/controller/UserController.java +++ b/src/main/java/com/dku/springstudy/controller/UserController.java @@ -7,18 +7,14 @@ import com.dku.springstudy.service.S3Service; import com.dku.springstudy.service.UserService; import com.fasterxml.jackson.core.JsonProcessingException; -import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import javax.mail.Multipart; import java.io.IOException; -import java.util.Optional; @RestController @RequiredArgsConstructor @@ -31,16 +27,16 @@ public class UserController { @PostMapping("/account/sign-up") @ApiOperation(value = "회원가입", notes = "SignUpRequest 객체로 받아 유저를 등록합니다.") - public ResponseDTO signUp(@RequestBody SignUpRequest signUpRequest){ + public ResponseDTO signUp(@RequestBody SignUpRequestDTO signUpRequest){ userService.signUp(signUpRequest); return new ResponseDTO<>(HttpStatus.OK.value(), signUpRequest); } @PostMapping("/account/login") @ApiOperation(value = "로그인", notes = "LoginRequest 객체로 email과 password를 받아 로그인을 진행하고, access token과 refresh token을 리턴합니다.") - public ResponseDTO login(@RequestBody LoginRequest loginRequest) throws JsonProcessingException { - UserResponse userResponse = userService.login(loginRequest); - TokenResponse tokens = jwtProvider.createTokensByLogin(userResponse); + public ResponseDTO login(@RequestBody LoginRequestDTO loginRequest) throws JsonProcessingException { + UserResponseDTO userResponse = userService.login(loginRequest); + TokensResponseDTO tokens = jwtProvider.createTokensByLogin(userResponse); return new ResponseDTO<>(HttpStatus.OK.value(), tokens); } @@ -48,14 +44,14 @@ public ResponseDTO login(@RequestBody LoginRequest loginRequest) throws JsonP @ApiOperation(value = "access토큰 재발급", notes = "access 토큰이 만료된 경우 refresh 토큰을 이용하여 access 토큰을 갱신합니다.") public ResponseDTO reissue(@AuthenticationPrincipal String userId) throws JsonProcessingException { User user = userRepository.findById(userId).orElseThrow(()->new IllegalStateException("오류 : 유저없음")); - UserResponse userResponse = UserResponse.of(user); - TokenResponse tokens = jwtProvider.reissueAtk(userResponse); + UserResponseDTO userResponse = UserResponseDTO.of(user); + TokensResponseDTO tokens = jwtProvider.reissueAtk(userResponse); return new ResponseDTO<>(HttpStatus.OK.value(),tokens); } @PutMapping("/change/image") @ApiOperation(value = "회원정보 수정", notes = "프로필 이미지와 닉네임을 변경 할 수 있습니다.") - public ResponseDTO changePersonalInformation(@AuthenticationPrincipal String userId, UserImageChangeDTO userImageChangeDTO, + public ResponseDTO changePersonalInformation(@AuthenticationPrincipal String userId, UserInformationChangeRequestDTO userImageChangeDTO, @RequestPart("file") MultipartFile file) throws IOException { String imgPath = s3Service.upload(file); userImageChangeDTO.setImageUrl(imgPath); diff --git a/src/main/java/com/dku/springstudy/dto/LoginRequest.java b/src/main/java/com/dku/springstudy/dto/LoginRequestDTO.java similarity index 79% rename from src/main/java/com/dku/springstudy/dto/LoginRequest.java rename to src/main/java/com/dku/springstudy/dto/LoginRequestDTO.java index 21b9b21..770e65c 100644 --- a/src/main/java/com/dku/springstudy/dto/LoginRequest.java +++ b/src/main/java/com/dku/springstudy/dto/LoginRequestDTO.java @@ -3,7 +3,7 @@ import lombok.Data; @Data -public class LoginRequest { +public class LoginRequestDTO { private String email; private String password; } diff --git a/src/main/java/com/dku/springstudy/dto/SignUpRequest.java b/src/main/java/com/dku/springstudy/dto/SignUpRequestDTO.java similarity index 88% rename from src/main/java/com/dku/springstudy/dto/SignUpRequest.java rename to src/main/java/com/dku/springstudy/dto/SignUpRequestDTO.java index 5dce2d2..335fd2c 100644 --- a/src/main/java/com/dku/springstudy/dto/SignUpRequest.java +++ b/src/main/java/com/dku/springstudy/dto/SignUpRequestDTO.java @@ -3,7 +3,7 @@ import lombok.Data; @Data -public class SignUpRequest { +public class SignUpRequestDTO { private final String email; private final String password; private final String username; diff --git a/src/main/java/com/dku/springstudy/dto/TokenResponse.java b/src/main/java/com/dku/springstudy/dto/TokensResponseDTO.java similarity index 78% rename from src/main/java/com/dku/springstudy/dto/TokenResponse.java rename to src/main/java/com/dku/springstudy/dto/TokensResponseDTO.java index 28a12a6..9bfcfb2 100644 --- a/src/main/java/com/dku/springstudy/dto/TokenResponse.java +++ b/src/main/java/com/dku/springstudy/dto/TokensResponseDTO.java @@ -3,7 +3,7 @@ import lombok.Data; @Data -public class TokenResponse { +public class TokensResponseDTO { private final String atk; private final String rtk; } diff --git a/src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java b/src/main/java/com/dku/springstudy/dto/UserInformationChangeRequestDTO.java similarity index 76% rename from src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java rename to src/main/java/com/dku/springstudy/dto/UserInformationChangeRequestDTO.java index eeb77f1..b9ee59a 100644 --- a/src/main/java/com/dku/springstudy/dto/UserImageChangeDTO.java +++ b/src/main/java/com/dku/springstudy/dto/UserInformationChangeRequestDTO.java @@ -5,7 +5,7 @@ @Data @Builder -public class UserImageChangeDTO { +public class UserInformationChangeRequestDTO { private String imageUrl; private String nickname; } diff --git a/src/main/java/com/dku/springstudy/dto/UserResponse.java b/src/main/java/com/dku/springstudy/dto/UserResponseDTO.java similarity index 72% rename from src/main/java/com/dku/springstudy/dto/UserResponse.java rename to src/main/java/com/dku/springstudy/dto/UserResponseDTO.java index 4dcdea6..a7176aa 100644 --- a/src/main/java/com/dku/springstudy/dto/UserResponse.java +++ b/src/main/java/com/dku/springstudy/dto/UserResponseDTO.java @@ -5,7 +5,7 @@ import lombok.Data; @Data -public class UserResponse { +public class UserResponseDTO { private final String userId; private final String email; @@ -13,15 +13,15 @@ public class UserResponse { private final String nickname; private Role role = Role.USER; - public UserResponse(String userId, String email, String nickname, Role role) { + public UserResponseDTO(String userId, String email, String nickname, Role role) { this.userId = userId; this.email = email; this.nickname = nickname; this.role = role; } - public static UserResponse of(User user) { - return new UserResponse( + public static UserResponseDTO of(User user) { + return new UserResponseDTO( user.getId(), user.getEmail(), user.getNickname(), diff --git a/src/main/java/com/dku/springstudy/service/UserService.java b/src/main/java/com/dku/springstudy/service/UserService.java index 466a6c6..f1431dc 100644 --- a/src/main/java/com/dku/springstudy/service/UserService.java +++ b/src/main/java/com/dku/springstudy/service/UserService.java @@ -22,7 +22,7 @@ public class UserService { private final PasswordEncoder passwordEncoder; @Transactional - public void signUp(SignUpRequest signUpRequest){ + public void signUp(SignUpRequestDTO signUpRequest){ boolean isExist = userRepository.existsByEmail(signUpRequest.getEmail()); if(isExist){ @@ -44,7 +44,7 @@ public void signUp(SignUpRequest signUpRequest){ } @Transactional - public UserResponse login(LoginRequest loginRequest) throws JsonProcessingException { + public UserResponseDTO login(LoginRequestDTO loginRequest) throws JsonProcessingException { User user = userRepository.findByEmail(loginRequest.getEmail()) .orElseThrow(() -> new IllegalStateException("아이디 혹은 비밀번호를 확인하세요.")); @@ -53,15 +53,15 @@ public UserResponse login(LoginRequest loginRequest) throws JsonProcessingExcept throw new IllegalStateException("아이디 혹은 비밀번호를 확인하세요."); } - UserResponse userResponse = UserResponse.of(user); + UserResponseDTO userResponse = UserResponseDTO.of(user); final String token = jwtProvider.createTokensByLogin(userResponse).getAtk(); user.setToken(token); - return UserResponse.of(user); + return UserResponseDTO.of(user); } @Transactional - public UserInformationChangeResponseDTO changeImageAndNickname(@AuthenticationPrincipal String userId, UserImageChangeDTO userImageChangeDTO){ + public UserInformationChangeResponseDTO changeImageAndNickname(@AuthenticationPrincipal String userId, UserInformationChangeRequestDTO userImageChangeDTO){ User user = userRepository.findById(userId).orElseThrow(()-> new IllegalStateException("오류 : 없는 사용자 입니다.")); String newImage = userImageChangeDTO.getImageUrl(); String newNickname = userImageChangeDTO.getNickname(); From e61b3adae265c638cc6dd5506166158def62e25b Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Tue, 31 Jan 2023 00:59:17 +0900 Subject: [PATCH 52/67] =?UTF-8?q?[feat]:=20=EB=AA=A8=EB=93=A0=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EC=97=90=20JPA=20Auditing=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84(=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EA=B0=92=20=EC=83=9D=EC=84=B1=EC=8B=9C=EA=B0=84,=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=8B=9C=EA=B0=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springstudy/SpringStudyApplication.java | 2 ++ .../dku/springstudy/model/BaseTimeEntity.java | 22 +++++++++++++++++++ .../java/com/dku/springstudy/model/Board.java | 2 +- .../com/dku/springstudy/model/Images.java | 2 +- .../java/com/dku/springstudy/model/Items.java | 2 +- .../java/com/dku/springstudy/model/Likes.java | 2 +- .../java/com/dku/springstudy/model/User.java | 2 +- 7 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/model/BaseTimeEntity.java diff --git a/src/main/java/com/dku/springstudy/SpringStudyApplication.java b/src/main/java/com/dku/springstudy/SpringStudyApplication.java index ef164c9..1bef475 100644 --- a/src/main/java/com/dku/springstudy/SpringStudyApplication.java +++ b/src/main/java/com/dku/springstudy/SpringStudyApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class SpringStudyApplication { diff --git a/src/main/java/com/dku/springstudy/model/BaseTimeEntity.java b/src/main/java/com/dku/springstudy/model/BaseTimeEntity.java new file mode 100644 index 0000000..ade7483 --- /dev/null +++ b/src/main/java/com/dku/springstudy/model/BaseTimeEntity.java @@ -0,0 +1,22 @@ +package com.dku.springstudy.model; + +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.time.LocalDateTime; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseTimeEntity { + + @CreatedDate + private LocalDateTime createdDate; + + @LastModifiedDate + private LocalDateTime modifiedDate; +} diff --git a/src/main/java/com/dku/springstudy/model/Board.java b/src/main/java/com/dku/springstudy/model/Board.java index 919e41a..b5602d7 100644 --- a/src/main/java/com/dku/springstudy/model/Board.java +++ b/src/main/java/com/dku/springstudy/model/Board.java @@ -10,7 +10,7 @@ @AllArgsConstructor @Getter @Builder @Entity -public class Board { +public class Board extends BaseTimeEntity { @Id @GeneratedValue @Column(name = "board_id") private Long id; diff --git a/src/main/java/com/dku/springstudy/model/Images.java b/src/main/java/com/dku/springstudy/model/Images.java index ad044e0..8b56700 100644 --- a/src/main/java/com/dku/springstudy/model/Images.java +++ b/src/main/java/com/dku/springstudy/model/Images.java @@ -9,7 +9,7 @@ @Getter @Builder @Entity -public class Images { +public class Images extends BaseTimeEntity{ @Id @GeneratedValue @Column(name = "image_id") diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java index 806c3c2..0614971 100644 --- a/src/main/java/com/dku/springstudy/model/Items.java +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -11,7 +11,7 @@ @Getter @Builder @Entity -public class Items { +public class Items extends BaseTimeEntity { @Id @GeneratedValue @Column(name = "item_id") diff --git a/src/main/java/com/dku/springstudy/model/Likes.java b/src/main/java/com/dku/springstudy/model/Likes.java index 23763cd..536e758 100644 --- a/src/main/java/com/dku/springstudy/model/Likes.java +++ b/src/main/java/com/dku/springstudy/model/Likes.java @@ -8,7 +8,7 @@ @AllArgsConstructor @Getter @Builder @Entity -public class Likes { +public class Likes extends BaseTimeEntity{ @Id @GeneratedValue @Column(name = "likes_id") diff --git a/src/main/java/com/dku/springstudy/model/User.java b/src/main/java/com/dku/springstudy/model/User.java index e414e72..7fffe51 100644 --- a/src/main/java/com/dku/springstudy/model/User.java +++ b/src/main/java/com/dku/springstudy/model/User.java @@ -9,7 +9,7 @@ @Getter @Builder @Table(name = "Users", uniqueConstraints = {@UniqueConstraint(columnNames = "email")}) @Entity -public class User { +public class User extends BaseTimeEntity{ @Id @GeneratedValue(generator = "system-uuid") From 1b8af84fa2fb52c680110328d091dbd8d119b0eb Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Wed, 1 Feb 2023 19:46:29 +0900 Subject: [PATCH 53/67] =?UTF-8?q?[feat]:=20=EC=A4=91=EA=B3=A0=EA=B1=B0?= =?UTF-8?q?=EB=9E=98=20=EA=B8=80=EC=93=B0=EA=B8=B0(=EB=8B=A4=EC=A4=91=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BoardController.java | 32 +++++++ .../com/dku/springstudy/dto/BoardDTO.java | 14 +++ .../java/com/dku/springstudy/model/Board.java | 2 +- .../repository/BoardRepository.java | 8 ++ .../dku/springstudy/service/BoardService.java | 89 +++++++++++++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/dku/springstudy/controller/BoardController.java create mode 100644 src/main/java/com/dku/springstudy/dto/BoardDTO.java create mode 100644 src/main/java/com/dku/springstudy/repository/BoardRepository.java create mode 100644 src/main/java/com/dku/springstudy/service/BoardService.java diff --git a/src/main/java/com/dku/springstudy/controller/BoardController.java b/src/main/java/com/dku/springstudy/controller/BoardController.java new file mode 100644 index 0000000..81da872 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/BoardController.java @@ -0,0 +1,32 @@ +package com.dku.springstudy.controller; + +import com.dku.springstudy.dto.BoardDTO; +import com.dku.springstudy.dto.ResponseDTO; +import com.dku.springstudy.service.BoardService; +import com.dku.springstudy.service.S3Service; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +public class BoardController { + + private final S3Service s3Service; + private final BoardService boardService; + + @ApiOperation(value = "게시판 글쓰기", notes = "여러장의 이미지와 제목,가격,카테고리,게시글 내용 값을 받아서 게시판을 작성한다") + @PostMapping("/board") + public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, + BoardDTO boardDTO, @RequestPart("file") List file) { + List imgPaths = boardService.multipleUpload(file); + boardDTO.setImageUrls(imgPaths); + boardService.write(boardDTO, userId); + return new ResponseDTO<>(HttpStatus.OK.value(), boardDTO); + } +} diff --git a/src/main/java/com/dku/springstudy/dto/BoardDTO.java b/src/main/java/com/dku/springstudy/dto/BoardDTO.java new file mode 100644 index 0000000..de25efc --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/BoardDTO.java @@ -0,0 +1,14 @@ +package com.dku.springstudy.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class BoardDTO { + + private List imageUrls; + private String title; + private int price; + private String intro; +} \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/model/Board.java b/src/main/java/com/dku/springstudy/model/Board.java index b5602d7..222812f 100644 --- a/src/main/java/com/dku/springstudy/model/Board.java +++ b/src/main/java/com/dku/springstudy/model/Board.java @@ -26,7 +26,7 @@ public class Board extends BaseTimeEntity { private List item = new ArrayList<>(); private String title; @Lob - private String introduction; + private String intro; @Enumerated(EnumType.STRING) private Category category; diff --git a/src/main/java/com/dku/springstudy/repository/BoardRepository.java b/src/main/java/com/dku/springstudy/repository/BoardRepository.java new file mode 100644 index 0000000..6723a51 --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/BoardRepository.java @@ -0,0 +1,8 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.model.Board; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BoardRepository extends JpaRepository { + +} diff --git a/src/main/java/com/dku/springstudy/service/BoardService.java b/src/main/java/com/dku/springstudy/service/BoardService.java new file mode 100644 index 0000000..358fb44 --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/BoardService.java @@ -0,0 +1,89 @@ +package com.dku.springstudy.service; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.dku.springstudy.dto.BoardDTO; +import com.dku.springstudy.model.Board; +import com.dku.springstudy.model.Category; +import com.dku.springstudy.model.User; +import com.dku.springstudy.repository.BoardRepository; +import com.dku.springstudy.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Transactional(readOnly = true) +@RequiredArgsConstructor +@Service +public class BoardService { + + @Value("${spring.cloud.aws.s3.bucket}") + private String bucket; + private final AmazonS3 amazonS3; + + private final BoardRepository boardRepository; + private final UserRepository userRepository; + + @Transactional + public void write(BoardDTO boardDTO, String userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalStateException("멤버가 없습니다")); + Board board = Board.builder() + .user(user) + .title(boardDTO.getTitle()) + .price(boardDTO.getPrice()) + .intro(boardDTO.getIntro()) + .category(Category.BEAUTY) + .build(); + System.out.println(boardDTO.getIntro()); + boardRepository.save(board); + } + + public List multipleUpload(List multipartFile) { + List fileNameList = new ArrayList<>(); + + multipartFile.forEach(file -> { + String fileName = createFileName(file.getOriginalFilename()); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(file.getSize()); + objectMetadata.setContentType(file.getContentType()); + + try (InputStream inputStream = file.getInputStream()) { + amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + } catch (IOException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다."); + } + fileNameList.add(fileName); + }); + return fileNameList; + } + + public void deleteFile(String fileName) { + amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + } + + private String createFileName(String fileName) { + return UUID.randomUUID().toString().concat(getFileExtension(fileName)); + } + + private String getFileExtension(String fileName) { + try { + return fileName.substring(fileName.lastIndexOf(".")); + } catch (StringIndexOutOfBoundsException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다."); + } + } +} From bf470259d2d5f4d7a94a3748a99e65972899bbee Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Wed, 1 Feb 2023 20:48:44 +0900 Subject: [PATCH 54/67] =?UTF-8?q?[chore]:=20Hibernate5Module=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 53e7511..b1fd040 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.1' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.12.349' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' developmentOnly 'org.springframework.boot:spring-boot-devtools' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' From 34c09c1ee587f0f3aed5fabdd6684ff929ef1b0b Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Wed, 1 Feb 2023 20:53:33 +0900 Subject: [PATCH 55/67] =?UTF-8?q?[fix]:=20=EC=A7=80=EC=97=B0=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=EC=8B=9C=20=ED=94=84=EB=A1=9D=EC=8B=9C=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20json=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/security/LazyLoadingProxyConfig.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/config/security/LazyLoadingProxyConfig.java diff --git a/src/main/java/com/dku/springstudy/config/security/LazyLoadingProxyConfig.java b/src/main/java/com/dku/springstudy/config/security/LazyLoadingProxyConfig.java new file mode 100644 index 0000000..006e6b0 --- /dev/null +++ b/src/main/java/com/dku/springstudy/config/security/LazyLoadingProxyConfig.java @@ -0,0 +1,13 @@ +package com.dku.springstudy.config.security; + +import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LazyLoadingProxyConfig { + @Bean + Hibernate5Module hibernate5Module() { + return new Hibernate5Module(); + } +} From 9348400e414a57d10486f6d7ec58deda329e508f Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Wed, 1 Feb 2023 21:17:41 +0900 Subject: [PATCH 56/67] =?UTF-8?q?[feat]:=20=EA=B2=8C=EC=8B=9C=ED=8C=90=20?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BoardController.java | 14 ++++++++++- .../dku/springstudy/dto/BoardResponseDTO.java | 23 +++++++++++++++++++ .../dku/springstudy/service/BoardService.java | 7 +++++- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java diff --git a/src/main/java/com/dku/springstudy/controller/BoardController.java b/src/main/java/com/dku/springstudy/controller/BoardController.java index 81da872..4a2d607 100644 --- a/src/main/java/com/dku/springstudy/controller/BoardController.java +++ b/src/main/java/com/dku/springstudy/controller/BoardController.java @@ -1,7 +1,9 @@ package com.dku.springstudy.controller; import com.dku.springstudy.dto.BoardDTO; +import com.dku.springstudy.dto.BoardResponseDTO; import com.dku.springstudy.dto.ResponseDTO; +import com.dku.springstudy.model.Board; import com.dku.springstudy.service.BoardService; import com.dku.springstudy.service.S3Service; import io.swagger.annotations.ApiOperation; @@ -12,6 +14,7 @@ import org.springframework.web.multipart.MultipartFile; import java.util.List; +import java.util.stream.Collectors; @RestController @RequiredArgsConstructor @@ -29,4 +32,13 @@ public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, boardService.write(boardDTO, userId); return new ResponseDTO<>(HttpStatus.OK.value(), boardDTO); } -} + @ApiOperation(value = "게시판 보기", notes = "사진,제목,가격,장소, 등을 게시판을 통해 보여준다") + @GetMapping("/board") + public ResponseDTO index(){ + List boardLists = boardService.index(); + List result = boardLists.stream() + .map(b -> new BoardResponseDTO(b)) + .collect(Collectors.toList()); + return new ResponseDTO<>(HttpStatus.OK.value(), result); + } +} \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java b/src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java new file mode 100644 index 0000000..3b55045 --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java @@ -0,0 +1,23 @@ +package com.dku.springstudy.dto; + +import com.dku.springstudy.model.Board; +import com.dku.springstudy.model.Category; +import lombok.Data; + +@Data +public class BoardResponseDTO { + + private Long id; + private String title; + private String intro; + private Category category; + private int price; + + public BoardResponseDTO(Board board){ + id = board.getId(); + title = board.getTitle(); + intro = board.getIntro(); + category = board.getCategory(); + price = board.getPrice(); + } +} diff --git a/src/main/java/com/dku/springstudy/service/BoardService.java b/src/main/java/com/dku/springstudy/service/BoardService.java index 358fb44..34dc78b 100644 --- a/src/main/java/com/dku/springstudy/service/BoardService.java +++ b/src/main/java/com/dku/springstudy/service/BoardService.java @@ -66,7 +66,7 @@ public List multipleUpload(List multipartFile) { } catch (IOException e) { throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다."); } - fileNameList.add(fileName); + fileNameList.add(amazonS3.getUrl(bucket, fileName).toString()); }); return fileNameList; } @@ -86,4 +86,9 @@ private String getFileExtension(String fileName) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다."); } } + + public List index(){ + List boards = boardRepository.findAll(); + return boards; + } } From ea3b15e4d17d64d5435fd3e86fc8aecd29d6cdca Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Thu, 2 Feb 2023 00:42:44 +0900 Subject: [PATCH 57/67] =?UTF-8?q?[refactor]:=20=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=EA=B3=BC=20=EC=83=81=ED=92=88=EC=9D=80=20=EC=9D=BC=EB=8C=80?= =?UTF-8?q?=EC=9D=BC=20=EA=B4=80=EA=B3=84=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/dku/springstudy/model/Board.java | 2 +- src/main/java/com/dku/springstudy/model/Items.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dku/springstudy/model/Board.java b/src/main/java/com/dku/springstudy/model/Board.java index 222812f..bd0e85e 100644 --- a/src/main/java/com/dku/springstudy/model/Board.java +++ b/src/main/java/com/dku/springstudy/model/Board.java @@ -22,7 +22,7 @@ public class Board extends BaseTimeEntity { @OneToMany(mappedBy = "board",cascade = CascadeType.ALL) private List likes = new ArrayList<>(); - @OneToMany(mappedBy = "board",cascade = CascadeType.ALL) + @OneToOne(mappedBy = "board",cascade = CascadeType.ALL) private List item = new ArrayList<>(); private String title; @Lob diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java index 0614971..cba69b8 100644 --- a/src/main/java/com/dku/springstudy/model/Items.java +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -17,7 +17,7 @@ public class Items extends BaseTimeEntity { @Column(name = "item_id") private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "board_id") private Board board; From aabefcdaac029cf8cafedf68a7682cf1c87bb377 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Thu, 2 Feb 2023 10:01:08 +0900 Subject: [PATCH 58/67] =?UTF-8?q?[refactor]:=20board=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=EB=A5=BC=20items=EC=97=94=ED=8B=B0=ED=8B=B0=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD(=EB=8F=84=EB=A9=94=EC=9D=B8,=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EB=8A=94=20=ED=99=94=EB=A9=B4=EC=97=90=20?= =?UTF-8?q?=EC=A2=85=EC=86=8D=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94?= =?UTF-8?q?=EB=8B=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ardController.java => ItemController.java} | 24 ++++++------- .../dku/springstudy/dto/BoardResponseDTO.java | 23 ------------ .../dto/{BoardDTO.java => ItemsDTO.java} | 2 +- .../dku/springstudy/dto/ItemsResponseDTO.java | 33 +++++++++++++++++ .../java/com/dku/springstudy/model/Board.java | 35 ------------------- .../com/dku/springstudy/model/Images.java | 6 +--- .../java/com/dku/springstudy/model/Items.java | 26 ++++++++++---- ...rdRepository.java => ItemsRepository.java} | 4 +-- .../{BoardService.java => ItemsService.java} | 29 ++++++++------- 9 files changed, 82 insertions(+), 100 deletions(-) rename src/main/java/com/dku/springstudy/controller/{BoardController.java => ItemController.java} (69%) delete mode 100644 src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java rename src/main/java/com/dku/springstudy/dto/{BoardDTO.java => ItemsDTO.java} (89%) create mode 100644 src/main/java/com/dku/springstudy/dto/ItemsResponseDTO.java delete mode 100644 src/main/java/com/dku/springstudy/model/Board.java rename src/main/java/com/dku/springstudy/repository/{BoardRepository.java => ItemsRepository.java} (52%) rename src/main/java/com/dku/springstudy/service/{BoardService.java => ItemsService.java} (82%) diff --git a/src/main/java/com/dku/springstudy/controller/BoardController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java similarity index 69% rename from src/main/java/com/dku/springstudy/controller/BoardController.java rename to src/main/java/com/dku/springstudy/controller/ItemController.java index 4a2d607..f10c5fe 100644 --- a/src/main/java/com/dku/springstudy/controller/BoardController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -1,10 +1,10 @@ package com.dku.springstudy.controller; -import com.dku.springstudy.dto.BoardDTO; -import com.dku.springstudy.dto.BoardResponseDTO; +import com.dku.springstudy.dto.ItemsDTO; +import com.dku.springstudy.dto.ItemsResponseDTO; import com.dku.springstudy.dto.ResponseDTO; -import com.dku.springstudy.model.Board; -import com.dku.springstudy.service.BoardService; +import com.dku.springstudy.model.Items; +import com.dku.springstudy.service.ItemsService; import com.dku.springstudy.service.S3Service; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; @@ -18,26 +18,26 @@ @RestController @RequiredArgsConstructor -public class BoardController { +public class ItemController { private final S3Service s3Service; - private final BoardService boardService; + private final ItemsService itemsService; @ApiOperation(value = "게시판 글쓰기", notes = "여러장의 이미지와 제목,가격,카테고리,게시글 내용 값을 받아서 게시판을 작성한다") @PostMapping("/board") public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, - BoardDTO boardDTO, @RequestPart("file") List file) { - List imgPaths = boardService.multipleUpload(file); + ItemsDTO boardDTO, @RequestPart("file") List file) { + List imgPaths = itemsService.multipleUpload(file); boardDTO.setImageUrls(imgPaths); - boardService.write(boardDTO, userId); + itemsService.write(boardDTO, userId); return new ResponseDTO<>(HttpStatus.OK.value(), boardDTO); } @ApiOperation(value = "게시판 보기", notes = "사진,제목,가격,장소, 등을 게시판을 통해 보여준다") @GetMapping("/board") public ResponseDTO index(){ - List boardLists = boardService.index(); - List result = boardLists.stream() - .map(b -> new BoardResponseDTO(b)) + List itemLists = itemsService.index(); + List result = itemLists.stream() + .map(b -> new ItemsResponseDTO(b)) .collect(Collectors.toList()); return new ResponseDTO<>(HttpStatus.OK.value(), result); } diff --git a/src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java b/src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java deleted file mode 100644 index 3b55045..0000000 --- a/src/main/java/com/dku/springstudy/dto/BoardResponseDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dku.springstudy.dto; - -import com.dku.springstudy.model.Board; -import com.dku.springstudy.model.Category; -import lombok.Data; - -@Data -public class BoardResponseDTO { - - private Long id; - private String title; - private String intro; - private Category category; - private int price; - - public BoardResponseDTO(Board board){ - id = board.getId(); - title = board.getTitle(); - intro = board.getIntro(); - category = board.getCategory(); - price = board.getPrice(); - } -} diff --git a/src/main/java/com/dku/springstudy/dto/BoardDTO.java b/src/main/java/com/dku/springstudy/dto/ItemsDTO.java similarity index 89% rename from src/main/java/com/dku/springstudy/dto/BoardDTO.java rename to src/main/java/com/dku/springstudy/dto/ItemsDTO.java index de25efc..0a89a7c 100644 --- a/src/main/java/com/dku/springstudy/dto/BoardDTO.java +++ b/src/main/java/com/dku/springstudy/dto/ItemsDTO.java @@ -5,7 +5,7 @@ import java.util.List; @Data -public class BoardDTO { +public class ItemsDTO { private List imageUrls; private String title; diff --git a/src/main/java/com/dku/springstudy/dto/ItemsResponseDTO.java b/src/main/java/com/dku/springstudy/dto/ItemsResponseDTO.java new file mode 100644 index 0000000..ba1beef --- /dev/null +++ b/src/main/java/com/dku/springstudy/dto/ItemsResponseDTO.java @@ -0,0 +1,33 @@ +package com.dku.springstudy.dto; + +import com.dku.springstudy.model.Images; +import com.dku.springstudy.model.Items; +import com.dku.springstudy.model.Category; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class ItemsResponseDTO { + + private Long id; + + private List images; + private String title; + private String intro; + private Category category; + private int price; + + private LocalDateTime modifiedDate; + + public ItemsResponseDTO(Items items){ + id = items.getId(); + images = items.getImages(); + title = items.getTitle(); + intro = items.getIntro(); + category = items.getCategory(); + price = items.getPrice(); + modifiedDate = items.getModifiedDate(); + } +} diff --git a/src/main/java/com/dku/springstudy/model/Board.java b/src/main/java/com/dku/springstudy/model/Board.java deleted file mode 100644 index bd0e85e..0000000 --- a/src/main/java/com/dku/springstudy/model/Board.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dku.springstudy.model; - -import lombok.*; - -import javax.persistence.*; -import java.util.ArrayList; -import java.util.List; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Getter @Builder -@Entity -public class Board extends BaseTimeEntity { - @Id @GeneratedValue - @Column(name = "board_id") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @OneToMany(mappedBy = "board",cascade = CascadeType.ALL) - private List likes = new ArrayList<>(); - - @OneToOne(mappedBy = "board",cascade = CascadeType.ALL) - private List item = new ArrayList<>(); - private String title; - @Lob - private String intro; - - @Enumerated(EnumType.STRING) - private Category category; - - private int price; -} diff --git a/src/main/java/com/dku/springstudy/model/Images.java b/src/main/java/com/dku/springstudy/model/Images.java index 8b56700..cda3dd8 100644 --- a/src/main/java/com/dku/springstudy/model/Images.java +++ b/src/main/java/com/dku/springstudy/model/Images.java @@ -19,12 +19,8 @@ public class Images extends BaseTimeEntity{ @JoinColumn(name = "user_id") private User user; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "board_id") - private Board board; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "item_id") - private Items item; + private Items items; } diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java index cba69b8..72a3d22 100644 --- a/src/main/java/com/dku/springstudy/model/Items.java +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -8,19 +8,31 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -@Getter -@Builder +@Getter @Builder @Entity public class Items extends BaseTimeEntity { - @Id @GeneratedValue @Column(name = "item_id") private Long id; - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "board_id") - private Board board; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; - private ItemStatus itemStatus; + @OneToMany(mappedBy = "items",cascade = CascadeType.ALL) + private List likes = new ArrayList<>(); + + @OneToMany(mappedBy = "items",cascade = CascadeType.ALL) + private List images = new ArrayList<>(); + + private String title; + @Lob + private String intro; + @Enumerated(EnumType.STRING) + private Category category; + + private int price; + + private ItemStatus itemStatus; } diff --git a/src/main/java/com/dku/springstudy/repository/BoardRepository.java b/src/main/java/com/dku/springstudy/repository/ItemsRepository.java similarity index 52% rename from src/main/java/com/dku/springstudy/repository/BoardRepository.java rename to src/main/java/com/dku/springstudy/repository/ItemsRepository.java index 6723a51..aeaf824 100644 --- a/src/main/java/com/dku/springstudy/repository/BoardRepository.java +++ b/src/main/java/com/dku/springstudy/repository/ItemsRepository.java @@ -1,8 +1,8 @@ package com.dku.springstudy.repository; -import com.dku.springstudy.model.Board; +import com.dku.springstudy.model.Items; import org.springframework.data.jpa.repository.JpaRepository; -public interface BoardRepository extends JpaRepository { +public interface ItemsRepository extends JpaRepository { } diff --git a/src/main/java/com/dku/springstudy/service/BoardService.java b/src/main/java/com/dku/springstudy/service/ItemsService.java similarity index 82% rename from src/main/java/com/dku/springstudy/service/BoardService.java rename to src/main/java/com/dku/springstudy/service/ItemsService.java index 34dc78b..0bd4201 100644 --- a/src/main/java/com/dku/springstudy/service/BoardService.java +++ b/src/main/java/com/dku/springstudy/service/ItemsService.java @@ -5,11 +5,11 @@ import com.amazonaws.services.s3.model.DeleteObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; -import com.dku.springstudy.dto.BoardDTO; -import com.dku.springstudy.model.Board; +import com.dku.springstudy.dto.ItemsDTO; +import com.dku.springstudy.model.Items; import com.dku.springstudy.model.Category; import com.dku.springstudy.model.User; -import com.dku.springstudy.repository.BoardRepository; +import com.dku.springstudy.repository.ItemsRepository; import com.dku.springstudy.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -28,27 +28,26 @@ @Transactional(readOnly = true) @RequiredArgsConstructor @Service -public class BoardService { +public class ItemsService { @Value("${spring.cloud.aws.s3.bucket}") private String bucket; private final AmazonS3 amazonS3; - private final BoardRepository boardRepository; + private final ItemsRepository itemsRepository; private final UserRepository userRepository; @Transactional - public void write(BoardDTO boardDTO, String userId) { + public void write(ItemsDTO itemDTO, String userId) { User user = userRepository.findById(userId).orElseThrow(() -> new IllegalStateException("멤버가 없습니다")); - Board board = Board.builder() + Items items = Items.builder() .user(user) - .title(boardDTO.getTitle()) - .price(boardDTO.getPrice()) - .intro(boardDTO.getIntro()) + .title(itemDTO.getTitle()) + .price(itemDTO.getPrice()) + .intro(itemDTO.getIntro()) .category(Category.BEAUTY) .build(); - System.out.println(boardDTO.getIntro()); - boardRepository.save(board); + itemsRepository.save(items); } public List multipleUpload(List multipartFile) { @@ -87,8 +86,8 @@ private String getFileExtension(String fileName) { } } - public List index(){ - List boards = boardRepository.findAll(); - return boards; + public List index(){ + List items = itemsRepository.findAll(); + return items ; } } From 9c47ba1233828d3dc684eb78fdc54eaeb10cd360 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Thu, 2 Feb 2023 10:02:02 +0900 Subject: [PATCH 59/67] =?UTF-8?q?[refactor]:=20user=EA=B4=80=EB=A0=A8=20dt?= =?UTF-8?q?o=EB=8A=94=20user=20=ED=8C=A8=ED=82=A4=EC=A7=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/config/security/jwt/JwtProvider.java | 4 ++-- .../java/com/dku/springstudy/controller/MailController.java | 2 +- .../java/com/dku/springstudy/controller/UserController.java | 1 + .../com/dku/springstudy/dto/{ => user}/LoginRequestDTO.java | 2 +- src/main/java/com/dku/springstudy/dto/{ => user}/MailDTO.java | 2 +- .../com/dku/springstudy/dto/{ => user}/SignUpRequestDTO.java | 2 +- .../com/dku/springstudy/dto/{ => user}/TokensResponseDTO.java | 2 +- .../dto/{ => user}/UserInformationChangeRequestDTO.java | 2 +- .../dto/{ => user}/UserInformationChangeResponseDTO.java | 2 +- .../com/dku/springstudy/dto/{ => user}/UserResponseDTO.java | 2 +- src/main/java/com/dku/springstudy/model/Likes.java | 4 ++-- src/main/java/com/dku/springstudy/service/UserService.java | 2 +- 12 files changed, 14 insertions(+), 13 deletions(-) rename src/main/java/com/dku/springstudy/dto/{ => user}/LoginRequestDTO.java (75%) rename src/main/java/com/dku/springstudy/dto/{ => user}/MailDTO.java (67%) rename src/main/java/com/dku/springstudy/dto/{ => user}/SignUpRequestDTO.java (86%) rename src/main/java/com/dku/springstudy/dto/{ => user}/TokensResponseDTO.java (76%) rename src/main/java/com/dku/springstudy/dto/{ => user}/UserInformationChangeRequestDTO.java (81%) rename src/main/java/com/dku/springstudy/dto/{ => user}/UserInformationChangeResponseDTO.java (81%) rename src/main/java/com/dku/springstudy/dto/{ => user}/UserResponseDTO.java (94%) diff --git a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java index a9f5e88..7ff17cd 100644 --- a/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java +++ b/src/main/java/com/dku/springstudy/config/security/jwt/JwtProvider.java @@ -1,8 +1,8 @@ package com.dku.springstudy.config.security.jwt; import com.dku.springstudy.config.security.RedisDao; -import com.dku.springstudy.dto.TokensResponseDTO; -import com.dku.springstudy.dto.UserResponseDTO; +import com.dku.springstudy.dto.user.TokensResponseDTO; +import com.dku.springstudy.dto.user.UserResponseDTO; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.Claims; diff --git a/src/main/java/com/dku/springstudy/controller/MailController.java b/src/main/java/com/dku/springstudy/controller/MailController.java index e3b59e1..d84aa1f 100644 --- a/src/main/java/com/dku/springstudy/controller/MailController.java +++ b/src/main/java/com/dku/springstudy/controller/MailController.java @@ -1,7 +1,7 @@ package com.dku.springstudy.controller; import com.dku.springstudy.service.MailServiceImpl; -import com.dku.springstudy.dto.MailDTO; +import com.dku.springstudy.dto.user.MailDTO; import com.dku.springstudy.dto.ResponseDTO; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/dku/springstudy/controller/UserController.java b/src/main/java/com/dku/springstudy/controller/UserController.java index 65467d2..37b5e24 100644 --- a/src/main/java/com/dku/springstudy/controller/UserController.java +++ b/src/main/java/com/dku/springstudy/controller/UserController.java @@ -2,6 +2,7 @@ import com.dku.springstudy.config.security.jwt.JwtProvider; import com.dku.springstudy.dto.*; +import com.dku.springstudy.dto.user.*; import com.dku.springstudy.model.User; import com.dku.springstudy.repository.UserRepository; import com.dku.springstudy.service.S3Service; diff --git a/src/main/java/com/dku/springstudy/dto/LoginRequestDTO.java b/src/main/java/com/dku/springstudy/dto/user/LoginRequestDTO.java similarity index 75% rename from src/main/java/com/dku/springstudy/dto/LoginRequestDTO.java rename to src/main/java/com/dku/springstudy/dto/user/LoginRequestDTO.java index 770e65c..861c8d7 100644 --- a/src/main/java/com/dku/springstudy/dto/LoginRequestDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/LoginRequestDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import lombok.Data; diff --git a/src/main/java/com/dku/springstudy/dto/MailDTO.java b/src/main/java/com/dku/springstudy/dto/user/MailDTO.java similarity index 67% rename from src/main/java/com/dku/springstudy/dto/MailDTO.java rename to src/main/java/com/dku/springstudy/dto/user/MailDTO.java index 5c94f97..a177132 100644 --- a/src/main/java/com/dku/springstudy/dto/MailDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/MailDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import lombok.Data; diff --git a/src/main/java/com/dku/springstudy/dto/SignUpRequestDTO.java b/src/main/java/com/dku/springstudy/dto/user/SignUpRequestDTO.java similarity index 86% rename from src/main/java/com/dku/springstudy/dto/SignUpRequestDTO.java rename to src/main/java/com/dku/springstudy/dto/user/SignUpRequestDTO.java index 335fd2c..48d2824 100644 --- a/src/main/java/com/dku/springstudy/dto/SignUpRequestDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/SignUpRequestDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import lombok.Data; diff --git a/src/main/java/com/dku/springstudy/dto/TokensResponseDTO.java b/src/main/java/com/dku/springstudy/dto/user/TokensResponseDTO.java similarity index 76% rename from src/main/java/com/dku/springstudy/dto/TokensResponseDTO.java rename to src/main/java/com/dku/springstudy/dto/user/TokensResponseDTO.java index 9bfcfb2..2f58642 100644 --- a/src/main/java/com/dku/springstudy/dto/TokensResponseDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/TokensResponseDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import lombok.Data; diff --git a/src/main/java/com/dku/springstudy/dto/UserInformationChangeRequestDTO.java b/src/main/java/com/dku/springstudy/dto/user/UserInformationChangeRequestDTO.java similarity index 81% rename from src/main/java/com/dku/springstudy/dto/UserInformationChangeRequestDTO.java rename to src/main/java/com/dku/springstudy/dto/user/UserInformationChangeRequestDTO.java index b9ee59a..70b128f 100644 --- a/src/main/java/com/dku/springstudy/dto/UserInformationChangeRequestDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/UserInformationChangeRequestDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java b/src/main/java/com/dku/springstudy/dto/user/UserInformationChangeResponseDTO.java similarity index 81% rename from src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java rename to src/main/java/com/dku/springstudy/dto/user/UserInformationChangeResponseDTO.java index 0600973..4cbf85e 100644 --- a/src/main/java/com/dku/springstudy/dto/UserInformationChangeResponseDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/UserInformationChangeResponseDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/com/dku/springstudy/dto/UserResponseDTO.java b/src/main/java/com/dku/springstudy/dto/user/UserResponseDTO.java similarity index 94% rename from src/main/java/com/dku/springstudy/dto/UserResponseDTO.java rename to src/main/java/com/dku/springstudy/dto/user/UserResponseDTO.java index a7176aa..b71566c 100644 --- a/src/main/java/com/dku/springstudy/dto/UserResponseDTO.java +++ b/src/main/java/com/dku/springstudy/dto/user/UserResponseDTO.java @@ -1,4 +1,4 @@ -package com.dku.springstudy.dto; +package com.dku.springstudy.dto.user; import com.dku.springstudy.model.Role; import com.dku.springstudy.model.User; diff --git a/src/main/java/com/dku/springstudy/model/Likes.java b/src/main/java/com/dku/springstudy/model/Likes.java index 536e758..143cd25 100644 --- a/src/main/java/com/dku/springstudy/model/Likes.java +++ b/src/main/java/com/dku/springstudy/model/Likes.java @@ -19,6 +19,6 @@ public class Likes extends BaseTimeEntity{ private User user; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "board_id") - private Board board; + @JoinColumn(name = "item_id") + private Items items; } diff --git a/src/main/java/com/dku/springstudy/service/UserService.java b/src/main/java/com/dku/springstudy/service/UserService.java index f1431dc..8c7c950 100644 --- a/src/main/java/com/dku/springstudy/service/UserService.java +++ b/src/main/java/com/dku/springstudy/service/UserService.java @@ -1,7 +1,7 @@ package com.dku.springstudy.service; import com.dku.springstudy.config.security.jwt.JwtProvider; -import com.dku.springstudy.dto.*; +import com.dku.springstudy.dto.user.*; import com.dku.springstudy.model.Role; import com.dku.springstudy.model.User; import com.dku.springstudy.repository.UserRepository; From 930beb3b92a0449e94f22ce436d5174a7d4c6d46 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Thu, 2 Feb 2023 16:26:04 +0900 Subject: [PATCH 60/67] =?UTF-8?q?[feat]:=20JPA=20=EC=96=91=EB=B0=A9?= =?UTF-8?q?=ED=96=A5=20=EA=B4=80=EA=B3=84=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EB=8F=99=EC=8B=9C=20=EC=A0=80=EC=9E=A5=20=EA=B5=AC=ED=98=84(?= =?UTF-8?q?=EC=97=AC=EB=9F=AC=EA=B0=9C=EC=9D=98=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80,=20=EC=83=81=ED=92=88=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ItemController.java | 12 ++- .../com/dku/springstudy/dto/ItemsDTO.java | 1 + .../com/dku/springstudy/model/Images.java | 4 +- .../java/com/dku/springstudy/model/Items.java | 10 +- .../repository/ImageRepository.java | 7 ++ .../dku/springstudy/service/ImageService.java | 94 +++++++++++++++++++ .../dku/springstudy/service/ItemsService.java | 88 ++++------------- 7 files changed, 138 insertions(+), 78 deletions(-) create mode 100644 src/main/java/com/dku/springstudy/repository/ImageRepository.java create mode 100644 src/main/java/com/dku/springstudy/service/ImageService.java diff --git a/src/main/java/com/dku/springstudy/controller/ItemController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java index f10c5fe..2e4620b 100644 --- a/src/main/java/com/dku/springstudy/controller/ItemController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -4,6 +4,7 @@ import com.dku.springstudy.dto.ItemsResponseDTO; import com.dku.springstudy.dto.ResponseDTO; import com.dku.springstudy.model.Items; +import com.dku.springstudy.service.ImageService; import com.dku.springstudy.service.ItemsService; import com.dku.springstudy.service.S3Service; import io.swagger.annotations.ApiOperation; @@ -22,15 +23,16 @@ public class ItemController { private final S3Service s3Service; private final ItemsService itemsService; + private final ImageService imageService; @ApiOperation(value = "게시판 글쓰기", notes = "여러장의 이미지와 제목,가격,카테고리,게시글 내용 값을 받아서 게시판을 작성한다") @PostMapping("/board") public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, - ItemsDTO boardDTO, @RequestPart("file") List file) { - List imgPaths = itemsService.multipleUpload(file); - boardDTO.setImageUrls(imgPaths); - itemsService.write(boardDTO, userId); - return new ResponseDTO<>(HttpStatus.OK.value(), boardDTO); + ItemsDTO itemsDTO, @RequestPart("file") List file) { + + itemsService.itemUpload(itemsDTO, userId); + imageService.multipleUpload(file,userId, itemsDTO); + return new ResponseDTO<>(HttpStatus.OK.value(), itemsDTO); } @ApiOperation(value = "게시판 보기", notes = "사진,제목,가격,장소, 등을 게시판을 통해 보여준다") @GetMapping("/board") diff --git a/src/main/java/com/dku/springstudy/dto/ItemsDTO.java b/src/main/java/com/dku/springstudy/dto/ItemsDTO.java index 0a89a7c..68366bc 100644 --- a/src/main/java/com/dku/springstudy/dto/ItemsDTO.java +++ b/src/main/java/com/dku/springstudy/dto/ItemsDTO.java @@ -10,5 +10,6 @@ public class ItemsDTO { private List imageUrls; private String title; private int price; + private String category; private String intro; } \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/model/Images.java b/src/main/java/com/dku/springstudy/model/Images.java index cda3dd8..5926480 100644 --- a/src/main/java/com/dku/springstudy/model/Images.java +++ b/src/main/java/com/dku/springstudy/model/Images.java @@ -1,12 +1,13 @@ package com.dku.springstudy.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.*; import javax.persistence.*; @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -@Getter +@Getter @Setter @Builder @Entity public class Images extends BaseTimeEntity{ @@ -23,4 +24,5 @@ public class Images extends BaseTimeEntity{ @JoinColumn(name = "item_id") private Items items; + private String url; } diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java index 72a3d22..232cd96 100644 --- a/src/main/java/com/dku/springstudy/model/Items.java +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -1,5 +1,6 @@ package com.dku.springstudy.model; +import com.dku.springstudy.dto.ItemsDTO; import lombok.*; import javax.persistence.*; @@ -22,7 +23,7 @@ public class Items extends BaseTimeEntity { @OneToMany(mappedBy = "items",cascade = CascadeType.ALL) private List likes = new ArrayList<>(); - @OneToMany(mappedBy = "items",cascade = CascadeType.ALL) + @OneToMany(mappedBy = "items", cascade = CascadeType.ALL) private List images = new ArrayList<>(); private String title; @@ -34,5 +35,12 @@ public class Items extends BaseTimeEntity { private int price; + @Enumerated(EnumType.STRING) private ItemStatus itemStatus; + + public void addItemWithImage(Images image){ + images.add(image); + image.setItems(this); + + } } diff --git a/src/main/java/com/dku/springstudy/repository/ImageRepository.java b/src/main/java/com/dku/springstudy/repository/ImageRepository.java new file mode 100644 index 0000000..a7a48df --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/ImageRepository.java @@ -0,0 +1,7 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.model.Images; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ImageRepository extends JpaRepository { +} diff --git a/src/main/java/com/dku/springstudy/service/ImageService.java b/src/main/java/com/dku/springstudy/service/ImageService.java new file mode 100644 index 0000000..deeb418 --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/ImageService.java @@ -0,0 +1,94 @@ +package com.dku.springstudy.service; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.dku.springstudy.dto.ItemsDTO; +import com.dku.springstudy.model.*; +import com.dku.springstudy.repository.ImageRepository; +import com.dku.springstudy.repository.ItemsRepository; +import com.dku.springstudy.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Transactional(readOnly = true) +@RequiredArgsConstructor +@Service +public class ImageService { + @Value("${spring.cloud.aws.s3.bucket}") + private String bucket; + + private final ItemsRepository itemsRepository; + private final ImageRepository imageRepository; + private final AmazonS3 amazonS3; + private final UserRepository userRepository; + @Transactional + public List multipleUpload(List multipartFile, String userId, ItemsDTO itemsDTO) { + List fileNameList = new ArrayList<>(); + + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalStateException("멤버가 없습니다")); + + Items items = Items.builder() + .user(user) + .images(fileNameList) + .title(itemsDTO.getTitle()) + .price(itemsDTO.getPrice()) + .intro(itemsDTO.getIntro()) + .category(Category.valueOf(itemsDTO.getCategory())) + .itemStatus(ItemStatus.SELLING) + .build(); + + multipartFile.forEach(file -> { + String fileName = createFileName(file.getOriginalFilename()); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(file.getSize()); + objectMetadata.setContentType(file.getContentType()); + + Images images = Images.builder() + .user(user) + .url(amazonS3.getUrl(bucket, fileName).toString()) + .build(); + fileNameList.add(images); + items.addItemWithImage(images); + + try (InputStream inputStream = file.getInputStream()) { + amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + } catch (IOException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다."); + } + }); + itemsRepository.save(items); + + return fileNameList; + } + + public void deleteFile(String fileName) { + amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + } + + private String createFileName(String fileName) { + return UUID.randomUUID().toString().concat(getFileExtension(fileName)); + } + + private String getFileExtension(String fileName) { + try { + return fileName.substring(fileName.lastIndexOf(".")); + } catch (StringIndexOutOfBoundsException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다."); + } + } +} diff --git a/src/main/java/com/dku/springstudy/service/ItemsService.java b/src/main/java/com/dku/springstudy/service/ItemsService.java index 0bd4201..b0c1b90 100644 --- a/src/main/java/com/dku/springstudy/service/ItemsService.java +++ b/src/main/java/com/dku/springstudy/service/ItemsService.java @@ -1,93 +1,39 @@ package com.dku.springstudy.service; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; import com.dku.springstudy.dto.ItemsDTO; -import com.dku.springstudy.model.Items; -import com.dku.springstudy.model.Category; -import com.dku.springstudy.model.User; +import com.dku.springstudy.model.*; import com.dku.springstudy.repository.ItemsRepository; import com.dku.springstudy.repository.UserRepository; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.server.ResponseStatusException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; import java.util.List; -import java.util.UUID; - @Transactional(readOnly = true) @RequiredArgsConstructor @Service public class ItemsService { - - @Value("${spring.cloud.aws.s3.bucket}") - private String bucket; - private final AmazonS3 amazonS3; - private final ItemsRepository itemsRepository; private final UserRepository userRepository; - @Transactional - public void write(ItemsDTO itemDTO, String userId) { - User user = userRepository.findById(userId).orElseThrow(() -> new IllegalStateException("멤버가 없습니다")); - Items items = Items.builder() - .user(user) - .title(itemDTO.getTitle()) - .price(itemDTO.getPrice()) - .intro(itemDTO.getIntro()) - .category(Category.BEAUTY) - .build(); - itemsRepository.save(items); - } - - public List multipleUpload(List multipartFile) { - List fileNameList = new ArrayList<>(); - - multipartFile.forEach(file -> { - String fileName = createFileName(file.getOriginalFilename()); - ObjectMetadata objectMetadata = new ObjectMetadata(); - objectMetadata.setContentLength(file.getSize()); - objectMetadata.setContentType(file.getContentType()); - - try (InputStream inputStream = file.getInputStream()) { - amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata) - .withCannedAcl(CannedAccessControlList.PublicRead)); - } catch (IOException e) { - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다."); - } - fileNameList.add(amazonS3.getUrl(bucket, fileName).toString()); - }); - return fileNameList; - } - - public void deleteFile(String fileName) { - amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); - } - - private String createFileName(String fileName) { - return UUID.randomUUID().toString().concat(getFileExtension(fileName)); - } - - private String getFileExtension(String fileName) { - try { - return fileName.substring(fileName.lastIndexOf(".")); - } catch (StringIndexOutOfBoundsException e) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다."); - } - } public List index(){ List items = itemsRepository.findAll(); return items ; } + + public void itemUpload(ItemsDTO itemsDTO, String userId) { + User user = userRepository.findById(userId).orElseThrow(()-> new IllegalStateException("오류 : 없는 사용자 입니다.")); +/** + Items items = Items.builder() + .user(user) + .title(itemsDTO.getTitle()) + .price(itemsDTO.getPrice()) + .intro(itemsDTO.getIntro()) + .category(Category.valueOf(itemsDTO.getCategory())) + .itemStatus(ItemStatus.SELLING) + .build(); + + itemsRepository.save(items); + */ + } } From 2ee487125b3e9f3c85309181146c1bda8dfffeb8 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Thu, 2 Feb 2023 17:11:47 +0900 Subject: [PATCH 61/67] =?UTF-8?q?[feat]:=20enum=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EA=B0=92=20=EC=9D=91=EB=8B=B5(=EC=83=81=ED=92=88=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20API)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dku/springstudy/controller/ItemController.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/dku/springstudy/controller/ItemController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java index 2e4620b..b20589d 100644 --- a/src/main/java/com/dku/springstudy/controller/ItemController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -3,6 +3,7 @@ import com.dku.springstudy.dto.ItemsDTO; import com.dku.springstudy.dto.ItemsResponseDTO; import com.dku.springstudy.dto.ResponseDTO; +import com.dku.springstudy.model.Category; import com.dku.springstudy.model.Items; import com.dku.springstudy.service.ImageService; import com.dku.springstudy.service.ItemsService; @@ -43,4 +44,10 @@ public ResponseDTO index(){ .collect(Collectors.toList()); return new ResponseDTO<>(HttpStatus.OK.value(), result); } + + @ApiOperation(value = "상품 카데고리 보기", notes = "다양한 상품의 카테고리 정보를 제공한다") + @GetMapping("/enum") + public ResponseDTO category(){ + return new ResponseDTO<>(HttpStatus.OK.value(), Category.values()); + } } \ No newline at end of file From a2b1cd6f38c901c66067dff0e09e7fc55ac2c572 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 3 Feb 2023 16:54:59 +0900 Subject: [PATCH 62/67] =?UTF-8?q?[feat]:=20=EC=A2=8B=EC=95=84=EC=9A=94=20A?= =?UTF-8?q?PI=20=EA=B5=AC=ED=98=84(=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20&=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=B7=A8?= =?UTF-8?q?=EC=86=8C=20=EA=B5=AC=ED=98=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/LikesController.java | 24 ++++++++++ .../java/com/dku/springstudy/model/Items.java | 13 ++++++ .../java/com/dku/springstudy/model/Likes.java | 8 ++++ .../repository/LikesRepository.java | 16 +++++++ .../dku/springstudy/service/LikesService.java | 45 +++++++++++++++++++ 5 files changed, 106 insertions(+) create mode 100644 src/main/java/com/dku/springstudy/controller/LikesController.java create mode 100644 src/main/java/com/dku/springstudy/repository/LikesRepository.java create mode 100644 src/main/java/com/dku/springstudy/service/LikesService.java diff --git a/src/main/java/com/dku/springstudy/controller/LikesController.java b/src/main/java/com/dku/springstudy/controller/LikesController.java new file mode 100644 index 0000000..4a4e5d7 --- /dev/null +++ b/src/main/java/com/dku/springstudy/controller/LikesController.java @@ -0,0 +1,24 @@ +package com.dku.springstudy.controller; + +import com.dku.springstudy.dto.ResponseDTO; +import com.dku.springstudy.service.LikesService; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class LikesController { + + private final LikesService likesService; + + @ApiOperation(value = "상품 좋아요 기능", notes = "좋아요 기능 이미 했으면 취소 안했으면 추가를 실행한다") + @GetMapping("/likes/{itemId}") + public ResponseDTO clickLikes(@AuthenticationPrincipal String userId, @PathVariable Long itemId) { + return new ResponseDTO<>(HttpStatus.OK.value(), likesService.clickLikes(userId, itemId)); + } +} diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java index 232cd96..29f0163 100644 --- a/src/main/java/com/dku/springstudy/model/Items.java +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -1,6 +1,7 @@ package com.dku.springstudy.model; import com.dku.springstudy.dto.ItemsDTO; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.*; import javax.persistence.*; @@ -43,4 +44,16 @@ public void addItemWithImage(Images image){ image.setItems(this); } + + public void addLike(Likes likes){ + this.likes.add(likes); + } + + public void deleteLike(Likes likes){ + this.likes.remove(likes); + } + + public int getTotalLikes(){ + return likes.size(); + } } diff --git a/src/main/java/com/dku/springstudy/model/Likes.java b/src/main/java/com/dku/springstudy/model/Likes.java index 143cd25..4324236 100644 --- a/src/main/java/com/dku/springstudy/model/Likes.java +++ b/src/main/java/com/dku/springstudy/model/Likes.java @@ -21,4 +21,12 @@ public class Likes extends BaseTimeEntity{ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "item_id") private Items items; + + public void addLike(){ + this.items.addLike(this); + } + + public void deleteLike(){ + this.items.deleteLike(this); + } } diff --git a/src/main/java/com/dku/springstudy/repository/LikesRepository.java b/src/main/java/com/dku/springstudy/repository/LikesRepository.java new file mode 100644 index 0000000..eeb8468 --- /dev/null +++ b/src/main/java/com/dku/springstudy/repository/LikesRepository.java @@ -0,0 +1,16 @@ +package com.dku.springstudy.repository; + +import com.dku.springstudy.model.Items; +import com.dku.springstudy.model.Likes; +import com.dku.springstudy.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface LikesRepository extends JpaRepository { + + Likes findByItemsAndUser(Items items, User user); + + List findByUser(User user); + +} diff --git a/src/main/java/com/dku/springstudy/service/LikesService.java b/src/main/java/com/dku/springstudy/service/LikesService.java new file mode 100644 index 0000000..9d28e45 --- /dev/null +++ b/src/main/java/com/dku/springstudy/service/LikesService.java @@ -0,0 +1,45 @@ +package com.dku.springstudy.service; + +import com.dku.springstudy.model.Items; +import com.dku.springstudy.model.Likes; +import com.dku.springstudy.model.User; +import com.dku.springstudy.repository.ItemsRepository; +import com.dku.springstudy.repository.LikesRepository; +import com.dku.springstudy.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Transactional(readOnly = true) +@RequiredArgsConstructor +@Service +public class LikesService { + + private final UserRepository userRepository; + private final LikesRepository likesRepository; + private final ItemsRepository itemsRepository; + + @Transactional + public String clickLikes(String userId, Long itemId){ + User user = userRepository.findById(userId).orElseThrow(()->new IllegalStateException("유저 없음 오류")); + Items items = itemsRepository.findById(itemId).orElseThrow(()->new IllegalStateException("아이템 없음 오류")); + + Likes likes = likesRepository.findByItemsAndUser(items, user); + if(likes != null){ + likes.deleteLike(); + likesRepository.delete(likes); + return "좋아요 취소"; + } + else{ + Likes like = Likes.builder() + .user(user) + .items(items) + .build(); + likesRepository.save(like); + like.addLike(); + return "좋아요 완료"; + } + } +} From a2fb7d08234ea39b7c3d08f1a4b474ed20188984 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 3 Feb 2023 18:17:50 +0900 Subject: [PATCH 63/67] =?UTF-8?q?[feat]:=20=EC=83=81=ED=92=88=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=ED=95=98=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ItemController.java | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/dku/springstudy/controller/ItemController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java index b20589d..0732caa 100644 --- a/src/main/java/com/dku/springstudy/controller/ItemController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -5,6 +5,7 @@ import com.dku.springstudy.dto.ResponseDTO; import com.dku.springstudy.model.Category; import com.dku.springstudy.model.Items; +import com.dku.springstudy.repository.ItemsRepository; import com.dku.springstudy.service.ImageService; import com.dku.springstudy.service.ItemsService; import com.dku.springstudy.service.S3Service; @@ -16,6 +17,7 @@ import org.springframework.web.multipart.MultipartFile; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @RestController @@ -24,25 +26,30 @@ public class ItemController { private final S3Service s3Service; private final ItemsService itemsService; + + private final ItemsRepository itemsRepository; private final ImageService imageService; @ApiOperation(value = "게시판 글쓰기", notes = "여러장의 이미지와 제목,가격,카테고리,게시글 내용 값을 받아서 게시판을 작성한다") @PostMapping("/board") - public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, - ItemsDTO itemsDTO, @RequestPart("file") List file) { - - itemsService.itemUpload(itemsDTO, userId); + public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, ItemsDTO itemsDTO, + @RequestPart("file") List file) { imageService.multipleUpload(file,userId, itemsDTO); return new ResponseDTO<>(HttpStatus.OK.value(), itemsDTO); } + + /** + * 화면에 맞는 dto, api스펙, 무한 스크롤 페이징 고민해야 한다 + * @return + */ @ApiOperation(value = "게시판 보기", notes = "사진,제목,가격,장소, 등을 게시판을 통해 보여준다") @GetMapping("/board") public ResponseDTO index(){ - List itemLists = itemsService.index(); - List result = itemLists.stream() - .map(b -> new ItemsResponseDTO(b)) - .collect(Collectors.toList()); - return new ResponseDTO<>(HttpStatus.OK.value(), result); + Items itemLists = itemsService.index(); + //List result = itemLists.stream() + // .map(b -> new ItemsResponseDTO(b)) + // .collect(Collectors.toList()); + return new ResponseDTO<>(HttpStatus.OK.value(), itemLists); } @ApiOperation(value = "상품 카데고리 보기", notes = "다양한 상품의 카테고리 정보를 제공한다") @@ -50,4 +57,11 @@ public ResponseDTO index(){ public ResponseDTO category(){ return new ResponseDTO<>(HttpStatus.OK.value(), Category.values()); } + + @ApiOperation(value = "상품 삭제하기", notes = "게시글에 올린 상품을 삭제할 수 있다") + @DeleteMapping("/board/{itemId}") + public ResponseDTO delete(@AuthenticationPrincipal String userId, @PathVariable Long itemId){ + itemsRepository.deleteById(itemId); + return new ResponseDTO<>(HttpStatus.OK.value(), "삭제 완료"); + } } \ No newline at end of file From ea162899caf7b587ec6d9c821cb7280332879919 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 3 Feb 2023 21:17:58 +0900 Subject: [PATCH 64/67] =?UTF-8?q?[refactor]:=20post=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EC=8B=9C=20=EC=9D=91=EB=8B=B5=EA=B0=92=EC=9D=80=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=20=EC=97=94=ED=8B=B0=ED=8B=B0=EC=9D=98=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EB=94=94=20=EA=B0=92=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dku/springstudy/controller/ItemController.java | 6 +++--- src/main/java/com/dku/springstudy/dto/ItemsDTO.java | 2 ++ src/main/java/com/dku/springstudy/service/ImageService.java | 5 ++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/dku/springstudy/controller/ItemController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java index 0732caa..7880df6 100644 --- a/src/main/java/com/dku/springstudy/controller/ItemController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -30,12 +30,12 @@ public class ItemController { private final ItemsRepository itemsRepository; private final ImageService imageService; - @ApiOperation(value = "게시판 글쓰기", notes = "여러장의 이미지와 제목,가격,카테고리,게시글 내용 값을 받아서 게시판을 작성한다") + @ApiOperation(value = "게시판 글쓰기", notes = "여러장의 이미지와 제목,가격,카테고리,게시글 내용 값을 받아서 게시판을 작성한뒤 게시판 id 반환") @PostMapping("/board") public ResponseDTO uploadFile(@AuthenticationPrincipal String userId, ItemsDTO itemsDTO, @RequestPart("file") List file) { - imageService.multipleUpload(file,userId, itemsDTO); - return new ResponseDTO<>(HttpStatus.OK.value(), itemsDTO); + Long itemId = imageService.multipleUpload(file, userId, itemsDTO); + return new ResponseDTO<>(HttpStatus.OK.value(), itemId); } /** diff --git a/src/main/java/com/dku/springstudy/dto/ItemsDTO.java b/src/main/java/com/dku/springstudy/dto/ItemsDTO.java index 68366bc..2ad9860 100644 --- a/src/main/java/com/dku/springstudy/dto/ItemsDTO.java +++ b/src/main/java/com/dku/springstudy/dto/ItemsDTO.java @@ -7,6 +7,8 @@ @Data public class ItemsDTO { + private Long id; + private List imageUrls; private String title; private int price; diff --git a/src/main/java/com/dku/springstudy/service/ImageService.java b/src/main/java/com/dku/springstudy/service/ImageService.java index deeb418..1272359 100644 --- a/src/main/java/com/dku/springstudy/service/ImageService.java +++ b/src/main/java/com/dku/springstudy/service/ImageService.java @@ -36,7 +36,7 @@ public class ImageService { private final AmazonS3 amazonS3; private final UserRepository userRepository; @Transactional - public List multipleUpload(List multipartFile, String userId, ItemsDTO itemsDTO) { + public Long multipleUpload(List multipartFile, String userId, ItemsDTO itemsDTO) { List fileNameList = new ArrayList<>(); User user = userRepository.findById(userId).orElseThrow(() -> new IllegalStateException("멤버가 없습니다")); @@ -72,8 +72,7 @@ public List multipleUpload(List multipartFile, String use } }); itemsRepository.save(items); - - return fileNameList; + return items.getId(); } public void deleteFile(String fileName) { From bb8bff5558ee3324e8cca18920a6501c4a284215 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 3 Feb 2023 22:05:53 +0900 Subject: [PATCH 65/67] =?UTF-8?q?[feat]:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20=EC=96=B4=EB=A0=A4=EA=B0=9C?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=80=20DB=20=EB=BF=90=EB=A7=8C=20=EC=95=84=EB=8B=88?= =?UTF-8?q?=EB=9D=BC=20S3=EB=B2=84=ED=82=B7=EC=97=90=EB=8F=84=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dku/springstudy/controller/ItemController.java | 4 ++++ .../com/dku/springstudy/service/ImageService.java | 13 +++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/dku/springstudy/controller/ItemController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java index 7880df6..b34947c 100644 --- a/src/main/java/com/dku/springstudy/controller/ItemController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -4,6 +4,7 @@ import com.dku.springstudy.dto.ItemsResponseDTO; import com.dku.springstudy.dto.ResponseDTO; import com.dku.springstudy.model.Category; +import com.dku.springstudy.model.Images; import com.dku.springstudy.model.Items; import com.dku.springstudy.repository.ItemsRepository; import com.dku.springstudy.service.ImageService; @@ -61,6 +62,9 @@ public ResponseDTO category(){ @ApiOperation(value = "상품 삭제하기", notes = "게시글에 올린 상품을 삭제할 수 있다") @DeleteMapping("/board/{itemId}") public ResponseDTO delete(@AuthenticationPrincipal String userId, @PathVariable Long itemId){ + Items items = itemsRepository.findById(itemId).orElseThrow(()->new IllegalStateException("게시글에 올린 상품이 없음")); + List images = items.getImages(); + imageService.deleteFile(images); itemsRepository.deleteById(itemId); return new ResponseDTO<>(HttpStatus.OK.value(), "삭제 완료"); } diff --git a/src/main/java/com/dku/springstudy/service/ImageService.java b/src/main/java/com/dku/springstudy/service/ImageService.java index 1272359..bd10523 100644 --- a/src/main/java/com/dku/springstudy/service/ImageService.java +++ b/src/main/java/com/dku/springstudy/service/ImageService.java @@ -31,6 +31,9 @@ public class ImageService { @Value("${spring.cloud.aws.s3.bucket}") private String bucket; + @Value("${spring.cloud.aws.s3.targetURL}") + private String target; + private final ItemsRepository itemsRepository; private final ImageRepository imageRepository; private final AmazonS3 amazonS3; @@ -75,8 +78,14 @@ public Long multipleUpload(List multipartFile, String userId, Ite return items.getId(); } - public void deleteFile(String fileName) { - amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + public void deleteFile(List fileName) { + fileName.forEach(file-> + { + String url = file.getUrl(); + url = url.replace(target,""); + amazonS3.deleteObject(new DeleteObjectRequest(bucket, url)); + }); + } private String createFileName(String fileName) { From 29258702188606488dc7aabc1c665a78b34096a4 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Fri, 3 Feb 2023 23:53:18 +0900 Subject: [PATCH 66/67] =?UTF-8?q?[feat]:=20=EC=83=81=ED=92=88=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ItemController.java | 16 +++++++----- .../java/com/dku/springstudy/model/Items.java | 9 +++++-- .../repository/ImageRepository.java | 8 ++++++ .../dku/springstudy/service/ImageService.java | 26 +++++++++++++++++++ 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/dku/springstudy/controller/ItemController.java b/src/main/java/com/dku/springstudy/controller/ItemController.java index b34947c..eff8b35 100644 --- a/src/main/java/com/dku/springstudy/controller/ItemController.java +++ b/src/main/java/com/dku/springstudy/controller/ItemController.java @@ -1,7 +1,6 @@ package com.dku.springstudy.controller; import com.dku.springstudy.dto.ItemsDTO; -import com.dku.springstudy.dto.ItemsResponseDTO; import com.dku.springstudy.dto.ResponseDTO; import com.dku.springstudy.model.Category; import com.dku.springstudy.model.Images; @@ -9,7 +8,6 @@ import com.dku.springstudy.repository.ItemsRepository; import com.dku.springstudy.service.ImageService; import com.dku.springstudy.service.ItemsService; -import com.dku.springstudy.service.S3Service; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -18,16 +16,11 @@ import org.springframework.web.multipart.MultipartFile; import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; @RestController @RequiredArgsConstructor public class ItemController { - - private final S3Service s3Service; private final ItemsService itemsService; - private final ItemsRepository itemsRepository; private final ImageService imageService; @@ -68,4 +61,13 @@ public ResponseDTO delete(@AuthenticationPrincipal String userId, @PathVariab itemsRepository.deleteById(itemId); return new ResponseDTO<>(HttpStatus.OK.value(), "삭제 완료"); } + + @ApiOperation(value = "상품정보 수정하기", notes = "상품정보를 수정하며 이미지가 있는 경우 기존의 이미지 파일을 삭제합니다.") + @PatchMapping("/board/{itemId}") + public ResponseDTO update(@AuthenticationPrincipal String userId, ItemsDTO itemsDTO, + @RequestPart("file") List file, @PathVariable Long itemId) { + + imageService.multipleModify(file, userId, itemsDTO, itemId); + return new ResponseDTO<>(HttpStatus.OK.value(), "수정완료"); + } } \ No newline at end of file diff --git a/src/main/java/com/dku/springstudy/model/Items.java b/src/main/java/com/dku/springstudy/model/Items.java index 29f0163..ae31881 100644 --- a/src/main/java/com/dku/springstudy/model/Items.java +++ b/src/main/java/com/dku/springstudy/model/Items.java @@ -1,7 +1,6 @@ package com.dku.springstudy.model; import com.dku.springstudy.dto.ItemsDTO; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.*; import javax.persistence.*; @@ -39,10 +38,16 @@ public class Items extends BaseTimeEntity { @Enumerated(EnumType.STRING) private ItemStatus itemStatus; + public void modifyItems(ItemsDTO itemsDTO) { + this.title = itemsDTO.getTitle(); + this.price = itemsDTO.getPrice(); + this.intro = itemsDTO.getIntro(); + this.category = Category.valueOf(itemsDTO.getCategory()); + } + public void addItemWithImage(Images image){ images.add(image); image.setItems(this); - } public void addLike(Likes likes){ diff --git a/src/main/java/com/dku/springstudy/repository/ImageRepository.java b/src/main/java/com/dku/springstudy/repository/ImageRepository.java index a7a48df..e6aa105 100644 --- a/src/main/java/com/dku/springstudy/repository/ImageRepository.java +++ b/src/main/java/com/dku/springstudy/repository/ImageRepository.java @@ -2,6 +2,14 @@ import com.dku.springstudy.model.Images; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; public interface ImageRepository extends JpaRepository { + + @Transactional + @Modifying + @Query("delete from Images im where im.items.id = :id") + void deleteByItemsId(Long id); } diff --git a/src/main/java/com/dku/springstudy/service/ImageService.java b/src/main/java/com/dku/springstudy/service/ImageService.java index bd10523..a7925e3 100644 --- a/src/main/java/com/dku/springstudy/service/ImageService.java +++ b/src/main/java/com/dku/springstudy/service/ImageService.java @@ -99,4 +99,30 @@ private String getFileExtension(String fileName) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다."); } } + + @Transactional + public void multipleModify(List multipartFile, String userId, ItemsDTO itemsDTO, Long itemId) { + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalStateException("멤버가 없습니다")); + Items items = itemsRepository.findById(itemId).orElseThrow(() -> new IllegalStateException("상품이 없습니다")); + + List beforeImages = items.getImages(); + if (multipartFile.size()!=0) { + deleteFile(beforeImages); + imageRepository.deleteByItemsId(items.getId()); + } + + multipartFile.forEach(file -> { + String fileNameModify = createFileName(file.getOriginalFilename()); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(file.getSize()); + objectMetadata.setContentType(file.getContentType()); + + Images images = Images.builder() + .user(user) + .url(amazonS3.getUrl(bucket, fileNameModify).toString()) + .build(); + items.addItemWithImage(images); + }); + items.modifyItems(itemsDTO); + } } From a52beaea8a68c4e9ca43e79bde945dadcf0977a4 Mon Sep 17 00:00:00 2001 From: SeoJiHyeon Date: Sat, 4 Feb 2023 00:12:05 +0900 Subject: [PATCH 67/67] =?UTF-8?q?[docs]:=20README.md=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e1de20b..ead592a 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,17 @@
+### 3주차 + +> 여러개의 테이블이 얽힌 화면에 맞는 DTO설정 및 API구현 + +
+ ## 개발 기록 - 회원가입 & 로그인 API 구현 ```commit``` : [2d556a0](https://github.com/ji-hyeon97/Spring-JPA-study/commit/2d556a0b00a58f70c7d10b7e15a1170d2d8b27a8) - SMPT 이메일 인증 API 구현 ```commit``` : [3fd9d89](https://github.com/ji-hyeon97/Spring-JPA-study/commit/3fd9d898213aa011d04684e3c5fa40c10f0d1ca9) -- access 토큰 재발급 API 구현 ```commit``` : [6851e06](https://github.com/ji-hyeon97/Spring-JPA-study/commit/6851e06e80ce4e7688d169878cca5806d32592fd) \ No newline at end of file +- access 토큰 재발급 API 구현 ```commit``` : [6851e06](https://github.com/ji-hyeon97/Spring-JPA-study/commit/6851e06e80ce4e7688d169878cca5806d32592fd) +- AWS S3 연동 및 다중 이미지 업로드 API 구현 ```commit``` : [930beb3](https://github.com/ji-hyeon97/Spring-JPA-study/commit/930beb3b92a0449e94f22ce436d5174a7d4c6d46) +- 좋아요 API 구현 ```commit``` : [a2b1cd6](https://github.com/ji-hyeon97/Spring-JPA-study/commit/a2b1cd6f38c901c66067dff0e09e7fc55ac2c572) +- 상품 수정 및 삭제 API 구현 ```commit``` : [2925870](https://github.com/ji-hyeon97/Spring-JPA-study/commit/29258702188606488dc7aabc1c665a78b34096a4) , [a2fb7d0](https://github.com/ji-hyeon97/Spring-JPA-study/commit/a2fb7d08234ea39b7c3d08f1a4b474ed20188984) \ No newline at end of file