아래의 필드를 기준으로 중복되면 안 되는 요소를 처리하였습니다.
또한 현재 예시들은 msa 환경에서의 확인 작업으로 진행됨을 알립니다.
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.StringExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@Repository
@RequiredArgsConstructor
public class QuerydslMemberRepositoryImpl implements QuerydslMemberRepository {
private final JPAQueryFactory queryFactory;
/**
* {@inheritDoc}
* */
@Override
public boolean existMemberByNickname(String nickname) {
QMember member = QMember.member;
return Optional.ofNullable(queryFactory
.selectFrom(member).where(member.nickname.eq(nickname)
.and(member.isSoftDelete.isFalse()))
.fetchFirst()).isPresent(); }
/**
* {@inheritDoc}
* */
@Override
public boolean existMemberByPhoneNumber(String phoneNumber) {
QMember member = QMember.member;
return Optional.ofNullable(queryFactory
.selectFrom(member).where(member.phoneNumber.eq(phoneNumber)
.and(member.isSoftDelete.isFalse()))
.fetchFirst()).isPresent();
}
/**
* {@inheritDoc}
* */
@Override
public boolean existMemberByEmail(String email) {
QMember member = QMember.member;
return Optional.ofNullable(queryFactory
.selectFrom(member).where(member.emailAddress.eq(email)
.and(member.isSoftDelete.isFalse()))
.fetchFirst()).isPresent();
}
/**
* {@inheritDoc}
* */
@Override
public boolean existMemberByLoginId(String loginId) {
QMember member = QMember.member;
return Optional.ofNullable(queryFactory
.selectFrom(member).where(member.id.eq(loginId)
.and(member.isSoftDelete.isFalse())).fetchFirst()).isPresent();
}
}
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class QueryMemberServiceImpl implements QueryMemberService {
private final QuerydslMemberRepository querydslMemberRepository;
private final QuerydslMemberRoleRepository querydslMemberRoleRepository;
@Override
public boolean existMemberByNickname(String nickname) {
boolean result = querydslMemberRepository.existMemberByNickname(nickname);
return result;
}
@Override
public boolean existMemberByPhoneNumber(String phoneNumber) {
boolean result = querydslMemberRepository.existMemberByPhoneNumber(phoneNumber);
return result;
}
@Override
public boolean existMemberByEmail(String email) {
boolean result = querydslMemberRepository.existMemberByEmail(email);
return result;
}
@Override
public boolean existMemberByLoginId(String loginId) {
boolean result = querydslMemberRepository.existMemberByLoginId(loginId);
return result;
}
}
true
를 없다면 false
를 돌려준다.[controller]
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.coyote.Response;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequestMapping(value = "/api/service/members")
@RestController
@RequiredArgsConstructor
public class QueryMemberRestController {
private final QueryMemberService queryMemberService;
/**
* 이메일로 중복 여부 확인
* @param email 회원 이메일
* @return 중복여부
* */
@GetMapping("/checkEmail/{email}")
@ResponseStatus(HttpStatus.OK)
public ResponseDto<MemberDuplicateDto> existMemberByEmail(@PathVariable String email){
MemberDuplicateDto response = new MemberDuplicateDto(queryMemberService.existMemberByEmail(email));
return ResponseDto.<MemberDuplicateDto>builder()
.status(HttpStatus.OK)
.success(true)
.data(response)
.build();
}
@GetMapping("/checkNickname/{nickname}")
@ResponseStatus(HttpStatus.OK)
public ResponseDto<MemberDuplicateDto> existMemberBy(@PathVariable String nickname){
MemberDuplicateDto response =new MemberDuplicateDto(queryMemberService.existMemberByNickname(nickname));
return ResponseDto.<MemberDuplicateDto>builder()
.status(HttpStatus.OK)
.success(true)
.data(response)
.build();
}
@GetMapping("/checkPhone/{phone}")
@ResponseStatus(HttpStatus.OK)
public ResponseDto<MemberDuplicateDto> existMemberByPhoneNumber(@PathVariable String phone){
MemberDuplicateDto response =new MemberDuplicateDto(queryMemberService.existMemberByPhoneNumber(phone));
return ResponseDto.<MemberDuplicateDto>builder()
.status(HttpStatus.OK)
.success(true)
.data(response)
.build();
}
@GetMapping("/checkLoginId/{loginId}")
@ResponseStatus(HttpStatus.OK)
public ResponseDto<MemberDuplicateDto> existMemberByLoginId(@PathVariable String loginId){
MemberDuplicateDto data = new MemberDuplicateDto(queryMemberService.existMemberByLoginId(loginId));
return ResponseDto.<MemberDuplicateDto>builder()
.status(HttpStatus.OK)
.success(true)
.data(data)
.build();
}
}
[response dto]
public class MemberDuplicateDto {
private boolean result;
public MemberDuplicateDto(boolean result){
this.result = result;
}
}
import com.yaloostore.front.member.service.inter.QueryMemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.util.Objects;
@Slf4j
@RequiredArgsConstructor
@Service
public class QueryMemberServiceImpl implements QueryMemberService {
private final RestTemplate restTemplate;
private final GatewayConfig config;
private final ObjectMapper objectMapper;
private final static String PREFIX_CHECK_PATH ="/api/service/members/check";
@Override
public MemberDuplicateDto checkNickname(String nickname) {
log.info("nickname : {}", nickname);
HttpEntity entity = getEntity();
URI uri = UriComponentsBuilder.fromUriString(config.getShopUrl())
.path(PREFIX_CHECK_PATH+"Nickname/{nickname}")
.encode()
.build()
.expand(nickname)
.toUri();
ResponseEntity<ResponseDto<MemberDuplicateDto>> response = restTemplate.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<ResponseDto<MemberDuplicateDto>>() {
});
return response.getBody().getData();
}
@Override
public MemberDuplicateDto checkPhoneNumber(String phone) {
log.info("phone : {}", phone);
HttpEntity entity = getEntity();
URI uri = UriComponentsBuilder.fromUriString(config.getShopUrl())
.path(PREFIX_CHECK_PATH+"Phone/{phone}")
.encode()
.build()
.expand(phone)
.toUri();
ResponseEntity<ResponseDto<MemberDuplicateDto>> response = restTemplate.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<ResponseDto<MemberDuplicateDto>>() {
});
return response.getBody().getData();
}
@Override
public MemberDuplicateDto checkEmail(String email) {
log.info("email : {}", email);
HttpEntity entity = getEntity();
URI uri = UriComponentsBuilder.fromUriString(config.getShopUrl())
.path(PREFIX_CHECK_PATH+"Email/{email}")
.encode()
.build()
.expand(email)
.toUri();
ResponseEntity<ResponseDto<MemberDuplicateDto>> response = restTemplate.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<ResponseDto<MemberDuplicateDto>>() {
});
return response.getBody().getData();
}
@Override
public MemberDuplicateDto checkLoginId(String loginId) {
log.info("loginId : {}", loginId);
HttpEntity entity = getEntity();
URI uri = UriComponentsBuilder.fromUriString(config.getShopUrl())
.path(PREFIX_CHECK_PATH+"LoginId/{loginId}")
.encode()
.build()
.expand(loginId)
.toUri();
ResponseEntity<ResponseDto<MemberDuplicateDto>> response = restTemplate.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<ResponseDto<MemberDuplicateDto>>() {
});
return response.getBody().getData();
}
private static HttpEntity getEntity() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity<>(headers);
return entity;
}
}
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 회원정보 수정, 회원가입 시 중복되면 안 되는 필드 확인 작업을 진행합니다.
* */
@RestController
@RequiredArgsConstructor
public class MemberRestController {
private final QueryMemberService queryMemberService;
@GetMapping("/checkNickname/{nickname}")
public MemberDuplicateDto checkNicknameDuplicate(@PathVariable String nickname){
return queryMemberService.checkNickname(nickname);
}
@GetMapping("/checkEmail/{email}")
public MemberDuplicateDto checkEmailDuplicate(@PathVariable String email){
return queryMemberService.checkEmail(email);
}
@GetMapping("/checkPhone/{phone}")
public MemberDuplicateDto checkPhoneDuplicate(@PathVariable String phone){
return queryMemberService.checkPhoneNumber(phone);
}
@GetMapping("/checkLoginId/{loginId}")
public MemberDuplicateDto checkLoginIdDuplicate(@PathVariable String loginId){
return queryMemberService.checkLoginId(loginId);
}
}
[form]
<div class="mb-3 mb-4">
<label for="email" class="form-label text-dark">Email </label>
<div class="row">
<div class="col-9">
<input type="email" id="email" th:name="emailAddress" class="form-control border-1" placeholder="이메일 주소를 입력해주세요." required="">
</div>
<div class="col-3 d-flex justify-content-around">
<button class="btn btn-light" type="button" id="checkEmailBth" onclick="checkEmail()">중복 확인</button>
</div>
</div>
</div>
[javaScript]
function checkPhoneNumber(){
let inputPhoneNumber = document.getElementById("phoneNumber");
let checkPhoneNumberBtn = document.getElementById("checkPhoneNumberBtn");
let phoneNumberValue = inputPhoneNumber.value;
const trimmedPhoneNumber = phoneNumberValue.replace(/-/g, '');
console.log(phoneNumberValue);
console.log(trimmedPhoneNumber);
const url = `/checkPhone/${phoneNumberValue}`;
let phoneRegex = /^01([0|1])\d{4}\d{4}$/;
let emptyRegex = /\s/g;
if(phoneRegex.test(trimmedPhoneNumber) && ! emptyRegex.test(trimmedPhoneNumber)){
fetch(url, {
Accept: "application/json",
method:"GET"
}).then((response) => {
return response.json()
}).then(data => {
if(!data.result){
//사용 가능한 경우 input창은 고치지 못하게 바꾸고 버튼도 누르지 못하게 바꾼다,.
alert('사용 가능한 휴대전화 번호입니다.')
inputPhoneNumber.readOnly=true;
checkPhoneNumberBtn.disabled = true;
}else{
alert('이미 사용 중인 휴대전화 번호입니다.')
}
});
} else{
alert('휴대전화 번호 형식에 맞게 작성해주세요.')
}
}
{
result: true
}
회원가입 페이지
회원 가입시 표현식에 위배되지 않는다면 사용가능하다고 뜸
회원 가입 시 표현식에 위배되는 경우라면 사용불가하다고 뜸