250x250
06-26 09:54
관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[Spring boot] 회원가입 기록 AWS(EC2, MySql) - JPA - Thymeleaf 본문

웹/Spring Boot

[Spring boot] 회원가입 기록 AWS(EC2, MySql) - JPA - Thymeleaf

막무가내막내 2020. 4. 16. 20:35
300x250
SMALL

 

 

스프링부트에서는 회원가입할때 스프링 시큐리티라고 보안관련 암호화하는 방법을 사용하나보다. 읽어보긴 했지만 적용하기엔 저같은 초심자한텐 무리이므로 나중에 해보도록 하겠습니다.

 

ajax 통신을 사용하여 회원가입 로직을 구현해 본 것을 기록해볼려고 합니다.

차근차근 첨부터 공부한게 아니여서 실습으로 배우면서 하는거라 이상한점이 있어도 양해 부탁드립니다. ㅎㅎ

막무가내 프로그래밍입니다. ㅎㅎ

 

[프로젝트 구조]

 

[컨트롤러]

map 으로 받을 때는 @ResponseBody 붙여주도록 하자.

package com.mtjin.itarticle.controller;

import com.mtjin.itarticle.UserDto;
import com.mtjin.itarticle.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Controller
@AllArgsConstructor
public class LoginController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView goLogin( HttpServletRequest request) {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/login");
        return mv;
    }

    //Map 형태 ResponseBody 어노테이션 필요 객체 Body로 받아야함
    @ResponseBody
    @RequestMapping(value = "/do_register", method = RequestMethod.POST)
    public Map<String, String> doRegister(@ModelAttribute(name = "userDto") UserDto userDto) {
        System.out.println(userDto.toString());
        Map<String, String> map = new HashMap<>();
        try {
            map.put("email", "true");
            map.put("name", "true");
            if (userService.isExistEmail(userDto)) {
                map.put("email", "false");
                map.put("success", "false");
            } else if (userService.isExistName(userDto)) {
                map.put("name", "false");
                map.put("success", "false");
            } else {
                userService.saveUser(userDto);
                map.put("success", "true");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    @ResponseBody
    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public ModelAndView goRegister() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/register");
        return mv;
    }

    @RequestMapping(value = "/forgot", method = RequestMethod.GET)
    public ModelAndView goForgot() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/forgot");
        return mv;
    }

    @RequestMapping(value = "/reset", method = RequestMethod.GET)
    public ModelAndView goReset() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/reset");
        return mv;
    }
}

 

 

[레포지토리]

이메일, 이름이 DB에 있는지 확인하는 함수 추가 (JpaRepository 의 기능을 사용 -> find~ )

되게 좋은 것 같습니다. 안드로이드의 Room 과 좀 비슷한 것 같습니다.

서비스에서 사용하는 save의 경우는 ORM으로 맵핑되서 저장되는데 Reposiory에 구현안해놔도 처음부터 사용이 가능하다. 이것또한 JPA의 기능..

package com.mtjin.itarticle.domain.repository;

import com.mtjin.itarticle.domain.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;


public interface UserRepository extends JpaRepository<UserEntity, Long> {

    List<UserEntity> findUserEntityByEmail(String email);

    List<UserEntity> findUserEntityByName(String name);
}

 

 

[서비스]

DTO를 건네받아 레포지토리에 엔티티로 맵핑하여 사용

package com.mtjin.itarticle.service;

import com.mtjin.itarticle.UserDto;
import com.mtjin.itarticle.domain.repository.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@AllArgsConstructor
@Service
public class UserService {
    private UserRepository userRepository;

    @Transactional
    public Long saveUser(UserDto userDto) {
        return userRepository.save(userDto.toEntity()).getId();
    }

    @Transactional
    public boolean isExistEmail(UserDto userDto) {
        return !userRepository.findUserEntityByEmail(userDto.toEntity().getEmail()).isEmpty();
    }

    @Transactional
    public boolean isExistName(UserDto userDto) {
        return !userRepository.findUserEntityByName(userDto.toEntity().getName()).isEmpty();
    }

}

 

 

 

[register.js]

회원가입 성공 시 로그인 페이지로 리다이렉트를 합니다.

이미 아이디나 이메일 있을 경우 알림창 띄워줍니다. 이것 때문에 ajax 통신 사용 

정규식 검사도 실행 (밑 코드에는 없습니다)

function ajax_register() {
    var register_form = $("#register_form").serialize();
    alert("Aaaa");
    $.ajax({
        type: 'POST',
        url: 'do_register',
        data: register_form,
        dataType: 'json',
        success: function (json) {
            if (json.success === "true") {
                Swal.fire({
                    title: "Success!",
                    text: "Congratulations, Register Success",
                    icon: "success"
                }).then(function() {
                    // 성공시 확인 버튼 클릭 후 login 페이지로 리다이렉트
                    window.location.href = "login";
                });
            } else {
                if (json.name === "false") {
                    //이미 존재하는 이름
                    Swal.fire({
                        title: 'Fail', /*상단 타이틀*/
                        text: 'Name is already Exist', /*내용*/
                        icon: 'error' /*아이콘 타입*/
                    });
                } else if (json.email === "false") {
                    //이미 존재하는 이메일
                    Swal.fire({
                        title: 'Fail', /*상단 타이틀*/
                        text: 'Email is already Exist', /*내용*/
                        icon: 'error' /*아이콘 타입*/
                    });
                } else {
                    Swal.fire({
                        title: 'Fail', /*상단 타이틀*/
                        text: 'Fail To Register', /*내용*/
                        icon: 'error'/*아이콘 타입*/
                    });
                }
            }
        }
    });
}

 

 

 

 

[뷰 타임리프]

name 모델(UserDto)과 맞춰주도록 합니다.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="author" content="Kodinger">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>My Login Page &mdash; Bootstrap 4 Login Page Snippet</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/static/css/my-login.css">
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
    <!-- Optional: include a polyfill for ES6 Promises for IE11 -->
    <script src="https://cdn.jsdelivr.net/npm/promise-polyfill"></script>
    <!--jquery-->
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
</head>
<body class="my-login-page">
<section class="h-100">
    <div class="container h-100">
        <div class="row justify-content-md-center h-100">
            <div class="card-wrapper">
                <div class="brand">
                    <img src="/static/img/logo.jpg" alt="bootstrap 4 login page">
                </div>
                <div class="card fat">
                    <div class="card-body">
                        <h4 class="card-title">Register</h4>
                        <form id="register_form" method="POST"
                              class="my-login-validation" novalidate="">
                            <div class="form-group">
                                <label for="name">Name</label>
                                <input th:name="name" id="name" type="text" class="form-control" name="name" required
                                       autofocus>
                                <div class="invalid-feedback">
                                    What's your name?
                                </div>
                            </div>

                            <div class="form-group">
                                <label for="email">E-Mail Address</label>
                                <input th:name="email" id="email" type="email" class="form-control" name="email"
                                       required>
                                <div class="invalid-feedback">
                                    Your email is invalid
                                </div>
                            </div>

                            <div class="form-group">
                                <label for="password">Password</label>
                                <input th:name="password" id="password" type="password" class="form-control"
                                       name="password" required data-eye>
                                <div class="invalid-feedback">
                                    Password is required
                                </div>
                            </div>

                            <div class="form-group">
                                <div class="custom-checkbox custom-control">
                                    <input type="checkbox" name="agree" id="agree" class="custom-control-input"
                                           required="">
                                    <label for="agree" class="custom-control-label">I agree to the <a href="#">Terms and
                                        Conditions</a></label>
                                    <div class="invalid-feedback">
                                        You must agree with our Terms and Conditions
                                    </div>
                                </div>
                            </div>

                            <div class="form-group m-0">
                                <button type="button" onclick="return ajax_register()" id="register_btn"
                                        class="btn btn-primary btn-block">
                                    Register
                                </button>
                            </div>
                            <div class="mt-4 text-center">
                                Already have an account? <a th:href="@{'/login'}">Login</a>
                            </div>
                        </form>
                    </div>
                </div>
                <div class="footer">
                    Copyright &copy; 2020 &mdash; ITARTICLE
                </div>
            </div>
        </div>
    </div>
</section>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
        integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
        crossorigin="anonymous"></script>
<script src="/static/js/my-login.js"></script>
<script src="/static/js/login/register.js"></script>
</body>
</html>

 

 

 

 

 

[화면]

 

 

 

300x250
LIST
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
0 Comments
댓글쓰기 폼