수업(국비지원)/Spring

[Spring] (MVC 2) 마이페이지 생성(mypage, UserLoginAspect, UserController, kiclayout)

byeolsub 2023. 4. 21. 00:09

📌 mypage.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- /springmvc1/src/main/webapp/WEB-INF/view/user/mypage.jsp --%>    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My page</title>
<%--  --%>
<script type="text/javascript">
   function disp_div(id, tab) {
	   $(".info").hide()
	   $(".tab").removeClass("select")
	   $("#" + id).show()
	   $("#" + tab).addClass("select")
   }
   function list_disp(id) {
	   $("#" + id).toggle()
   }
</script>
<style type="text/css">
  .select {
    padding : 3px;
    background-color : #0000ff;
  }
  .select>a {
    color : #ffffff;
    text-decoration : none;
    font-weight : bold; 
  }
</style>
</head>
<body>
<table class="w3-table">
   <tr><td id="tab1" class="tab select">
   <a href="javascript:disp_div('minfo', 'tab1')">회원정보 보기</a></td>
   <c:if test="${param.id != 'admin'}">
      <td id="tab2" class="tab">
   <a href="javascript:disp_div('oinfo', 'tab2')">주문정보 보기</a></td>
   </c:if></tr>   
</table>
<div id="oinfo" class="info" sytle="display: none; width:100%;">
   <table class="w3-table">
     <tr><th>주문번호</th><th>주문일자</th><th>총 주문금액</th></tr>
     <c:forEach items="${salelist}" var="sale" varStatus="stat">
     <tr><td align="center">
        <a href="javascript:list_disp('saleLine${stat.index}')">${sale.saleid}</a></td>
       <td align="center">
     <fmt:formatDate value="${sale.saledate}" pattern="yyyy-MM-dd"/>
       </td><td align="right">
     <fmt:formatNumber value="${sale.total}" pattern="#,###"/>원</td></tr>
       <tr id="saleLine${stat.index}" class="saleLine" style="display: none;">
         <td colspan="3" align="center">
         <table class="w3-table">
           <tr><th width="25%">상품명</th><th width="25%">상품가격</th>
               <th width="25%">구매수량</th><th width="25%">상품총액</th></tr>
                     <c:forEach items="${sale.itemList}" var="saleItem">
                       <tr><td class="title">${saleItem.item.name}</td>
                       <td>
      <fmt:formatNumber value="${saleItem.quantity*saleItem.item.price}" pattern="#,###"/>원</td></tr></c:forEach>                  
   </table></td></tr></c:forEach></table></div>
<div id="minfo" class="info">
 <table class="w3-table">
     <tr><td>아이디</td><td>${user.userid}</td></tr>
     <tr><td>이름</td><td>${user.username}</td></tr>
     <tr><td>우편번호</td><td>${user.postcode}</td></tr>
     <tr><td>전화번호</td><td>${user.phoneno}</td></tr>
     <tr><td>주소</td><td>${user.address}</td></tr>
     <tr><td>이메일</td><td>${user.email}</td></tr>
     <tr><td>생년월일</td><td><fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd" /></td></tr>
 </table><br>
 <a href="update?id=${user.userid}">[회원정보 수정]</a>&nbsp;
 <a href="password">[비밀번호 수정]</a>&bnsp;
   <c:if test="${loginUser.userid != 'admin'}">
    <a href="delete?id=${user.userid}">[회원탈퇴]</a>&nbsp;
    </c:if>
   <c:if test="${loginUser.userid == 'admin'}">
    <a href="../admin/list">[회원목록]</a>&nbsp; 
</c:if></div>
</body>
</html>

 

📌 UserLoginAspect.java 내용 추가하기

package aop;

import javax.servlet.http.HttpSession;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import exception.LoginException;
import logic.Cart;
import logic.User;

@Component //객체화
@Aspect //AOP 기능의 클래스
public class UserLoginAspect {
/*
 * Pointcut : 핵심메서드의 선택 기준 설정 
 * 
 *    execution(* controller.User*.loginCheck*(..)) && args(..,session) : 
 *        controller 페키지의 클래스 중 User로 시작하는 클래스의 메서드 중 longinCheck로 시작하는 (..) 매개변수와 상관없이 모든 메서드
 *    args(..,session) :
 *        매서드의 매개변수의 마지막 변수의 자료형이 HttpSession인 메서드를 선택.
 *        .. : 아무거나 상관없음  
 *        
 * Advice : AOP 메서드의 실행되는 시점 설정.
 *    1. @Around : 핵심(Pointcut) 메서드 실행 전 후 AOP 메서드 실행
 *                 ProceedingJoinPoint를 이용하여 전 후 를 구분함 
 *    2. @Before : 핵심 메서드 실행 전 AOP 메서드 실행
 *    3. @After : 핵심 메서드 실행 후 AOP 메서드 실행
 *    4. @AfterReturning : 핵심 메서드 실행 정상 종료 후 AOP 메서드 실행 
 *    5. @AfterThrowing : 핵심 메서드 실행 오류 종료 후 AOP 메서드 실행         
 */
	@Around("execution(* controller.User*.loginCheck*(..)) && args(..,session)")
	public Object userLoginCheck(ProceedingJoinPoint joinPoint, HttpSession session) throws Throwable {
		//joinPoint : 실행되어야 하는 메서드들의 순서를 관리 할 수 있는 객체 
		//session : Pointcut 메서드의 마지막 매개변수
		User loginUser = (User)session.getAttribute("loginUser");
		if(loginUser == null) { //로그인이 안된 경우
			throw new LoginException("[userlogin]로그인 후 거래 하세요.", "login");
		}
		return joinPoint.proceed(); //다음번 메서드로 진행. 실행 전과 후를 나눠주는 역할
	}
	**@Around("execution(* controller.User*.idCheck*(..)) && args(..,id,session)")
	public Object useridCheck(ProceedingJoinPoint joinPoint,String id, HttpSession session) throws Throwable {
		User loginUser = (User)session.getAttribute("loginUser");
		if(loginUser == null) {
			throw new LoginException("[idCheck]로그인 후 거래하세요.", "login");
		} else if(!loginUser.getUserid().equals(id) && !loginUser.getUserid().equals("admin")) {
			throw new LoginException("[idCheck]본인만 거래 가능합니다.", "../item/list");
		}
		return joinPoint.proceed();
	}**
}

 


📌 kiclayout.jsp 내용 추가

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="path" value="${pageContext.request.contextPath}"/>    
<%-- /springmvc1/src/main/webapp/layout/kiclayout.jsp --%>    

<!DOCTYPE html>
<html>
<head>
<title><sitemesh:write property="title"/></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript" 
src="http://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
html,body,h1,h2,h3,h4,h5 {font-family: "Raleway", sans-serif}
</style>
<sitemesh:write property="head"/>
</head>
<body class="w3-light-grey">

<!-- Top container -->
<div class="w3-bar w3-top w3-black w3-large" style="z-index:4">
  <button class="w3-bar-item w3-button w3-hide-large w3-hover-none w3-hover-text-light-grey" onclick="w3_open();"><i class="fa fa-bars"></i> &nbsp;Menu</button>
  <span class="w3-bar-item w3-right">
    <c:if test="${empty sessionScope.loginUser}">
     <a href="${path}/user/login">로그인</a>
     <a href="${path}/user/join">회원가입</a>
    </c:if>
    <c:if test="${!empty sessionScope.loginUser}">
     ${sessionScope.loginUser.username}님이 로그인 하셨습니다.&nbsp;&nbsp; 
     <a href="${path}/user/logout">로그아웃</a>
    </c:if>
  </span>
</div>

<!-- Sidebar/menu -->
<nav class="w3-sidebar w3-collapse w3-white w3-animate-left" style="z-index:3;width:300px;" id="mySidebar"><br>
  <div class="w3-container w3-row">
    <div class="w3-col s4">
      <img src="${path}/image/logo.png" class="w3-circle w3-margin-right" style="width:100px">
    </div>
    <div class="w3-col s8 w3-bar">
      <c:if test="${!empty sessionScope.loginUser}">
      <span>반갑습니다, <strong>${sessionScope.loginUser.username}님</strong></span><br>
      </c:if>
      <c:if test="${empty sessionScope.loginUser}">
      <span><strong>로그인 하세요.</strong></span><br>
      </c:if>
    </div>
  </div>
  <hr>
  <div class="w3-bar-block">
    <a href="#" class="w3-bar-item w3-button w3-padding-16 w3-hide-large w3-dark-grey w3-hover-black" onclick="w3_close()" title="close menu"><i class="fa fa-remove fa-fw"></i>&nbsp; Close Menu</a>
    <a href="${path}/user/mypage?id=${loginUser.userid}" class="w3-bar-item w3-button w3-padding w3-blue">
    <i class="fa fa-users fa-fw">
    </i>&nbsp; 회원관리</a>
    <a href="${path}/item/list" class="w3-bar-item w3-button w3-padding">
    <i class="fa fa-eye fa-fw">
    </i>&nbsp; 상품관리</a>
    <hr>
    <a href="${path}/board/list?doardid=1" class="w3-bar-item w3-button w3-padding">
    <i class="fa fa-users fa-fw">
    </i>&nbsp; 공지사항</a>
    <a href="${path}/board/list?boardid=2" class="w3-bar-item w3-button w3-padding">
    <i class="fa fa-bullseye fa-fw">
    </i>&nbsp; 자유게시판</a>
    <a href="${path}/board/list?boardid=3" class="w3-bar-item w3-button w3-padding">
    <i class="fa fa-diamond fa-fw">
    </i>&nbsp; QnA</a>
  </div>
</nav>


<!-- Overlay effect when opening sidebar on small screens -->
<div class="w3-overlay w3-hide-large w3-animate-opacity" onclick="w3_close()" style="cursor:pointer" title="close side menu" id="myOverlay"></div>

<!-- !PAGE CONTENT! -->
<div class="w3-main" style="margin-left:300px;margin-top:43px;">

  <!-- Header -->
  <header class="w3-container" style="padding-top:22px">
    <h5><b><i class="fa fa-dashboard"></i> My Dashboard</b></h5>
  </header>

  <div class="w3-row-padding w3-margin-bottom">
    <div class="w3-quarter">
      <div class="w3-container w3-red w3-padding-16">
        <div class="w3-left"><i class="fa fa-comment w3-xxxlarge"></i></div>
        <div class="w3-right">
          <h3>52</h3>
        </div>
        <div class="w3-clear"></div>
        <h4>Messages</h4>
      </div>
    </div>
    <div class="w3-quarter">
      <div class="w3-container w3-blue w3-padding-16">
        <div class="w3-left"><i class="fa fa-eye w3-xxxlarge"></i></div>
        <div class="w3-right">
          <h3>99</h3>
        </div>
        <div class="w3-clear"></div>
        <h4>Views</h4>
      </div>
    </div>
    <div class="w3-quarter">
      <div class="w3-container w3-teal w3-padding-16">
        <div class="w3-left"><i class="fa fa-share-alt w3-xxxlarge"></i></div>
        <div class="w3-right">
          <h3>23</h3>
        </div>
        <div class="w3-clear"></div>
        <h4>Shares</h4>
      </div>
    </div>
    <div class="w3-quarter">
      <div class="w3-container w3-orange w3-text-white w3-padding-16">
        <div class="w3-left"><i class="fa fa-users w3-xxxlarge"></i></div>
        <div class="w3-right">
          <h3>50</h3>
        </div>
        <div class="w3-clear"></div>
        <h4>Users</h4>
      </div>
    </div>
  </div>

  <div class="w3-panel">
  <sitemesh:write property="body"/>
  </div>
  <hr>
  
  <!-- Footer -->
  <footer class="w3-container w3-padding-16 w3-light-grey">
    <h4>FOOTER</h4>
    <p>Powered by <a href="https://www.w3schools.com/w3css/default.asp" target="_blank">w3.css</a></p>
  </footer>

  <!-- End page content -->
</div>

<script>
// Get the Sidebar
var mySidebar = document.getElementById("mySidebar");

// Get the DIV with overlay effect
var overlayBg = document.getElementById("myOverlay");

// Toggle between showing and hiding the sidebar, and add overlay effect
function w3_open() {
  if (mySidebar.style.display === 'block') {
    mySidebar.style.display = 'none';
    overlayBg.style.display = "none";
  } else {
    mySidebar.style.display = 'block';
    overlayBg.style.display = "block";
  }
}

// Close the sidebar with the close button
function w3_close() {
  mySidebar.style.display = "none";
  overlayBg.style.display = "none";
}
</script>

</body>
</html>

 

📌 UserController.java 내용 추가

package controller;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import logic.ShopService;
import logic.User;

@Controller
@RequestMapping("user")
public class UserController {
	@Autowired
	private ShopService service;
	
	@GetMapping("*") // * : 그 외 모든 get 방식 요청
	public ModelAndView getUser() {
		ModelAndView mav = new ModelAndView();
		mav.addObject(new User());
		return mav;
	}
	@PostMapping("join")
	public ModelAndView join (@Valid User user, BindingResult bresult) {
		ModelAndView mav = new ModelAndView();
		if(bresult.hasErrors()) { //입력값 오류 발생
			mav.getModel().putAll(bresult.getModel());
			//전반적인 오류코드 등록
			bresult.reject("error.input.user"); 
			return mav;
		}
		//db에 회원정보 등록
		try {
			service.userInsert(user);
			mav.addObject("user", user);
			//DataIntegrityViolationException : 중복키 오류
			//                                  같은 이름의 userid 값이 존재
		} catch(DataIntegrityViolationException e) {
			e.printStackTrace();
			bresult.reject("error.duplicate.user");
			mav.getModel().putAll(bresult.getModel());
			return mav;
		}
		mav.setViewName("redirect:login");
		return mav;
   }
	
	/*
	 * 로그인 - POST 방식 요청
	 * 1. 유효성 검증
	 *    User객체에 저장된 파라미터 값을 이용하여 유효성검증
	 * 2. 입력받은 userid, password로 db에서 해당 정보를 읽기.
	 *   - userid가 없는 경우
	 *   - password가 틀린 경우
	 *   - 정상적인 사용자인 경우 : session에 로그인 정보 등록하기
	 *     session.setAttribute("loginUser", user 객체)   
	 */
	@PostMapping("login")
	public ModelAndView login(@Valid User user, BindingResult bresult, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		//1. 유효성 검증
		if(bresult.hasErrors()) {
			mav.getModel().putAll(bresult.getModel());
			bresult.reject("error.input.login");
			return mav;
		}
		//2. 입력받은 userid, password로 db에서 해당 정보를 읽기.
		try {
			User dbUser = service.getUser(user.getUserid());
			if(user.getPassword().equals(dbUser.getPassword())) { //정상적인 사용자 인 경우
				session.setAttribute("loginUser", dbUser);
			} else {
				bresult.reject("error.login.password");
				mav.getModel().putAll(bresult.getModel());
				return mav;
			}
			//EmptyResultDataAccessException : 해당 레코드 없음
		} catch(EmptyResultDataAccessException e) { //id가 없는 경우 예외처리
			bresult.reject("error.login.id");
			mav.getModel().putAll(bresult.getModel());
			return mav;
		}
		mav.setViewName("redirect:mypage?id=" + user.getUserid());
		return mav;
	}
//http://localhost:8088/springmvc1/user/logout	
	@RequestMapping("logout") //핵심 메서드 : 기본 실행 메서드 (진짜 수행에 기본이 되는) 
	public String loginCheckLogout(HttpSession session) {
		session.invalidate();
		return "redirect:login";
	}
	
	/*
	 * AOP 설정하기 : UserLoginAspect 클래스의 userIdCheck 메서드로 구현하기.
	 * 1. pointcut : UserController 클래스의 idCheck로 시작하는 메서드이고, 
	 *               마지막 매개변수의 id,session인 경우 
	 * 2. 로그인 여부 검증
	 *   - 로그인이 안된경우 로그인 후 거래하세요. 메세지 출력. login페이지 호출
	 * 3. admin이 아니면서, 로그인 아이디와 id값이 다른 경우
	 *    본인만 거래 가능합니다. 메세지 출력. item/list 페이지 호출              
	 */
	**@RequestMapping("mypage")
	public ModelAndView idCheckMypage(String id, HttpSession session) {
		System.out.println("mypage 메서드 시작");
		ModelAndView mav = new ModelAndView();
		//회원 정보를 조회하여 user 이름으로 뷰 전달
		User user = service.getUser(id);
		mav.addObject("user", user);
		return mav;
	}**
}