spring

spring_login-spring

ssmm95 2024. 11. 1. 12:53

테이블 생성할 때

application.yml 파일에서 create로 바꾸고 

 

spring:
  application:
    name: login-spring
  datasource:
    url: jdbc:h2:tcp://localhost/~/testApi
    driver-class-name: org.h2.Driver
    username: sa
  jpa:
    hibernate:
      ddl-auto: create #update
    properties:
      hibernate:
        format_sql: true
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html

logging:
  level:
    org.hibernate.SQL: debug
    org.hibernate.orm.jdbc.bind: trace

package login.login_spring.domain;

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

@Entity
@Setter
@Getter
public class EzenMember {

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

    private String loginId;

    private String name;

    private String password;

    private String grade;
}

 

 

h2 들어가서 확인

 

- 회원 아이디로 조회하는 기능 추가

(interface로 생성)

 

package login.login_spring.reporitory;

import login.login_spring.domain.EzenMember;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<EzenMember, Long> {
    //사용자 아이디로 조회하는 기능 추가
    Optional<EzenMember> findByLoginId(String loginId);
}

 

아래와 같이 콘솔창에 오류가 없으면 된다

 

- memberservice

작성순서 유의

package login.login_spring.service;

import login.login_spring.domain.EzenMember;
import login.login_spring.reporitory.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;


@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository; //final 붙이기

    //회원가입
    public Long join(EzenMember member) {
        validateDuplicateMember(member);
       this.memberRepository.save(member);
      return member.getId();

    }

    //중복회원 검증

    private void validateDuplicateMember(EzenMember member){
        Optional<EzenMember> findMember = memberRepository.findByLoginId(member.getLoginId());
        if(findMember.isPresent()){
            throw new IllegalStateException("이미 존재하는 회원");
        }
    }
    //전체회원 조회
    public List<EzenMember> findMember(){
        return memberRepository.findAll();
    }

    //회원 한 명 조회
    public Optional<EzenMember> findOne(Long memberId) {
        return memberRepository.findById(memberId);
    }

    // 회원삭제
    public void delete(EzenMember member){
        this.memberRepository.deleteById(member.getId());
    }

}

 

 

 

- dto 폴더 생성 후 MemberForm 생성

 

Ezen멤버에서 코드를 긁어오면 된다 

package login.login_spring.dto;

import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class MemberForm {

    @NotEmpty
    private String loginId;

    @NotEmpty
    private String name;

    @NotEmpty(message = "비밀번호는 필수입니다")
    private String password;

    private String grade;
}

 

 


- 회원가입 폼 작성 addMemberForm

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addMemberForm</title>
    <link href="/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div>
        <div class="py-3 text-center max600">
            <h2>회원 가입</h2>
        </div>
        <div class="py-3">
            <h2>회원 정보 입력</h2>
        </div>
        <form>
            <div class="mb-3">
                <label for="userId" class="form-label">로그인 ID</label>
                <input type="text" class="form-control" id="userId" name="userId">
            </div>
            <div class="mb-3">
                <label for="password" class="form-label">비밀번호</label>
                <input type="password" class="form-control" id="password" name="password">
            </div>
            <div class="mb-3">
                <label for="name" class="form-label">이름</label>
                <input type="text" class="form-control" id="name" name="name">
            </div>
            <hr>
            <div class="row">
                <div class="col">
                    <button type="submit" class="btn btn-primary btn-lg w-100">회원가입</button>
                </div>
                <div class="col">
                    <button type="submit" class="btn btn-dark btn-lg w-100">취소</button>
                </div>
            </div>
        </form>
    </div>
</div>
</body>
</html>

 

- 타임리프를 이용해서 addMemberForm 작성

th 를 사용하면 꼭 새로 새로고침▶버튼 클릭

th 를 사용하면 id, name 값이 필요없다 (버튼박스확인)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addMemberForm</title>
    <link href="/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div>
        <div class="py-5 text-center max600">
            <h2>회원 가입</h2>
        </div>
        <h4 class="mb-3">회원 정보 입력</h4>
        <form th:action th:Object="${memberForm}" method="post">
            <div class="mb-3">
                <label th:for="loginId">로그인 ID</label>
                <input type="text" th:field="*{loginId}" class="form-control" >
            </div>
            <div class="mb-3">
                <label th:for="password">비밀번호</label>
                <input type="password" th:field="*{password}" class="form-control" >
            </div>
            <div class="mb-3">
                <label th:for="name">이름</label>
                <input type="text" th:field="*{name}" class="form-control" >
            </div>
            <hr>
            <div class="row">
                <div class="col">
                    <button type="submit" class="btn btn-primary btn-lg w-100">회원가입</button>
                </div>
                <div class="col">
                    <button type="submit" class="btn btn-dark btn-lg w-100">취소</button>
                </div>
            </div>
        </form>
    </div>
</div>
</body>
</html>

 

 

- MemberController 수정 (포스트) 

순서에 유의

package login.login_spring.controller;

import login.login_spring.domain.EzenMember;
import login.login_spring.dto.MemberForm;
import login.login_spring.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    @GetMapping("/add")
    public String createForm(Model model){
        model.addAttribute("memberForm", new MemberForm());
        return "user/addMemberForm";
    }

    @PostMapping("/add")
    public String create(@ModelAttribute("memberForm") MemberForm memberForm) {
        EzenMember ezenMember = new EzenMember();
        ezenMember.setLoginId(memberForm.getLoginId());
        ezenMember.setName(memberForm.getName());
        ezenMember.setPassword(memberForm.getPassword());
        ezenMember.setGrade("User");
        memberService.join(ezenMember);
        return "redirect:/";
    }
}

 

 

- 빈 칸으로 입력하고 회원가입을 클릭해도 데이터 생성이 된다 

 

 

 

- MemberController - @postMapping 부분을 다시 수정한다

(중복검사)

반드시 @Model ~ 앞으로 @valid(jakarta) 입력 후 MemberForm memberForm, BindingResult~ 

if(~ 

까지 입력

    @PostMapping("/add")
    public String create(@Valid @ModelAttribute("memberForm") MemberForm memberForm, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            return "user/addMemberForm";
        }
        EzenMember ezenMember = new EzenMember();
        ezenMember.setLoginId(memberForm.getLoginId());
        ezenMember.setName(memberForm.getName());
        ezenMember.setPassword(memberForm.getPassword());
        ezenMember.setGrade("User");
        memberService.join(ezenMember);
        return "redirect:/";
    }
}

 

- addMemberForm 수정

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addMemberForm</title>
    <link href="/css/bootstrap.css" rel="stylesheet">
    <link href="/css/style.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div>
        <div class="py-5 text-center max600">
            <h2>회원 가입</h2>
        </div>
        <h4 class="mb-3">회원 정보 입력</h4>
        <form th:action th:Object="${memberForm}" method="post">
            <div class="mb-3">
                <label th:for="loginId">로그인 ID</label>
                <input type="text" th:field="*{loginId}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{loginId}" class="field-error"></div>
            </div>
            <div class="mb-3">
                <label th:for="password">비밀번호</label>
                <input type="password" th:field="*{password}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{password}" class="field-error"></div>
            </div>
            <div class="mb-3">
                <label th:for="name">이름</label>
                <input type="text" th:field="*{name}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{name}" class="field-error"></div>
            </div>

 

빈칸 상태로 회원가입을 클릭하면

이렇게 비어있을 수 없다고 표시된다 

 

그리고 중복 아이디를 입력하면 존재하는 회원이라고 뜬다

 

 

설정이 완료되면 

application.yml 들어가서 create > update로 변경 - ▶ 오른쪽 상단 실행

 

- 회원목록 페이지를 만들자

 

 

- home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}">
    <link th:href="@{/css/style.css}" rel="stylesheet">
</head>
<body>
<div class="container max600">
    <div class="py-5 text-center">
        <h2>홈 화면</h2>
    </div>
<div class="row">
    <div class="col">
        <button th:onclick="|location.href='@{/add}'|" type="button" class="btn btn-secondary btn-lg w-100">회원 가입</button>
    </div>
    <div class="col">
        <button th:onclick="|location.href='@{/members}'|" type="button" class="btn btn-dark btn-lg w-100">회원목록</button>
    </div>
    <div class="col">
        <button th:onclick="|location.href='@{/login}'|" type="button" class="btn btn-dark btn-lg w-100">로그인</button>
    </div>
</div>
</div>

<hr>
</body>
</html>

 

- memberController

//회원 목록
    @GetMapping("/members")
    public String listMembers(){
    
        return "admin/memberList";
    }
    
    //admin 폴더 생성 후 memberList 생성

 

 //회원 목록
    @GetMapping("/members")
    public String listMembers(Model model){
        List<EzenMember> members = memberService.findAllMember();
        model.addAttribute("members", members);

        return "admin/memberList";
    }
// 수정

 

- admin 폴더의 memberList.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>회원 목록</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}">
    <link th:href="@{/css/style.css}" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="py-5 text-center">
        <h2>회원 목록</h2>
    </div>
        <table class="table table-striped">
            <thead>
            <tr>
                <th>#</th>
                <th>아이디</th>
                <th>이름</th>
                <th>비밀번호</th>
                <th>등급</th>
                <th>수정</th>
                <th>삭제</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each = "member: ${members}">
                <td th:text="${member.getId()}">#</td>
                <td th:text="${member.getLoginId()}">아이디</td>
                <td th:text="${member.getName()}">이름</td>
                <td th:text="${member.getPassword()}">비밀번호</td>
                <td th:text="${member.getGrade()}">등급</td>
                <td><a th:href="@{/members/{id}/edit (id=${member.id})}" class="btn btn-primary">수정</a></td>
                <td><a th:href="@{/members/{id}/delete (id=${member.id})}" class="btn btn-danger">삭제</a></td>
            </tr>
            </tbody>
        </table>
</div>
</body>
</html>

 

여기까지의 화면

 

ctrl + alt + v  하면 위와같은 복사창이 뜬다 
디렉터리와 이름 새로 설정 후 확인

 

- admin폴더의 updateMemberForm

 

// 매우 중요

<input type="hidden" th:field="*{id}">
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addMemberForm</title>
    <link href="/css/bootstrap.css" rel="stylesheet">
    <link href="/css/style.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div>
        <div class="py-5 text-center max600">
            <h2>회원 수정</h2>
        </div>
        <h4 class="mb-3">회원 정보 입력</h4>
        <form th:action th:Object="${memberForm}" method="post">
            <input type="hidden" th:field="*{id}">
            <div class="mb-3">
                <label th:for="loginId">로그인 ID</label>
                <input type="text" th:field="*{loginId}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{loginId}" class="field-error"></div>
            </div>
            <div class="mb-3">
                <label th:for="password">비밀번호</label>
                <input type="password" th:field="*{password}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{password}" class="field-error"></div>
            </div>
            <div class="mb-3">
                <label th:for="name">이름</label>
                <input type="text" th:field="*{name}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{name}" class="field-error"></div>
            </div>
            <div class="mb-3">
                <label th:for="name">등급</label>
                <input type="text" th:field="*{grade}" class="form-control" th:errorClass="field-error">
                <div th:errors="*{grade}" class="field-error"></div>
            </div>
            <hr>
            <div class="row">
                <div class="col">
                    <button type="submit" class="btn btn-primary btn-lg w-100">회원 수정</button>
                </div>
                <div class="col">
                    <button type="submit" class="btn btn-dark btn-lg w-100">취소</button>
                </div>
            </div>
        </form>
    </div>
</div>
</body>
</html>

 

 

- dto.MemberForm 수정

아래코드 추가

private Long id;
package login.login_spring.dto;

import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class MemberForm {

    private Long id;

    @NotEmpty
    private String loginId;

    @NotEmpty
    private String name;

    @NotEmpty(message = "비밀번호는 필수입니다")
    private String password;

    private String grade;
}

- MemberController

회원 목록 밑에 멤버 멤버 수정 폼 보여주기 

(수정 버튼 클릭했을 때 )

memberService.findOne(memberid);
// ctrl + alt + v 누르면 아래처럼처럼 바뀜 

Optional<EzenMember> findMember = memberService.findOne(memberid);

바뀌기 전

  // 멤버수정 폼(보여주기)
    ///members/{사용자마음대로설정}/edit
    @GetMapping("/members/{memberid}/edit")
    public String updateMemberForm(@PathVariable("memberid") Long memberid, Model model){
        // 단, (@PathVariable("memberid") 와 "/members/{memberid}/edit") 같아야한다
        Optional<EzenMember> findMember = memberService.findOne(memberid);
        EzenMember findMemberGet = findMember.get();

        MemberForm memberForm = new MemberForm();
        memberForm.setId(findMemberGet.getId());
        memberForm.setLoginId(findMemberGet.getLoginId());
        memberForm.setName(findMemberGet.getName());
        memberForm.setPassword(findMemberGet.getPassword());
        memberForm.setGrade(findMemberGet.getGrade());
        model.addAttribute("memberform", memberForm);

    }

바뀐 후 

//회원 목록
    @GetMapping("/members")
    public String listMembers(Model model){
        List<EzenMember> members = memberService.findAllMember();
        model.addAttribute("members", members);

        return "admin/memberList";
    }


    // 멤버수정 폼(보여주기)
    ///members/{사용자마음대로설정}/edit
    @GetMapping("/members/{memberid}/edit")
    public String updateMemberForm(@PathVariable("memberid") Long memberid, Model model){
        Optional<EzenMember> findMember = memberService.findOne(memberid);
        EzenMember findMemberGet = findMember.get();
        MemberForm memberForm = new MemberForm();
        memberForm.setId(findMemberGet.getId());
        memberForm.setLoginId(findMemberGet.getLoginId());
        memberForm.setName(findMemberGet.getName());
        memberForm.setPassword(findMemberGet.getPassword());
        memberForm.setGrade(findMemberGet.getGrade());
        model.addAttribute("memberForm", memberForm);
        return "admin/updateMemberForm";

    }


수정버튼까지 나왔다

 

여기서 등급을 user 가 아니라 admin으로 변경입력 후 회원수정 넣었을 때 바뀌게 해보자

 

- MemberController 에 아래의 코드를 입력

    // 멤버수정 (저장)
   @PostMapping("/members/{memberid}/edit")
    public String updateMember(@ModelAttribute("memberForm") MemberForm form){

        EzenMember ezenMember = new EzenMember();
        ezenMember.setId(form.getId());
        ezenMember.setLoginId(form.getLoginId());
        ezenMember.setName(form.getName());
        ezenMember.setPassword(form.getPassword());
        ezenMember.setGrade(form.getGrade());

        memberService.save(ezenMember);
        return "redirect:/members";

        //prg 패턴

   }
    public Long save(EzenMember member) {

        this.memberRepository.save(member);
        return member.getId();

    }
@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository; //final 붙이기

    //회원가입
    public Long join(EzenMember member) {
        validateDuplicateMember(member);
       this.memberRepository.save(member);
      return member.getId();

    }

    public Long save(EzenMember member) {

        this.memberRepository.save(member);
        return member.getId();

    }


    private void validateDuplicateMember(EzenMember member){
        Optional<EzenMember> findMember = memberRepository.findByLoginId(member.getLoginId());
        if(findMember.isPresent()){
            throw new IllegalStateException("이미 존재하는 회원");

 

 

수정이된다

 

 

- 수정이 될 때 비밀번호 입력 안 해도 수정완료가 되는데 

수정할 때 비밀번호를 입력하지 않으면 수정이 불가하게 만들어보자

- memberController

 // 멤버수정 (저장)
   @PostMapping("/members/{memberid}/edit")
    public String updateMember(@Valid @ModelAttribute("memberForm") MemberForm form
    , BindingResult bindingResult){

        if(bindingResult.hasErrors()){
            return "admin/updateMemberForm";
        }

        EzenMember ezenMember = new EzenMember();
        ezenMember.setId(form.getId());
        ezenMember.setLoginId(form.getLoginId());
        ezenMember.setName(form.getName());
        ezenMember.setPassword(form.getPassword());
        ezenMember.setGrade(form.getGrade());

 

 

- updateMemberForm

 

비밀번호 div - input 에 아래코드 입력

th:placeholder="*{password}

th:placeholder="'힌트 : 비밀번호는: '+ *{password} +'입니다'"
 <div class="mb-3">
                <label th:for="password">비밀번호</label>
                <input type="password" th:field="*{password}" class="form-control" th:errorClass="field-error" th:placeholder="*{password}">
                <div th:errors="*{password}" class="field-error" ></div>
            </div>

 

 


 

- 회원목록에서 회원 삭제버튼 클릭하면 삭제 후 회원목록 페이지가 뜨게 해보자

 

- memberController

 

- memberList에 있는 주소값을 가져온다

<td><a th:href="@{/members/{id}/delete (id=${member.id})}" class="btn btn-danger">삭제</a></td>

/members/{id}/delete 
이 부분
// 멤버 삭제
    @GetMapping ("/members/{memberid}/delete")
    public String delete(@PathVariable("memberid") Long memberid) {
        Optional<EzenMember> findMember = memberService.findOne(memberid);

        if(findMember.isPresent()){
            EzenMember deleteMember = findMember.get();
            memberService.delete(deleteMember);
        }
        return "redirect:/members";
    }
EzenMember findMember = memberService.findOne(memberid);

ctrl alt v 누르면 

Optional<EzenMember> findMember = memberService.findOne(memberid);


삭제 잘 된다 

'spring' 카테고리의 다른 글

SPRING_Optinal  (0) 2024.11.22
spring_application.yml  (0) 2024.11.01
spring_IntellJ 트리식 구조로 프로젝트 패키지 보기  (0) 2024.10.31
spring_인텔리제이에서 부트스트랩 적용하기  (0) 2024.10.31
spring_home  (0) 2024.10.30