김경록님의 멋사 SpringSecurity 회원가입 유튜브 강의를 듣는중이다. 4강까지의 내용
package kdn.BackEnd.controller;
import kdn.BackEnd.domain.dto.UserJoinRequest;
import kdn.BackEnd.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
@PostMapping("/join")
public ResponseEntity<String> join(@RequestBody UserJoinRequest dto){
userService.join(dto.getUserName(), dto.getPassword());
return ResponseEntity.ok().body("register succeced");
}
}
유저컨트롤러
포스트요청("/join")을 받으면 실행되는 join메서드이다. @RequestBody로 UserJoinRequest dto에 바로 필드들을 넣었고 그 필드들은 userName,password이다. userService.join(dto.getUserName(),dto.getPassword());로 userService객체의 join메서드 파라미터로 쓰였다. 이 join메서드는 다음과 같다.
package kdn.BackEnd.service;
import kdn.BackEnd.domain.User;
import kdn.BackEnd.exception.AppExcepiton;
import kdn.BackEnd.exception.ErrCode;
import kdn.BackEnd.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
public String join(String userName, String pasword){
//userName 중복 체크
userRepository.findByUserName(userName).ifPresent(user -> {
throw new AppException(ErrCode.USERNAME_DUBPLICATED,userName + "은 이미 있습니다.");
});
//중복아닐시 저장
User user = User.builder()
.userName(userName)
.password(pasword)
.build();
userRepository.save(user);
return "SUCCESS";
}
}
join 말그대로 회원가입시 실행되는 함수인데
1)username이 중복될 경우
userRepository.findByUserName메소드로 repository(DB)안에 아까 getUserName()의 데이터를 찾고 만약 존재하면 (ifPresent) 예외를 발생시킨다. AppException은 이따가 알아보겠다. ifPresent는 자바의 Optional클래스의 메서드이다. 메서드명에서도 느낄수 있듯,만약 username이 repository(DB)에 존재한다면 실행된다.
2)username이 중복되지않고 처음 가입된 경우
새로운 User객체를 생성한다. User class에 @Builder 어노테이션을 통해 userName과 password를 user에 넣어주었다.
그리고선 userRepository.save(user);를 통해 user를 userRepository에 저장했다.
package kdn.BackEnd.repository;
import kdn.BackEnd.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User,Long> {
Optional<User> findByUserName(String userName);
}
userRepository의 인터페이스 UserRepository의 모습. JPA를 상속받았다. FindBy**하면 **에 해당되는(혹은 유사한)필드를 테이블에서 찾는다. 또 오늘 안 사실은 만약 두가지 테이블이 있다면 두가지 엔티티클래스와 두가지 레포지토리를 만들어야한다는것. 그리고 그 각각의 테이블과 엔티티,레포지토리는 이름이 corresponding해야한다. User 클래스를 만들고 UserRepository 인터페이스를 만들었다. 그리고 터미널상에서 mysql 명령어를 통해 user_info테이블을 만들었었다. 그리고 스프링과 연결한뒤 post요청을 통해 데이터를 넣었는데 user_info테이블상에서 데이터가 아무것도 안들어가있는 것이다! 그래서 다시 요청을 했는데 ifPresent에서 걸려서 예외처리가 되었다. 뭐지 싶었는데 SHOW TABLES로 확인해보니 user라는 테이블이 새로 생성된 것이었다!! 지피티한테 물어보니
스프링 부트에서는 JPA의 `hibernate.ddl-auto` 설정을 통해 테이블을 자동으로 생성하거나 업데이트하는 기능을 제공합니다. `hibernate.ddl-auto` 속성은 다음과 같이 설정될 수 있습니다:
- `create`: 애플리케이션 실행 시 테이블을 생성합니다. 이미 존재하는 경우, 이전 데이터가 삭제될 수 있습니다.
- `update`: 애플리케이션 실행 시 테이블을 생성하거나 업데이트합니다. 테이블이 이미 존재하면 변경 사항을 적용하려고 시도합니다.
- `validate`: 테이블 구조가 일치하는지만 확인하고 변경하지 않습니다.
- `none`: 자동 생성 또는 업데이트를 하지 않습니다.
기본적으로는 `update` 모드로 설정되어 있습니다. 따라서 데이터베이스에 해당 엔터티와 일치하는 테이블이 없다면 스프링 부트가 테이블을 생성하려고 시도할 것입니다.
다만, 이렇게 자동 생성되는 기능은 개발 및 테스트 환경에서 사용하는 것이 좋으며, 운영 환경에서는 신중하게 다루어야 합니다. 운영 환경에서는 데이터베이스 스키마를 관리하는 방법을 고려해야 합니다.
JPA가 테이블을 만들어 준 것이었다.ㄷㄷ
package kdn.BackEnd.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ExceptionManager {
@ExceptionHandler(AppException.class)
public ResponseEntity<?> appExceptionHandler(AppException e){
return ResponseEntity.status(e.getErrCode().getHttpStatus())
.body((e.getErrCode().name() + " " + e.getMessage()));
}
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<?> runtimeExceptionHandler(RuntimeException e){
return ResponseEntity.status(HttpStatus.CONFLICT)
.body((e.getMessage()));
}
}
ExceptionManger클래스
@RestControllerAdvice 어노테이션이 붙어있다. 그전에 @ControllerAdvice부터 알아보자면,
@ControllerAdvice 어노테이션은 클래스에 선언하면 되고, 모든 @Controller에 대한, 전역으로 발생할 수 있는 예외를 잡아서 처리할 수 있다. @RestControllerAdvice는 @Responsebody처럼 뷰이름을 반환하는것이 아닌,http mesage body를 리턴한다.
appExceptionHandler , runtimeExceptionHandler 메소드에는 @ExceptionHandler가 붙어있는데, 괄호안에 있는 에러.class가 발생할때에 실행된다. 예외가 발생했을때 handling해주는 것이다.
package kdn.BackEnd.exception;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class AppException extends RuntimeException{
private ErrCode errCode;
String message;
}
package kdn.BackEnd.exception;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
@AllArgsConstructor
@Getter
public enum ErrCode {
USERNAME_DUBPLICATED(HttpStatus.CONFLICT, "");
private HttpStatus httpStatus;
private String message;
}
ErrCode 열거체와 AppException 클래스.
package kdn.BackEnd.domain.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class UserJoinRequest {
private String userName;
private String password;
}
UserJoinRequest 클래스. join메서드에서 파라미터로 필요했다.
package kdn.BackEnd.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Builder
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String userName;
private String password;
}
User 클래스. @Builder와 @Entity가 보인다. @Entity는 데이터베이스의 테이블과 매핑된다. 즉 여기에 있는 id,userName,password가 db의 각 필드에 해당된다.
MessageCodesResolver..BindingResult의 reject,rejectvalue내부 (0) | 2024.04.20 |
---|---|
BindingResult (1) | 2024.04.20 |
로그인기능 구현 (0) | 2024.04.20 |
스프링부트 회원가입 구현 (0) | 2024.04.16 |
스프링컨테이너, 스프링빈 등록, 싱글톤 패턴 보장 (1) | 2024.04.07 |
댓글 영역