Skip to content

Commit

Permalink
Merge pull request #10 from Be9room/feat/9
Browse files Browse the repository at this point in the history
Feat/9 : 방명록 입장 시 랜덤 이름 부여하는 API 구현
  • Loading branch information
thsghdud13 authored Sep 25, 2024
2 parents 63e2ca8 + 983c2e3 commit ac26bba
Show file tree
Hide file tree
Showing 15 changed files with 369 additions and 5 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation group: 'org.webjars', name: 'stomp-websocket', version: '2.3.3-1'
implementation 'org.springframework.boot:spring-boot-starter-validation'
//rabbitMQ
implementation 'org.springframework.boot:spring-boot-starter-amqp'
implementation 'org.springframework.boot:spring-boot-starter-reactor-netty:3.0.0'
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/Be9room/festime/apiPayLoad/ApiResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package Be9room.festime.apiPayLoad;

import Be9room.festime.apiPayLoad.code.BaseCode;
import Be9room.festime.apiPayLoad.code.status.SuccessStatus;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
@JsonPropertyOrder({"isSuccess", "code", "message", "result"})
public class ApiResponse<T> {

@JsonProperty("isSuccess")
private final Boolean isSuccess;
private final String code;
private final String message;
@JsonInclude(JsonInclude.Include.NON_NULL)
private T result;

public static <T> ApiResponse<T> onSuccess(T result){
return new ApiResponse<>(true, SuccessStatus._OK.getCode() , SuccessStatus._OK.getMessage(), result);
}
public static <T> ApiResponse<T> of(BaseCode code, T result){
return new ApiResponse<>(true, code.getReasonHttpStatus().getCode(), code.getReasonHttpStatus().getMessage(), result);
}
public static <T> ApiResponse<T> onFailure(String code, String message, T data){
return new ApiResponse<>(false, code, message,data);
}
}
6 changes: 6 additions & 0 deletions src/main/java/Be9room/festime/apiPayLoad/code/BaseCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package Be9room.festime.apiPayLoad.code;

public interface BaseCode {
public ReasonDTO getReason();
public ReasonDTO getReasonHttpStatus();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package Be9room.festime.apiPayLoad.code;

public interface BaseErrorCode {
public ErrorReasonDTO getReason();
public ErrorReasonDTO getReasonHttpStatus();
}
14 changes: 14 additions & 0 deletions src/main/java/Be9room/festime/apiPayLoad/code/ErrorReasonDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package Be9room.festime.apiPayLoad.code;

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

@Getter
@Builder
public class ErrorReasonDTO {
private HttpStatus httpStatus;
private final boolean isSuccess;
private final String code;
private final String message;
}
14 changes: 14 additions & 0 deletions src/main/java/Be9room/festime/apiPayLoad/code/ReasonDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package Be9room.festime.apiPayLoad.code;

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

@Getter
@Builder
public class ReasonDTO {
private HttpStatus httpStatus;
private final boolean isSuccess;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package Be9room.festime.apiPayLoad.code.status;

import Be9room.festime.apiPayLoad.code.BaseErrorCode;
import Be9room.festime.apiPayLoad.code.ErrorReasonDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum ErrorStatus implements BaseErrorCode {
// 가장 일반적인 응답
_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."),
_BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."),
_UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."),
_FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."),

// 멤버 관려 예외
;
private final HttpStatus httpStatus;
private final String code;
private final String message;

@Override
public ErrorReasonDTO getReason() {
return ErrorReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(false)
.build();
}

@Override
public ErrorReasonDTO getReasonHttpStatus() {
return ErrorReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(false)
.httpStatus(httpStatus)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package Be9room.festime.apiPayLoad.code.status;

import Be9room.festime.apiPayLoad.code.BaseCode;
import Be9room.festime.apiPayLoad.code.ReasonDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum SuccessStatus implements BaseCode {
//일반적인 응답
_OK(HttpStatus.OK, "COMMON200","success"),

//멤버 관련 응답
MEMBER_ENTER(HttpStatus.OK, "MEMBER2001", "member entered")
;

private final HttpStatus httpStatus;
private final String code;
private final String message;

@Override
public ReasonDTO getReason() {
return ReasonDTO.builder()
.isSuccess(true)
.code(code)
.message(message)
.build();
}

@Override
public ReasonDTO getReasonHttpStatus() {
return ReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(true)
.httpStatus(httpStatus)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package Be9room.festime.apiPayLoad.exception;

import Be9room.festime.apiPayLoad.ApiResponse;
import Be9room.festime.apiPayLoad.code.ErrorReasonDTO;
import Be9room.festime.apiPayLoad.code.status.ErrorStatus;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.util.Map;

@Slf4j
@RestControllerAdvice(annotations = {RestController.class})
public class ExceptionAdvice extends ResponseEntityExceptionHandler {


@ExceptionHandler
public ResponseEntity<Object> validation(ConstraintViolationException e, WebRequest request) {
String errorMessage = e.getConstraintViolations().stream()
.map(constraintViolation -> constraintViolation.getMessage())
.findFirst()
.orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생"));

return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY,request);
}


// @Override
// public ResponseEntity<Object> handleMethodArgumentNotValid(
// MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request) {
//
// Map<String, String> errors = new LinkedHashMap<>();
//
// e.getBindingResult().getFieldErrors().stream()
// .forEach(fieldError -> {
// String fieldName = fieldError.getField();
// String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse("");
// errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage);
// });
//
// return handleExceptionInternalArgs(e,HttpHeaders.EMPTY,ErrorStatus.valueOf("_BAD_REQUEST"),request,errors);
// }

@ExceptionHandler
public ResponseEntity<Object> exception(Exception e, WebRequest request) {
e.printStackTrace();

return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(),request, e.getMessage());
}

@ExceptionHandler(value = GeneralException.class)
public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) {
ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus();
return handleExceptionInternal(generalException,errorReasonHttpStatus,null,request);
}

private ResponseEntity<Object> handleExceptionInternal(Exception e, ErrorReasonDTO reason,
HttpHeaders headers, HttpServletRequest request) {

ApiResponse<Object> body = ApiResponse.onFailure(reason.getCode(),reason.getMessage(),null);
// e.printStackTrace();

WebRequest webRequest = new ServletWebRequest(request);
return super.handleExceptionInternal(
e,
body,
headers,
reason.getHttpStatus(),
webRequest
);
}

private ResponseEntity<Object> handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus,
HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) {
ApiResponse<Object> body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint);
return super.handleExceptionInternal(
e,
body,
headers,
status,
request
);
}

private ResponseEntity<Object> handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus,
WebRequest request, Map<String, String> errorArgs) {
ApiResponse<Object> body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs);
return super.handleExceptionInternal(
e,
body,
headers,
errorCommonStatus.getHttpStatus(),
request
);
}

private ResponseEntity<Object> handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus,
HttpHeaders headers, WebRequest request) {
ApiResponse<Object> body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null);
return super.handleExceptionInternal(
e,
body,
headers,
errorCommonStatus.getHttpStatus(),
request
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package Be9room.festime.apiPayLoad.exception;

import Be9room.festime.apiPayLoad.code.BaseErrorCode;
import Be9room.festime.apiPayLoad.code.ErrorReasonDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class GeneralException extends RuntimeException{
private BaseErrorCode code;
public ErrorReasonDTO getErrorReason() {
return this.code.getReason();
}

public ErrorReasonDTO getErrorReasonHttpStatus(){
return this.code.getReasonHttpStatus();
}
}
24 changes: 24 additions & 0 deletions src/main/java/Be9room/festime/common/RandomNameGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package Be9room.festime.common;

import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Component
public class RandomNameGenerator {
List<String> adjective = Arrays.asList(
"노래하는", "졸린", "배고픈", "목마른", "피곤한", "행복한", "신나는", "화려한", "유쾌한" ,
"기대하는", "반짝이는", "특별한", "감동하는", "멋진", "춤추는", "대단한"
);

List<String> objective = Arrays.asList(
"인덕이", "안뇽이"
);
public String generate(){
Collections.shuffle(adjective);
Collections.shuffle(objective);
return adjective.get(0) + " " + objective.get(0);
}
}
31 changes: 31 additions & 0 deletions src/main/java/Be9room/festime/controller/MemberController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package Be9room.festime.controller;

import Be9room.festime.apiPayLoad.ApiResponse;
import Be9room.festime.apiPayLoad.code.status.SuccessStatus;
import Be9room.festime.common.RandomNameGenerator;
import Be9room.festime.dto.MemberDto;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
private final RandomNameGenerator randomNameGenerator;
@GetMapping
public ApiResponse<MemberDto.MemberResponseDto> enter(){

MemberDto.MemberResponseDto memberDto = MemberDto.MemberResponseDto.builder()
.memberName(randomNameGenerator.generate())
.memberId(UUID.randomUUID().toString())
.build();
return ApiResponse.of(SuccessStatus.MEMBER_ENTER, memberDto);
}



}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package Be9room.festime.controller;

import Be9room.festime.dto.MessageDTO;
import Be9room.festime.dto.MessageDto;
import Be9room.festime.enums.MessageType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -19,7 +19,7 @@ public class MessageController {
* @param message
*/
@MessageMapping(value = "/guestbook/enter")
public void enter(MessageDTO message){
public void enter(MessageDto message){
message.setMessageType(MessageType.ENTER.toString());
message.setMessage(message.getMemberName() + "님이 방명록에 참여했어요!");

Expand All @@ -33,7 +33,7 @@ public void enter(MessageDTO message){
* @param message
*/
@MessageMapping(value = "/guestbook/message")
public void message(MessageDTO message){
public void message(MessageDto message){
message.setMessageType(MessageType.MESSAGE.toString());

/* 메세지 저장 부분 */
Expand All @@ -46,7 +46,7 @@ public void message(MessageDTO message){
* @param message
*/
@MessageMapping(value = "/guestbook/leave")
public void leave(MessageDTO message){
public void leave(MessageDto message){
message.setMessageType(MessageType.LEAVE.toString());
message.setMessage(message.getMemberName() + "님이 방명록에서 나가셨어요!");

Expand Down
Loading

0 comments on commit ac26bba

Please sign in to comment.