Skip to content

Commit

Permalink
πŸ”Ž[Practice] Week_3_Server_Seminar
Browse files Browse the repository at this point in the history
  • Loading branch information
junggyo1020 committed May 1, 2024
1 parent d9c712f commit 6866e1c
Show file tree
Hide file tree
Showing 25 changed files with 507 additions and 17 deletions.
1 change: 1 addition & 0 deletions week3/seminar3/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'org.postgresql', name: 'postgresql', version: '42.7.3'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.sopt.seminar3.common;

import org.sopt.seminar3.common.dto.ErrorResponse;
import org.sopt.seminar3.exception.NotFoundException;
import org.sopt.seminar3.exception.message.ErrorMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Objects;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(NotFoundException.class)
protected ResponseEntity<ErrorResponse> handleEntityNotFoundException(NotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ErrorResponse.of(ErrorMessage.MEMBER_NOT_FOUND_BY_ID_EXCEPTION));
}

@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ErrorResponse.of(HttpStatus.BAD_REQUEST.value(), Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.seminar3.common.dto;

import org.sopt.seminar3.exception.message.ErrorMessage;

public record ErrorResponse(
int status,
String message
) {
public static ErrorResponse of(int status, String message) {
return new ErrorResponse(status, message);
}

public static ErrorResponse of(ErrorMessage errorMessage) {
return new ErrorResponse(errorMessage.getStatus(), errorMessage.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.seminar3.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration // λͺ¨λ“  μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ ν™˜κ²½μ—μ„œ μ μš©λ˜λŠ” 객체
@EnableJpaAuditing // JPAκ°€ μ—”ν‹°ν‹°λ₯Ό κ°μ‹œν•  수 μžˆλ‹€
public class JpaAuditingConfig {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.sopt.seminar3.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.sopt.seminar3.domain.SuccessMessage;
import org.sopt.seminar3.dto.BlogCreateRequest;
import org.sopt.seminar3.dto.BlogTitleUpdateRequest;
import org.sopt.seminar3.dto.SuccessStatusResponse;
import org.sopt.seminar3.service.BlogService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class BlogController {

private final BlogService blogService;

@PostMapping("/blog")
public ResponseEntity<SuccessStatusResponse> createBlog(
@RequestHeader(name = "memberId") Long memberId, // 멀버 μ‹λ³„μžλŠ” μ€‘μš”ν•œ μ •λ³΄μ΄λ―€λ‘œ 헀더λ₯Ό 톡해 λ°›μ•„μ˜΄
@RequestBody BlogCreateRequest blogCreateRequest
){
return ResponseEntity.status(HttpStatus.CREATED).header(
"Location",
blogService.create(memberId, blogCreateRequest))
.body(SuccessStatusResponse.of(SuccessMessage.BLOG_CREATE_SUCCESS));
}

@PatchMapping("/blog/{blogId}/title")
public ResponseEntity updateBlogTitle(
@PathVariable Long blogId,
@Valid @RequestBody BlogTitleUpdateRequest blogTitleUpdateRequest
){
blogService.updateTitle(blogId, blogTitleUpdateRequest);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.sopt.seminar3.controller;

import lombok.RequiredArgsConstructor;
import org.sopt.seminar3.dto.MemberCreateDto;
import org.sopt.seminar3.dto.MemberFindDto;
import org.sopt.seminar3.service.MemberService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/member")
public class MemberController {

private final MemberService memberService;

@PostMapping
public ResponseEntity createMember(
@RequestBody MemberCreateDto memberCreate
) {
return ResponseEntity.created(URI.create(memberService.createMember(memberCreate))).build();
}

@GetMapping("/{memberId}")
public ResponseEntity<MemberFindDto> findMemberById(
@PathVariable Long memberId
) {
return ResponseEntity.ok(memberService.findMemberById(memberId));
}

@DeleteMapping("/{memberId}")
public ResponseEntity deleteMemberById(
@PathVariable Long memberId
) {
memberService.deleteMemberById(memberId);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.sopt.seminar3.domain;

import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Getter
@MappedSuperclass // 곡톡 정보가 ν•„μš”ν•  λ•Œ λΆ€λͺ¨ ν΄λž˜μŠ€μ— μ„ μ–Έλœ ν•„λ“œλ₯Ό μƒμ†λ°›λŠ” ν΄λž˜μŠ€μ—μ„œ κ·ΈλŒ€λ‘œ μ‚¬μš©
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {

@CreatedDate
private LocalDateTime createdAt;

@LastModifiedDate
private LocalDateTime updatedAt;
}
50 changes: 50 additions & 0 deletions week3/seminar3/src/main/java/org/sopt/seminar3/domain/Blog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.sopt.seminar3.domain;

import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor
public class Blog extends BaseTimeEntity{

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// Member와 BlogλŠ” 1:1 관계
@OneToOne(fetch = FetchType.LAZY)
private Member member;

@Column(length = 200)
private String title;

private String description;

public static Blog create(
Member member,
String title,
String description
) {
return Blog.builder()
.member(member)
.title(title)
.description(description)
.build();
}

@Builder
public Blog(Member member, String title, String description) {
this.member = member;
this.title = title;
this.description = description;
}

public void updateTitle(
String title
){
this.title = title;
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
package com.sopt.practice2.domain;
package org.sopt.seminar3.domain;

import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity // 객체와 ν…Œμ΄λΈ”μ„ λ§€ν•‘ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜(JPAκ°€ κ΄€λ¦¬ν•˜λŠ” Entity)
@Getter // 전체 ν•„λ“œμ— λŒ€ν•œ getter ν•¨μˆ˜λ₯Ό lombok이 제곡
@NoArgsConstructor // κΈ°λ³Έ μƒμ„±μžλ₯Ό μƒμ„±ν•˜λ„λ‘ lombok이 제곡
@Entity
@Getter
@NoArgsConstructor
public class Member {
@Id // μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλŠ” μ—”ν‹°ν‹°λ₯Ό μ‹λ³„μž κ°’μœΌλ‘œ ꡬ뢄
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@Enumerated(EnumType.STRING)
private Part part;

private int age;

public static Member create(String name, Part part, int age) {
return Member.builder()
.name(name)
.part(part)
.age(age)
.build();
}

@Builder
public Member(String name, Part part, int age){
public Member(String name, Part part, int age) {
this.name = name;
this.part = part;
this.age = age;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sopt.practice2.domain;
package org.sopt.seminar3.domain;

public enum Part {

SERVER("SERVER"),
WEB("WEB"),
ANDROID("ANDROID"),
Expand All @@ -17,4 +18,4 @@ public enum Part {
public String getPart() {
return this.part;
}
}
}
23 changes: 23 additions & 0 deletions week3/seminar3/src/main/java/org/sopt/seminar3/domain/Post.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.sopt.seminar3.domain;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor
public class Post extends BaseTimeEntity{

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;

private String content;

// Blog 와 PostλŠ” N:1 관계
@ManyToOne(fetch = FetchType.LAZY)
private Blog blog;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.sopt.seminar3.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum SuccessMessage {

BLOG_CREATE_SUCCESS(HttpStatus.CREATED.value(),"λΈ”λ‘œκ·Έ 생성이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
;
private final int status;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sopt.seminar3.dto;

public record BlogCreateRequest(
String title,
String description
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.seminar3.dto;

import jakarta.validation.constraints.Size;

public record BlogTitleUpdateRequest(
@Size(max=5, message = "λΈ”λ‘œκ·Έ 제λͺ©μ΄ μ΅œλŒ€ κΈ€μž 수(5자)λ₯Ό μ΄ˆκ³Όν–ˆμŠ΅λ‹ˆλ‹€.")
String title
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.seminar3.dto;

import org.sopt.seminar3.domain.Part;

public record MemberCreateDto(
String name,
Part part,
int age
) {
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package com.sopt.practice2.Web.dto;
package org.sopt.seminar3.dto;

import com.sopt.practice2.domain.Member;
import com.sopt.practice2.domain.Part;
import org.sopt.seminar3.domain.Member;
import org.sopt.seminar3.domain.Part;

public record MemberFindDto(
String name,
Part part,
int age
) {

public static MemberFindDto of(
Member member
){
) {
return new MemberFindDto(member.getName(), member.getPart(), member.getAge());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.sopt.seminar3.dto;

import org.sopt.seminar3.domain.SuccessMessage;

public record SuccessStatusResponse(
int status,
String message
) {
public static SuccessStatusResponse of(SuccessMessage successMessage){
return new SuccessStatusResponse(successMessage.getStatus(), successMessage.getMessage());
}
}
Loading

0 comments on commit 6866e1c

Please sign in to comment.