Spring

부트캠프83일차(회원정보수정, idpw찾기 , 장바구니)

동곤일상 2025. 6. 9. 17:31
반응형

1) 회원정보수정(update)

2) 회원탈퇴 (delete)

3) 비밀번호변경(password)

4) 아이디 , 비번 찾기

5) 장바구니(추가 동작만 실제반영X)


1) 회원정보수정 (update)

@PostMapping("update")
	public ModelAndView idCheckUpdate(@Valid User user,BindingResult bresult,
			String userid,HttpSession session) {
		ModelAndView mav = new ModelAndView();
		//입력값오류발생 시 
		if(bresult.hasErrors()) {
			bresult.reject("error.update.user");
			return mav;
		}
		User loginUser = (User)session.getAttribute("loginUser");
		if(!loginUser.getPassword().equals(user.getPassword())) {
			bresult.reject("error.login.password");
			return mav;
		}
		//비밀번호일치시 실행
		try {
			service.userUpdate(user);
			if(loginUser.getUserid().equals(user.getUserid())){
				//세션을 수정된 데이터로변경
				session.setAttribute("loginUser", user);
			}
			mav.setViewName("redirect:mypage?userid="+user.getUserid());
		}catch (Exception e) {
			e.printStackTrace();
			throw new ShopException("고객정보수정실패", "update?userid="+user.getUserid());
		}
		return mav;
	}

다음과같이 코드를 짜준다

중요한점이라고 볼 수 있는곳은 update가 완료된 이후에

session정보(user객체)를 변경된 정보로 다시 설정해주는 것

 

globalError를 추가해줘야함!!!

message.properties

error.update.user  = 회원정보 수정 시 입력오류입니다.
error.login.password = 비밀번호가 틀려요

 

update.jsp의 일부분

<form:form modelAttribute="user" method="post" action="update">
		<%--BindingResult.reject(코드값)으로 등록된 데이터들 조회 --%>
		<spring:hasBindErrors name="user">
			<font color="red"> <c:forEach items="${errors.globalErrors}"
					var="error">
					<!-- mvcConfig의 messageSource에 등록된 properties에서 코드값을 출력 -->
					<spring:message code="${error.code}" />
					<br>
				</c:forEach>
			</font>
		</spring:hasBindErrors>

다음과같은 부분에 오류가 나타나게될것임

 

 

service, dao , mapper는

단순히 update를 하는

쿼리로이루어져있기때문에 생략하겠음!!!


2) 회원탈퇴 (delete)

 

 

 1.관리자인경우 탈퇴불가능

* 2. 비밀번호검증 -> 로그인된비밀번호와비교

* 본인탈퇴시 : 본인비번

* 관리자 ->타인 탈퇴 : 관리자비번으로검증

* 3.비밀번호불일치

* 메시지출력후 delete페이지로이동

* 4.비밀번호일치

* db에서 사용자정보삭제

* 본인탈퇴 : 로그아웃 . login페이지로이동

* 관리자 타인 탈퇴 : admin/list 페이지이동

@PostMapping("delete")
	public ModelAndView idCheckDelete(String password,String userid,HttpSession session) {
		ModelAndView mav = new ModelAndView();

		if(userid.equals("admin")) {
			throw new ShopException("관리자는 탈퇴할수없어요", "mypage?userid="+userid);
		}

		User loginUser = (User)session.getAttribute("loginUser");
		if(!password.equals(loginUser.getPassword())) {
			throw new ShopException("비밀번호오류", "delete?userid="+userid);
		}

		try {
			service.userDelete(userid);
		}
		catch (Exception e) {
			e.printStackTrace();
			throw new ShopException("탈퇴시 오류발생", "delete?userid="+userid);
		}

		//탈퇴성공
		String url = null;
		if(loginUser.getUserid().equals("admin")) {
			url="redirect:../admin/list";
		}
		else {
			session.invalidate();
			url="redirect:login";
		}
		mav.setViewName(url);
		return mav;		
	}

ModelandView.setViewName을 할 때

redirect를 해주지않는다면 jsp를 찾아가게될것임

하지만 redirect를 해준다면 해당 url정보에맞는 컨트롤러를 찾아갈거임

 

 

3) 비밀번호변경(password)


 * 본인비번만 변경가능
 * 1.로그인검증 -> AOP
 *  UserLoginAspect.loginCheck()
 *  poincut : UserController.loginCheck*(..)인 메서드,
 *  마지막변수가 HttpSession인 메서드
 * advice : around
 * 2. 현재 DB의 비밀번호와 파라미터 현재비밀번호일치 검증
 * 3.비밀번호일치  : DB수정 , 로그인정보변경 , mypage로이동
 * 4.비밀번호 불일치 : 오류메시지 출력 후 password창으로!

	@GetMapping("password")
	public String loginCheckForm(HttpSession session) {
		return null; //null로설정시 알아서 url을 맞춰줄거임
	}

	@PostMapping("password")
	public ModelAndView loginCheckPassword(@RequestParam String password ,
			@RequestParam String chgpass,HttpSession session) {
		ModelAndView mav = new ModelAndView();
		User loginUser = (User)session.getAttribute("loginUser");
		//User user = service.selectUser(loginUser.getUserid());
		if(!loginUser.getPassword().equals(password)) {
			throw new ShopException("비밀번호 불일치", "password");
		}
		try {
			loginUser.setPassword(chgpass);
			service.changePw(loginUser);
			session.setAttribute("loginUser", loginUser);
			mav.setViewName("redirect:mypage?userid="+loginUser.getUserid());
			return mav;
		}
		catch (Exception e) {
			e.printStackTrace();
			throw new ShopException("비밀번호변경시 DB오류입니다", "password");
		}
	}

post방식으로 파라미터값들이 넘어오므로 자기자신만 접근이가능함

 

일단 loginCheck AOP를 설정해보자 ( 로그인검증만 있으면 됨)

aop / UserLoginAspect.java

@Around("execution(* controller.User*.loginCheck*(..)) && args(..,session)")
	public Object loginCheck(ProceedingJoinPoint joinPoint,
			HttpSession session) throws Throwable{
		User loginUser = (User)session.getAttribute("loginUser");
		if(loginUser==null || !(loginUser instanceof User)) {
			throw new ShopException("[loginChk]로그인 필요", "login");			
		}
		return joinPoint.proceed();
	}

 

 


4) 아이디 , 비번 찾기

(굉장히 복잡하고 어려운로직임 설명을 몇개달아놓긴 할거임)

 

일단 mapping방식이 특이하다 (잘안쓸것같음)pwSearch , idSearch매핑을 처리하는부분인데.!{url}Search 의 방식으로 받음

 

@Pathvariable을 이용해서 (pw or id)정보를 받아옴

	@PostMapping("{url}Search")
	public ModelAndView search(@ModelAttribute User user , BindingResult bresult,
			@PathVariable String url) {
		System.out.println("@@url : "+url+"@@");
		//@PathVariable : {url}의 값을 매개변수로 전달
		//idSearch 요청 : url = id
		ModelAndView mav = new ModelAndView();
		String code = "error.userid.search";
		String title = "아이디";
		
		//요청url이 pwSearch라면 (아이디를 입력받을것임)
		if(url.equals("pw")) {
			title="비밀번호 초기화";
			code="error.password.search";
			if(user.getUserid()==null || 
				user.getUserid().trim().equals("")) {
				bresult.rejectValue("userid", "error.required");
			}
		}
		//
		if(user.getEmail()==null || user.getEmail().trim().equals("")) {
			bresult.rejectValue("email", "error.required");
		}
		if(user.getPhoneno()==null || user.getPhoneno().trim().equals("")) {
			bresult.rejectValue("phoneno", "error.required");
		}
		if(bresult.hasErrors()) {
			bresult.reject("error.input.check");
			return mav;
		}
		
		if(user.getUserid()!=null && user.getUserid().trim().equals("")) {
			//modelAttribute로넘겨받은 user의 아이디값이 빈 값이라면?(idSearch에서넘어온경우)
			user.setUserid(null);
		}
		String result = service.getSearch(user);
		System.out.println("result : "+result);
		if(result==null) {
			bresult.reject(code);
			return mav;
		}
		//url정보가 pw면 무작위비밀번호로업데이트 후 보여준다
		if(url.equals("pw")) {
			String tempPw = getTempPw();
			user.setPassword(tempPw);
			service.changePw(user);
			result = user.getPassword();
		}
		
		mav.addObject("result",result);
		mav.addObject("title",title);
		mav.setViewName("search");
		return mav;
	}

getTempPw메서드 :  대소문자,숫자조합의 랜덤한 6자리문자생성 

service.changePw : user객체의 id에 해당하는 비밀번호를 업데이트

 

DAO

public String search(User user) {
		String col = "userid"; //아이디검색
		if(user.getUserid()!=null) {
			col = "password";//비밀번호검색
		}
		param.clear();
		param.put("col", col);
		param.put("userid", user.getUserid());
		param.put("email", user.getEmail());
		param.put("phoneno", user.getPhoneno());
		return template.getMapper(cls).search(param);
	}

 

Mapper

v@Select({"<script>",
		"select ${col} from useraccount "
		+ "where email=#{email} and phoneno=#{phoneno} "
		+ "<if test='userid != null'> and userid=#{userid}</if> "
		+ "</script>"})
	String search(Map<String, Object> param);

 

5) 장바구니(추가 동작만 실제반영X)

 

controller(modelAndView에 적어준 url은  jsp주소를 이야기함)

cartAdd로 매핑이 되어있지만

실제로는 cart를 찾아감

package controller;

@Controller
@RequestMapping("cart")
public class CartController {

	@Autowired
	private ShopService service;

	
	@RequestMapping("cartAdd")
	public ModelAndView add(Integer id , Integer quantity,HttpSession session) {
		//new ModelAndView(뷰명) : /WEB-INF/view/cart/cart.jsp
		ModelAndView mav = new ModelAndView("cart/cart");
		Item item = service.getItem(id);
		Cart cart = (Cart)session.getAttribute("CART");
		if(cart==null) {
			cart = new Cart();
			session.setAttribute("CART", cart);
		}
		
		List<ItemSet> list = cart.getItemSetList();
		for (int i = 0; i < list.size(); i++) {
			//같은 아이템이존재한다면 갯수만늘려주는 작업
			if(list.get(i).getItem().equals(item)) {
				quantity += list.get(i).getQuantity();
				list.remove(i);
			}
		}
		cart.push(new ItemSet(item, quantity));
		
		mav.addObject("message",item.getName()+":"+quantity+"개 장바구니 추가");
		mav.addObject("cart",cart);
		System.out.println(cart);
		return mav;
	}
}

 

logic/ItemSet.java

package logic;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
@AllArgsConstructor //모든필드를 사용한 생성자
public class ItemSet {
	private Item item;
	private Integer quantity;

}

 

logic/cart.java

package logic;

@ToString
public class Cart {
	private List<ItemSet> itemSetList = new ArrayList<ItemSet>();
	
	public List<ItemSet> getItemSetList(){
		return itemSetList;
	}
	
	public void push(ItemSet set) {
		itemSetList.add(set);
	}
	
	public int getTotal() {
		return itemSetList.stream()
				//getItem().getPrice : item객체의 price프로퍼티
				.mapToInt(s->s.getItem().getPrice() * s.getQuantity())
				.sum();
	}
}

 

cart.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ 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>장바구니</title>
<!-- Bootstrap CSS CDN -->
</head>
<body>
<div class="cart-container">
    <h2 class="text-center mb-4">장바구니</h2>
    <table class="table table-striped table-hover">
        <thead class="table-dark">
            <tr>
                <th colspan="4">장바구니 상품목록</th>
            </tr>
            <tr>
                <th>상품명</th>
                <th>가격</th>
                <th>수량</th>
                <th>합계</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach items="${cart.itemSetList}" var="set" varStatus="stat">
                <tr>
                    <td>${set.item.name}</td>
                    <td><fmt:formatNumber value="${set.item.price}" pattern="###,###"/></td>
                    <td><fmt:formatNumber value="${set.quantity}" pattern="###,###"/></td>
                    <td>
                        <fmt:formatNumber value="${set.quantity * set.item.price}" pattern="###,###"/>
                        <a href="cartDelete?index=${stat.index}" class="delete-btn">ⓧ</a>
                    </td>
                </tr>
            </c:forEach>
            <tr class="total-row">
                <td colspan="4" class="text-end">
                    총 구입 금액: <fmt:formatNumber value="${cart.total}" pattern="###,###"/>원
                </td>
            </tr>
        </tbody>
    </table>
    <div class="message">
        ${message}
    </div>
    <div class="action-links">
        <a href="../item/list" class="btn-shop">상품목록</a>
        <a href="checkout" class="btn-checkout">주문하기</a>
    </div>
</div>
<!-- Bootstrap JS and Popper.js CDN for interactive components -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>