728x90
반응형
domain/Member.java
package hooyn.todo.domain;
import lombok.*;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.util.UUID;
@Entity //bean 등록
@Getter @Setter //lombok의 getter와 setter를 만들어주는 annotation
@NoArgsConstructor(access = AccessLevel.PROTECTED) //무분별한 객체 생성을 막기 위해
public class Member {
@Id @GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID uuid; //UUID를 랜덤으로 받아서 자동 설정
private String userNM; //사용자 이름
private String userID; //사용자 ID
private String userPW; //사용자 PW
/*
Todo mapping //추후에 Todo 도메인 제작 후 매핑 예정
Memo mapping //추후에 Memo 도메인 제작 후 매핑 예정
*/
public Member(String userNM, String userID, String userPW) { //생성자
this.userNM = userNM;
this.userID = userID;
this.userPW = userPW;
}
/**
* 비밀번호 암호화
*/
public void encodePassword(PasswordEncoder passwordEncoder){
this.userPW = passwordEncoder.encode(userPW); //비밀번호를 암호화 하기 위한 로직
}
/**
* 비밀번호 확인 (복호화)
*/
public boolean matchPassword(PasswordEncoder passwordEncoder, String password){
return passwordEncoder.matches(password, getUserPW()); //비밀번호를 확인하기 위한 로직
}
}
/repository/MemberRepository.java
package hooyn.todo.repository;
import com.querydsl.jpa.impl.JPAQueryFactory;
import hooyn.todo.domain.Member;
import hooyn.todo.domain.QMember;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.UUID;
@Repository
@RequiredArgsConstructor //private final에 생성자를 통한 의존성 주입을 해준다.
public class MemberRepository {
private final EntityManager em;
private final JPAQueryFactory queryFactory;
/* [회원 정보 저장] */
public UUID save(Member member){
em.persist(member);
return member.getUuid();
}
/* [회원 엔티티 조회] */
public Member findOne(String uuid){
return em.find(Member.class, UUID.fromString(uuid));
}
/* [사용자 아이디에 따른 회원 조회] */
public Member findByUserId(String userID){ //queryDSL을 사용
return queryFactory //queryDSL 사용
.selectFrom(QMember.member)
.where(QMember.member.userID.eq(userID))
.fetchOne();
}
}
/service/MemberService.java
package hooyn.todo.service;
import hooyn.todo.domain.Member;
import hooyn.todo.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
/**
* 회원 가입
*/
@Transactional
public UUID join(String userNM, String userID, String userPW){
Member member = new Member(userNM, userID, userPW);
member.encodePassword(passwordEncoder);
return memberRepository.save(member);
}
/**
* 아이디에 따른 회원 조회
*/
@Transactional(readOnly = true)
public Member findUser(String userID){
return memberRepository.findByUserId(userID);
}
/**
* 아이디 중복 확인
*/
@Transactional(readOnly = true)
public boolean checkDuplicatedID(String userID){
Member member = memberRepository.findByUserId(userID);
if(member!=null){
return false; //아이디로 검색되는 회원이 있다면 중복(false)
} else return true;
}
/**
* 비밀번호 제약조건 확인
*/
public boolean checkPasswordConstraint(String userPW){
Pattern pattern = Pattern.compile("^(?=.*[a-zA-Z])(?=.*\\d).{8,20}$");
return pattern.matcher(userPW).matches();
}
}
/api/request/SignInRequest.java -> MemberController에서 사용하기 위해 생성
package hooyn.todo.api.request;
import lombok.Getter;
@Getter
public class SignInRequest { //로그인 할 때 필요한 RequestBody값 설정
private String userID;
private String userPW;
}
/api/request/SignupRequest.java -> MemberController에서 사용하기 위해 생성
/api/response/Resp
package hooyn.todo.api.request;
import lombok.Getter;
@Getter
public class SignUpRequest { //회원가입 할 때 필요한 RequestBody값 설정
private String userNM;
private String userID;
private String userPW;
}
onse.java -> 전체 응답을 보내기 위해 생성
package hooyn.todo.api.response;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Response<T> {
private boolean isSuccess; //통신 성공 여부
private int statusCode; //통신 상태 코드
private T data; //응답 데이터
private String message; //응답 메시지
}
/api/controller/MemberController
package hooyn.todo.api.controller;
import hooyn.todo.api.request.SignInRequest;
import hooyn.todo.api.request.SignUpRequest;
import hooyn.todo.api.response.Response;
import hooyn.todo.domain.Member;
import hooyn.todo.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
private final PasswordEncoder passwordEncoder;
@PostMapping("/member/signup")
public Response signUp(@RequestBody SignUpRequest request){
boolean checkID = memberService.checkDuplicatedID(request.getUserID());
if(checkID){
if(memberService.checkPasswordConstraint(request.getUserPW())){
UUID data = memberService.join(request.getUserNM(), request.getUserID(), request.getUserPW());
return new Response(true, HttpStatus.OK.value(), data, "회원가입이 정상적으로 처리되었습니다.");
} else {
// 302 에러
return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호는 영문과 숫자포함 8-20자리입니다.");
}
} else {
// 301 에러
return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "이미 사용중인 아이디 입니다.");
}
}
@PostMapping("/member/signin")
public Response signUp(@RequestBody SignInRequest request){
Member member = memberService.findUser(request.getUserID());
if(member!=null){
if(member.matchPassword(passwordEncoder, request.getUserPW())){
return new Response(true, HttpStatus.OK.value(), member.getUuid(), "로그인 되었습니다.");
} else {
// 302 에러
return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호가 일치하지 않습니다.");
}
} else {
// 301 에러
return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 아이디입니다.");
}
}
}
*** QueryDSL을 사용하기 위한 추가 설정 ***
1. Bean 등록
package gachonUniv.dormitory;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import javax.persistence.EntityManager;
@SpringBootApplication
public class DormitoryApplication {
public static void main(String[] args) {
SpringApplication.run(DormitoryApplication.class, args);
}
//queryDSL을 사용하기 위해 JPAQueryFactory 빈 등록
@Bean
JPAQueryFactory jpaQueryFactory(EntityManager em){
return new JPAQueryFactory(em);
}
}
2. QueryDSL compile하여 Q객체 생성 (새로운 도메인 클래스를 생성할 때 실행시켜주어 Q객체를 생성해야합니다.)
QMember가 생긴것을 확인 할 수 있습니다. 이 상태가 되면 QueryDSL을 통해 Query가 가능합니다.
결론
Member에 해당하는 API를 설계해보았습니다. 다음 포스트에서는 테스트를 작성해보겠습니다.
오늘 구현하면서 배운 점은 자바 정규 표현식을 배울 수 있었습니다.
비밀번호 제약조건 로직을 자바 정규 표현식을 통해 구현을 했습니다.
728x90
반응형
'Project > Todo' 카테고리의 다른 글
[AWS EC2 ubuntu] 서버 초기 설정, MySQL 설정 (0) | 2022.07.12 |
---|---|
[AWS EC2 ubuntu] WinSCP와 PuTTY를 이용해서 EC2 인스턴스 접속 (0) | 2022.07.11 |
[AWS EC2 ubuntu] 인스턴스 생성과 보안 그룹 설정 (0) | 2022.07.10 |
[Spring Boot] 프로젝트 만들기 - spring initializr, build.gradle, application.properties (0) | 2022.07.07 |
[기획 및 설계] 프로젝트 테이블 설계 및 예상 API (0) | 2022.07.07 |