본 포스팅의 예제는 STS 또는 Eclipse를 사용하지 않고 Intellij를 통해 구현하고 있습니다.
그래서 기존의 STS(Spring Tool Studio)에서 생성된 Spring 프로젝트의 스프링 관련 설정 파일명과
프로젝트 구조가 약간 다를 수 있습니다.Intellij 스프링 mvc 프로젝트 생성 포스팅을 참고해주시면 감사하겠습니다.
Spring-MVC 기본 개념 및 테스트 예제 관련 포스팅 링크
순서 | 포스팅 제목 |
1 | Intellij에서 Spring MVC Project 생성하기 |
2 | Spring MVC - MariaDB 연결테스트 |
3 | Spring MVC - Mybatis 설정 및 테스트 |
4 | SpringMVC 구조 |
5 | SpringMVC + Mybatis |
6 | Spring MVC Controller 작성 연습 |
7 | Spring Interceptor |
Spring-MVC 게시판 예제 이전 포스팅 링크
1. 내 프로필 페이지 구현 하기
1.1 내 프로필 페이지 영속 계층(Persistence Tier) 구현 하기
src/기본패키지/user/persistence 패키지 안에 UserDAO 인터페이스와 UserDAOImpl 클래스 파일 두개에 아래와 같이 내용을 추가 해주세요.
// 회원정보 조회
public UserVo getUser(String user_id);
// 회원정보 수정
public void updateUserInfo(UserVo param);
// 회원정보 탈퇴
public void deleteUserInfoByUserNo(UserVo param);
// 회원정보 조회
public UserVo getUser(String user_id) {
return sqlSession.selectOne(NAMESPACE + ".getUser", user_id);
}
// 회원정보 수정
@Override
@LogException
public void updateUserInfo(UserVo param) {
sqlSession.update(NAMESPACE + ".updateUserInfo", param);
}
// 회원정보 탈퇴
@Override
@LogException
public void deleteUserInfoByUserNo(UserVo param) {
sqlSession.update(NAMESPACE + ".deleteUserInfoByUserNo", param);
}
/resources/mappers/user/ 패키지 안에 UserSQLMapper.xml 파일 안에 아래와 같이 내용을 추가해주세요.
<!-- 회원정보 조회 -->
<select id="getUser" resultType="UserVo">
select *
from eden_user
WHERE user_id = #{user_id}
</select>
<!-- 회원정보 수정 -->
<update id="updateUserInfo">
update eden_user
SET question_no = #{question_no},
user_nickname = #{user_nickname},
user_phone = #{user_phone},
user_email = #{user_email},
user_findAnswer = #{user_findAnswer}
where user_id = #{user_id}
</update>
<!-- 회원정보 탈퇴 -->
<update id="deleteUserInfoByUserNo">
UPDATE eden_user
SET user_status = 'Inactive'
WHERE user_no = #{user_no}
AND user_pw = #{user_pw}
</update>
1.2 내 프로필 페이지 비지니스 계층 (Business Tier) 구현
src/기본패키지/user/service 패키지 안에 UserService 인터페이스와 UserServiceImpl 클래스 파일에 아래와 같이 내용을 추가 해주세요
// 회원정보 조회
public UserVo getUser(String user_id);
// 회원정보 업데이트
public void updateUserInfo(UserVo param);
// 회원정보 탈퇴
public void deleteUserInfoByUserNo(UserVo param);
// 회원정보 조회
public UserVo getUser(String user_id) {
return userDAO.getUser(user_id);
}
// 회원정보 수정
@Override
@LogException
public void updateUserInfo(UserVo param) {
userDAO.updateUserInfo(param);
}
// 회원정보 탈퇴
@Override
@LogException
public void deleteUserInfoByUserNo(UserVo param) {
userDAO.deleteUserInfoByUserNo(param);
}
1.3 내 프로필 컨트롤러 구현
src/기본패키지/user/controller 패키지 안에 UserController 클래스와 RestUserController 클래스 파일의 내용을 아래와 같이 추가해주세요.
// 내정보 페이지
@GetMapping("profile")
public String profile(Model model, HttpSession session) {
UserVo sessionUser = (UserVo) session.getAttribute("sessionUser");
model.addAttribute("data", userService.getJoinQuestionList());
return "user/profile";
}
// 회원정보 수정
@PostMapping("updateUserInfo")
public HashMap<String, Object> updateUserInfo(UserVo param, HttpSession session) {
HashMap<String, Object> data = new HashMap<String, Object>();
UserVo sessionUser = userService.getUser(param.getUser_id());
if (sessionUser != null) {
data.put("result", "success");
userService.updateUserInfo(param);
} else {
data.put("result", "fail");
}
return data;
}
// 현재 비밀번호 체크
@PostMapping("checkPw")
@LogException
public HashMap<String, Object> checkPw(String current_password, String user_id) {
HashMap<String, Object> data = new HashMap<>();
UserVo userVo = userService.getUser(user_id);
if (userVo != null) {
if (BCrypt.checkpw(current_password, userVo.getUser_pw())) {
data.put("result", "success");
} else {
data.put("result", "fail");
}
}
return data;
}
// 비밀번호 수정
@PostMapping(value = "modifyPassword")
@LogException
public HashMap<String, Object> modifyPassword(UserVo userVo, HttpSession session) {
HashMap<String, Object> data = new HashMap<>();
UserVo sessionUser = userService.getUser(userVo.getUser_id());
if (sessionUser != null) {
/* 비밀번호 변경 */
String changePassword = BCrypt.hashpw(userVo.getUser_pw(), BCrypt.gensalt());
sessionUser.setUser_pw(changePassword);
userService.getUserUpdatePw(sessionUser);
/* 비밀번호 변경후 로그아웃 */
session.invalidate();
}
return data;
}
// 회원탈퇴
@PostMapping(value = "deleteUserInfoByUserNo")
public HashMap<String, Object> deleteUserInfoByUserNo(UserVo vo, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
HashMap<String, Object> data = new HashMap<String, Object>();
UserVo sessionUser = (UserVo) session.getAttribute("sessionUser");
String password = vo.getUser_pw();
if (!BCrypt.checkpw(vo.getUser_pw(), sessionUser.getUser_pw())) {
data.put("result", "fail");
} else {
data.put("result", "success");
userService.deleteUserInfoByUserNo(sessionUser);
session.invalidate();
}
return data;
}
1.4 내 프로필 페이지 JSP 구현
web-inf/views/user 패키지 안에 profile.jsp 파일 생성 후 내용을 아래와 같이 작성해주세요.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../include/head.jsp" %>
<%@ include file="../include/user_menu.jsp" %>
<html>
<body class="hold-transition skin-green-light sidebar-mini" oncopy="return false" oncut="return false"
onpaste="return false">
<div class="wrapper">
<%@ include file="../include/top_menu.jsp" %>
<%@ include file="../include/left_menu.jsp" %>
<div class="content-wrapper">
<section class="content container-fluid">
<div class="row">
<div class="col-md-5">
<div class="box box-primary">
<div class="box-body box-profile">
<img class="profile-user-img img-responsive img-circle"
src="/resources/dist/img/profile/${sessionUser.user_image}" alt="User profile picture">
<h3 class="profile-username text-center">${sessionUser.user_nickname}</h3>
<div class="text-center">
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal"
data-target="#userPhotoModal">
<i class="fa fa-photo"> 프로필사진 수정</i>
</a>
</div>
<ul class="list-group list-group-unbordered">
<li class="list-group-item">
<b>아이디</b> <a class="pull-right">${sessionUser.user_id}</a>
</li>
<li class="list-group-item">
<b>이메일</b> <a class="pull-right">${sessionUser.user_email}</a>
</li>
<li class="list-group-item">
<b>가입일자</b>
<a class="pull-right">
<fmt:formatDate value="${sessionUser.user_join_date}"
pattern="yyyy-MM-dd a hh:mm"/>
</a>
</li>
<li class="list-group-item">
<b>최근 로그인 일자</b>
<a class="pull-right">
<fmt:formatDate value="${sessionUser.user_last_connection_date}"
pattern="yyyy-MM-dd a hh:mm"/>
</a>
</li>
<li class="list-group-item">
<b>생년월일</b>
<a class="pull-right">
<fmt:formatDate value="${sessionUser.user_birth}" pattern="yy년MM월dd일"/>
</a>
</li>
</ul>
</div>
<div class="box-footer text-center">
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#userInfoModal">
<i class="fa fa-info-circle"> 회원정보 수정</i>
</a>
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#userPwModal">
<i class="fa fa-question-circle"> 비밀번호 수정</i>
</a>
<a href="#" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#userOutModal">
<i class="fa fa-user-times"> 회원 탈퇴</i>
</a>
</div>
</div>
</div>
</div>
</section>
</div>
<%@ include file="../include/footer.jsp" %>
</div>
<%@ include file="../include/plugin_js.jsp" %>
</body>
</html>
<div class="modal fade" id="userInfoModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">회원정보 수정</h4>
</div>
<div class="model-body" align="center">
<form id="updateForm" action="../user/updateUserInfo">
<div class="row mt-2">
<div class="col">
<div class="row mt-1">
<div class="col">
<label for="inputUserId">아이디</label>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="text" id="inputUserId" class="form-control" name="user_id"
value="${sessionUser.user_id}" disabled="disabled">
</div>
</div>
<div class="row mt-1">
<div class="col">
<label for="userNickName">닉네임</label>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="text" id="userNickName" class="form-control" name="user_nickname"
value="${sessionUser.user_nickname}">
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertNickName" style="font-size: 12px;"></div>
</div>
<div class="row mt-1">
<div class="col">
<label for="userPhone">휴대폰번호</label>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="text" id="userPhone" class="form-control" name="user_phone"
value="${sessionUser.user_phone}">
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertPhone" style="font-size:12px"></div>
</div>
<div class="row mt-1">
<div class="col-md-7">
<input type="text" id="userEmail" class="form-control" name="user_email"
value="${sessionUser.user_email}">
</div>
<div class="col">
<button type="button" id="checkEmailButton"
class="btn btn-primary pwModBtn" disabled='disabled'>인증번호 발송
</button>
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertEmail" style="font-size:12px;"></div>
</div>
<div class="row mt-1">
<div class="col">
<label for="checkEmail">인증번호</label>
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertCertified" style="font-size:12px;"></div>
</div>
<div class="row mt-1">
<div class="col">
<input class="form-control" id="checkEmail" type="text"
placeholder="인증번호를 입력해주세요." aria-label="default input example"
disabled="disabled">
</div>
</div>
<div class="row mt-2">
<div class="col">
<select class="form-select" name="question_no" id="userQuestion"
aria-label="Default select example">
<c:forEach items="${data }" var="question">
<option value="${question.question_no }">
${question.question_content }</option>
</c:forEach>
</select>
</div>
</div>
<div class="row mt-2">
<div class="col">
<input type="text" id="userFindAnswer" class="form-control"
value="${sessionUser.user_findAnswer}">
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertFindAnswer" style="font-size:12px;"></div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger pull-left" data-dismiss="modal">닫기</button>
<button type="button" class="btn btn-primary infoModBtn" id="updateInfo" disabled="disabled">수정</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="userPwModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">비밀번호 변경</h4>
</div>
<div class="modal-body" data-rno>
<div class="row mt-1">
<div class="col">
<div class="row mt-1">
<div class="col">
<input type="hidden" id="uid" value="${sessionUser.user_id}">
<label for="currentPassword">현재 비밀번호</label>
</div>
</div>
<div class="row mt-1">
<div class="col-md-7">
<input type="password" class="form-control"
placeholder="현재 사용중인 패스워드를 입력해주세요" id="currentPassword">
</div>
<div class="col">
<button type="button" class="but btn-info pwModBtn" id="checkPassword">체크하기</button>
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertCurrentPassword" style="font-size:12px;"></div>
</div>
<div class="row mt-1">
<div class="col">
<label for="newPassword">새로운 비밀번호 :</label>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="password" class="form-control" placeholder="새로운 패스워드를 입력해주세요"
id="newPassword" disabled="disabled">
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertNewPassword"></div>
</div>
<div class="row mt-1">
<div class="col">
<label for="checkingNewPassword">비밀번호 확인 : </label>
</div>
</div>
<div class="row mt-1">
<div class="col">
<input type="password" class="form-control"
placeholder="새로운 패스워드를 한번 더 입력해주세요" id="checkingNewPassword"
disabled="disabled">
</div>
</div>
<div class="row mt-1">
<div class="col-md-7" id="alertCheckingPassword"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger pull-left" data-dismiss="modal">닫기</button>
<button type="button" class="btn btn-primary pull-right pwModBtn" id="modifyPw" disabled="disabled">
저장
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="userOutModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">회원을 탈퇴하시겠습니까?</h4>
</div>
<div class="modal-body" data-rno>
<div class="row mt-1">
<div class="col">
<div class="row mt-1">
<div class="col">
<label for="currentPassword2">현재 비밀번호</label>
</div>
</div>
<div class="row mt-1">
<div class="col-md-7">
<input type="password" class="form-control"
placeholder="현재 사용중인 패스워드를 입력해주세요" id="currentPassword2">
</div>
<div class="col">
<button type="button" class="but btn-info pwModBtn" id="checkPassword2">체크하기</button>
</div>
</div>
<div class="row mt-1">
<div class="col" id="alertCurrentPassword2" style="font-size:12px;"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger pull-left" data-dismiss="modal">닫기</button>
<button type="button" class="btn btn-primary myInfoModModalBtn" id="deleteUser" disabled="disabled">탈퇴
</button>
</div>
</div>
</div>
</div>
1.5 내 프로필 JavaScript 구현
webapp/resources/dist/js/user/ 패키지 안에 relatedUser.js 파일에 아래의 내용을 추가 해주세요
$("#userFindAnswer").keyup(function () {
$("#updateInfo").attr("disabled", false);
});
$("#updateInfo").click(function () {
if ($("#alertNickName").text() == "! 이미 사용중인 닉네임 입니다.") {
alert("닉네임을 확인해주세요");
} else if ($("#alertPhone").text() == "! 이미 사용중인 휴대폰번호 입니다.") {
alert("휴대폰번호을 확인해주세요");
} else if ($("#alertEmail").text() == "! 이메일이 이미 사용중입니다.") {
alert("이메일주소를 확인해주세요");
} else if ($("#alertCertified") == "! 인증번호가 일치하지 않습니다. 다시 확인해주시기 바랍니다.") {
alert("인증번호를 확인해주세요");
} else {
$.ajax({
type: "post",
url: "../user/updateUserInfo",
data: {
question_no: $("#userQuestion").val(),
user_id: $("#inputUserId").val(),
user_nickname: $("#userNickName").val(),
user_phone: $("#userPhone").val(),
user_email: $("#userEmail").val(),
user_findAnswer: $("#userFindAnswer").val()
},
dataType: "json",
success: function (data) {
if (data.result == 'fail') {
alert("유저 정보 확인에 실패 하였습니다 다시 확인해주세요");
} else if (data.result == 'success') {
alert("유저 정보 업데이트에 성공 하였습니다");
location.reload();
}
}
});
}
});
$("#checkPassword").click(function () {
$.ajax({
type: "post",
url: "../user/checkPw",
data: {
user_id: $("#uid").val(),
current_password: $("#currentPassword").val()
},
dataType: "json",
success: function (data) {
if (data.result == 'fail') {
$("#alertCurrentPassword").css({
"color": "red",
"font-size": "12px"
});
$("#alertCurrentPassword").text("! 현재 비밀번호와 일치 하지 않습니다. 다시 확인해주세요");
} else {
$("#alertCurrentPassword").css({
"color": "green",
"font-size": "12px"
});
$("#alertCurrentPassword").text("✔ 현재 비밀번호와 일치 합니다.");
$("#currentPassword").attr("disabled", true);
$("#newPassword").attr("disabled", false);
}
}
});
});
$("#newPassword").keyup(function () {
var value = $(event.target).val();
var num = value.search(/[0-9]/g);
var eng = value.search(/[a-z]/ig);
var spe = value.search(/[`~!@@#$%^&*|₩₩₩'₩";:₩/?]/gi);
if (value.length < 8 || value.length > 30) {
$("#alertNewPassword").css({
"color": "red",
"font-size": "12px"
});
$("#alterPassword").text("! 비밀번호는 8자리이상 30자리 이하여야 합니다.")
} else if (value.replace(/\s| /gi, "").length == 0) {
$("#alertNewPassword").css({
"color": "red",
"font-size": "12px"
});
$("#alertNewPassword").text("! 비밀번호에 공백은 사용할 수 없습니다.")
} else if (num < 0 || eng < 0 || spe < 0) {
$("#alertNewPassword").css({
"color": "red",
"font-size": "12px"
});
$("#alertNewPassword").text("! 비밀번호는 영어+숫자+특수문자로 이루어져야 합니다.")
} else {
$("#alertNewPassword").css({
"color": "green",
"font-size": "10px"
});
$("#alertNewPassword").text("✔ 사용가능한 비밀번호입니다.");
$("#checkingNewPassword").attr("disabled", false);
}
});
$("#checkingNewPassword").keyup(function () {
var value = $("#newPassword").val();
if (value != $("#checkingNewPassword").val()) {
$("#alertCheckingPassword").css({
"color": "red",
"font-size": "12px"
});
$("#alertCheckingPassword").text("! 비밀번호가 일치하지 않습니다.")
return;
}
;
$("#alertCheckingPassword").css({
"color": "green",
"font-size": "10px"
});
$("#alertCheckingPassword").text("✔ 비밀번호가 일치합니다.");
$("#newPassword").attr("disabled", true);
$("#modifyPw").attr("disabled", false);
});
$("#modifyPw").click(function () {
$.ajax({
type: "post",
url: "../user/modifyPassword",
data: {
user_id: $("#uid").val(),
user_pw: $("#checkingNewPassword").val()
},
dataType: "json",
success: function (data) {
if (data.result == 'fail') {
alert("비밀번호 변경에 실패 하였습니다. 다시 확인해주세요");
} else {
alert("비밀번호 변경에 성공하였습니다");
location.reload();
}
}
});
});
$("#checkPassword2").click(function () {
$.ajax({
type: "post",
url: "../user/checkPw",
data: {
user_id: $("#uid").val(),
current_password: $("#currentPassword2").val()
},
dataType: "json",
success: function (data) {
if (data.result == 'fail') {
$("#alertCurrentPassword2").css({
"color": "red",
"font-size": "12px"
});
$("#alertCurrentPassword2").text("! 현재 비밀번호와 일치 하지 않습니다. 다시 확인해주세요");
} else {
$("#alertCurrentPassword2").css({
"color": "green",
"font-size": "12px"
});
$("#alertCurrentPassword2").text("✔ 현재 비밀번호와 일치 합니다.");
$("#deleteUser").attr("disabled", false);
}
}
});
});
$("#deleteUser").click(function () {
$.ajax({
type: "post",
url: "../user/deleteUserInfoByUserNo",
data: {
user_id: $("#uid").val(),
user_pw: $("#currentPassword2").val()
},
dataType: "json",
success: function (data) {
if (data.result == 'fail') {
alert("비밀번호을 확인해주세요");
} else {
alert("회원탈퇴에 성공 하였습니다.");
location.reload();
}
}
});
});
1.6 내 프로필 페이지 화면 확인
2. 정리
이번에는 내 프로필 페이지와 회원정보 변경 회원탈퇴 비밀번호 변경에 대해서 구현 해보았습니다. 다음에는 인터셉터를 활용한 권한 체크를 구현해보도록 하겠습니다.
'스프링 프레임워크 > 스프링 MVC' 카테고리의 다른 글
# Spring MVC 게시판 예제 12 : 계정 복구 (0) | 2023.03.05 |
---|---|
# Spring MVC 게시판 예제 11 : 인터셉터를 활용한 권한체크 (0) | 2023.03.05 |
# Spring MVC 게시판 예제 09 : 아이디 및 비밀번호 찾기 구현 (0) | 2023.02.24 |
# Spring MVC 게시판 예제 08 - HttpSession을 이용한 로그인 (2) | 2023.02.24 |
# Spring MVC 게시판 예제 07 - 회원 가입 유효성 검사 (Feat. Validation) (0) | 2023.02.23 |
댓글