Spring

부트캠프84일차(주문관련 및 회원목록조회(관리자용))

동곤일상 2025. 6. 10. 16:52
반응형

1) 주문 전 상품보기(checkOut페이지)

2) 세션검증 (CartAspect)

 

3) 주문하기 

 

4) 주문정보를 mypage에서 조회해보자

 

5) (※과제)

mypage -> 회원목록(admin/list) 완성해보기


 

1) 주문전 상품보기 (checkout페이지)

<body>
<h2>배송지정보</h2>
<table>
<tr><td width="30%">주문아이디</td>
	<td width="70%">${sessionScope.loginUser.userid}</td>
</tr>
<tr><td width="30%">이름</td>
	<td width="70%">${sessionScope.loginUser.username}</td>
</tr>
<tr><td width="30%">우편번호</td>
	<td width="70%">${sessionScope.loginUser.postcode}</td>
</tr>
<tr><td width="30%">주소</td>
	<td width="70%">${sessionScope.loginUser.address}</td>
</tr>
<tr><td width="30%">전화번호</td>
	<td width="70%">${sessionScope.loginUser.phoneno}</td>
</tr>
</table>
<h2>구매상품</h2>
<table>
<tr>
<th>상품명</th><th>가격</th>
<th>수량</th><th>합계</th>
</tr>
<c:forEach items="${sessionScope.CART.itemSetList}" var="itemSet" varStatus="stat">
<tr>
<td>${itemSet.item.name}</td><td>${itemSet.item.price}</td>
<td>${itemSet.quantity}</td><td>${itemSet.item.price * itemSet.quantity}</td>
</tr>
</c:forEach>
<tr><td colspan="4" align="right">
	총구입금액 : ${sessionScope.CART.total}원 </td></tr>
<tr><td colspan="4"><a href="end">확정하기</a>&emsp;
	<a href="../item/list">상품목록</a>&emsp;
</td></tr>
</table>
</body>

 

보기에도 알다시피 

세션정보가없다면 이 페이지는 아무것도 아닐거다

그러므로 AOP를 이용해 세션검증을 진행해보자

 

2) 세션검증 (CartAspect)

 

CartController.java

@RequestMapping("checkout")
	public String checkout(HttpSession session) {
		return null;
	}

 

 

CartAspect

@Component
@Aspect
public class CartAspect {
	/*
	 * poincut : Cartcontroller클래스의 매개변수의 마지막이 HttpSession이고
	 * check* 로 시작하는 메서드
	 * 
	 * advice : Before로 설정
	 */
	
	@Before("execution(* controller.Cart*.check*(..)) && args(..,session)")
	public void userIdCheck(HttpSession session) throws Throwable{
		User loginUser = (User)session.getAttribute("loginUser");
		if(loginUser==null) {
			throw new ShopException("회원만 주문이가능합니다", "../user/login");
		}
		Cart cart=(Cart)session.getAttribute("CART");
		if(cart==null || cart.getItemSetList().size()==0) {
			throw new ShopException("장바구니에 상품을 추가하세요", "../item/list");
		}
	}

}

CartController의  check로시작하며 마지막매개변수가 session인 메서드는

모두 다음과같이 세션검증을 거치게됨

(로그인하지않고 check**메서드에접근 시 로그인페이지로 이동)

(장바구니상품이없는데 check**접근 시 아이템리스트 페이지로이동)

 

 


3) 주문하기 

CREATE TABLE sale (  -- 주문정보
	saleid int PRIMARY KEY,
	userid varchar(10) NOT NULL,
	saledate datetime,
	foreign key (userid) references useraccount (userid)
);

CREATE TABLE saleitem (   -- 주문상품
	saleid int ,
	seq int ,
	itemid int NOT NULL,
	quantity int,
	PRIMARY KEY (saleid, seq),
	foreign key (saleid) references sale (saleid),
	foreign key (itemid) references item (id)
);

 

 

logic

package logic;

@Getter
@Setter
@ToString
public class Sale { //DB의 sale테이블의 내용 + 사용자정보 + 주문상품정보
	private int saleid; //주문번호
	private String userid; //고객아이디
	private Date saledate; //주문일자
	private User user; //고객의정보
	private List<SaleItem> itemList = new ArrayList<>();
	public int getTotal() {
		return itemList.stream()
				.mapToInt(s->s.getItem().getPrice() * s.getQuantity()).sum();
	}
}

//------------------------------------------

package logic;

@Getter
@Setter
@ToString
@NoArgsConstructor
public class SaleItem {
	
	private int saleid; //주문번호
	private int seq; //주문상품번호
	private int itemid; //상품아이디
	private Item item;//상품아이디에 해당하는 상품정보
	private int quantity;//수량
	
	public SaleItem(int saleid , int seq , ItemSet itemSet) {
		this.saleid = saleid;
		this.seq = seq;
		this.item = itemSet.getItem();
		this.itemid = itemSet.getItem().getId();//상품id
		this.quantity = itemSet.getQuantity(); //주문수량
	}

}

 

CartController 의 end매핑부분 ( 주문확정클릭시 동작)

//check로시작하며 session매개변수 -> AOP사용
	//주문확정 클릭시 동작하는 컨트롤러
	@GetMapping("end")
	public ModelAndView checkEnd(HttpSession session) {
		ModelAndView mav = new ModelAndView();
		Cart cart = (Cart)session.getAttribute("CART");
		User loginUser = (User)session.getAttribute("loginUser");
		Sale sale = service.checkend(loginUser,cart);
		session.removeAttribute("CART");//장바구니초기화
		mav.addObject("sale",sale);
		return mav;
		
	}

 

ShopService

public Sale checkend(User loginUser, Cart cart) {
		int maxSaleid = saleDao.getMaxSaleId(); //가장높은 주문번호 반환
		Sale sale = new Sale();
		sale.setSaleid(maxSaleid+1);
		sale.setUser(loginUser);
		sale.setUserid(loginUser.getUserid());  //세션정보(로그인)인 userid값 저장
		//sale.setSaledate(new Date()); insert시 now로 고정되어있음
		saleDao.insert(sale); //sale테이블에 해당객체의정보들 추가
		
		int seq = 0;
		//ItemSet : item 객체 , 수량이 존재
		List<ItemSet> itemSetList = cart.getItemSetList();
		for(ItemSet is : itemSetList) {
			//++seq : 2개이상 상품 동시 주문시 saleid가 같다. 
			//seq를 달리해 구분함
			SaleItem saleItem = new SaleItem(sale.getSaleid(), ++seq, is);
			sale.getItemList().add(saleItem);//sale의 list에 넣기
			saleItemDao.insert(saleItem);
		}
		return sale; //sale " 주문정보,고객정보,주문상품 등
	}

seq와 saleid를 헷갈릴수도있지만 간단하게 설명하자면

saleid : 주문번호

seq : 주문 상품들

 

즉 주문번호가10이라고치고 3개의상품을 주문했다면

각각 seq가 1 ,2, 3 으로 배정될것임

 

Dao

package dao;
@Repository
public class SaleDao {
	
	@Autowired
	private SqlSessionTemplate template;
	Class<SaleMapper> cls = SaleMapper.class;

	public void insert(Sale sale) {
		template.getMapper(cls).insert(sale);
		
	}

	public int getMaxSaleId() {
		return template.getMapper(cls).maxid();
	}
}

//------------------------------------
package dao;

@Repository
public class SaleItemDao {
	@Autowired
	//DBConfig에서 설정되어있으므로 autowired를 이용해 사용을 알림
	private SqlSessionTemplate template;
	private final Class<SaleItemMapper> cls = SaleItemMapper.class;

	
	public void insert(SaleItem saleItem) {
		template.getMapper(cls).insert(saleItem);
		
	}
	
}

 

Mapper

package dao.mapper;
public interface SaleMapper {


	@Insert("insert into sale (saleid,userid,saledate) "
			+ " values(#{saleid},#{userid},now())")
	void insert(Sale sale);
	
	@Select("select ifnull(max(saleid),0) from sale")
	int maxid();
}

//----------------------------

package dao.mapper;
public interface SaleItemMapper {

	@Insert("insert  into saleitem "
			+ "values (#{saleid},#{seq},#{itemid},#{quantity})")
	void insert(SaleItem saleItem);

}

 

DB에도 정상적으로 반영이되는지 확인해보자

 


4) 주문정보를 mypage에서 조회해보자

 

UserController 수정

@Autowired
	private ShopService shopService;
@RequestMapping("mypage")
	public ModelAndView idCheckMypage(String userid, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		//아이디를이용해 객체를 뽑음
		User user = service.selectUser(userid);
		
		List<Sale> salelist = shopService.saleList(userid);
		mav.addObject("user",user);
		mav.addObject("salelist",salelist);
		return mav;
	}

 

 

ShopService의 일부분

public List<Sale> saleList(String userid) {
		List<Sale> list = saleDao.saleList(userid);//userid사용자의 주문정보목록
		for (Sale sa : list) {
			List<SaleItem> saleItemList = saleItemDao.list(sa.getSaleid());
			for (SaleItem si : saleItemList) {
				Item item = itemDao.getItem(si.getItemid());
				si.setItem(item);
			}
			sa.setItemList(saleItemList);
		}
		return list;
	}

 

mapper들의 일부분 (DAO생략)

public interface SaleMapper {
@Select("select * from sale where userid=#{userid}")
	List<Sale> saleList(String userid);
    }
//-------------------------------------
public interface SaleItemMapper {
	@Select("select * from saleitem where saleid = #{saleid}")
	List<SaleItem> list(int saleid);
}
//-----------------------------------

public interface ItemMapper {

	@Select({"<script>",
		"select * from item <if test='id != null'>where id=#{id}</if> order by id",
		"</script>"})
	public List<Item> select(Map<String,Object> param);
    }

 

 

 

먼저 파라미터정보인 userid에 맞는

sale객체 (주문자정보)를 list형식으로 가져옴

 

해당 List<Sale>로 for문을 설정

 

각 Sale객체의  id를 이용해

List<SaleItem>반환 후 for문 생성

 

그 후 해당 SaleItem

itemId를 이용해

Item객체를 반환

 

saleItem에 

Item객체를 채워준다

 

List<SaleItem> ItemList();

마지막으로 각 Sale객체의 ItemList를 설정해줌

 

결론 :

Sale객체의 setItemList를 하기위한 작업들

List<Sale>반환

 

 


5) mypage -> 회원목록(admin/list) 완성해보기

 

user/mypage.jsp의 일부분

<c:if test="${loginUser.userid == 'admin'}">
                        <a href="../admin/list" class="btn btn-info btn-sm">회원목록</a>
                    </c:if>
                    <%---- 회원목록 완성해보기 --%>

 

일단 애초에 다른경로로가야함을 알수있음 adminCotroller를 하나 만들어서

admin이 매핑되게 설정해보자

 

package controller;

@Controller
@RequestMapping("admin")
public class AdminController {
	
	@Autowired
	UserService service;
	
	@GetMapping("/list")
	public String callList(Model model,HttpSession session) {
		List<User> list = service.selectList(); //모든 User객체를 꺼내옴
		model.addAttribute("list",list);
		return "/admin/list";
	}
}

UserService를 @autowired로 등록하지않는다면

사용할수가없음!!!!

list속성을 등록해줘야 view에서 그것으로 처리를함!!!!!

 

service내부의 로직이나 Dao는 그냥 mapper로 이동하게 해 주는 수단으로 사용됐으므로

생략하겠음....

 

UseMapper의 일부분 ( 모든 유저정보를 list로꺼내옴)

@Select("select * from useraccount")
	List<User> list();

 

 

aop / UserLoginAspect.java

@Component
@Aspect
public class UserLoginAspect {
@Around("execution(* controller.Admin*.call*(..)) && args(..,session)")
	public Object adminCheck(ProceedingJoinPoint joinPoint,
			HttpSession session) throws Throwable{
		User loginUser = (User)session.getAttribute("loginUser");
		if(loginUser==null || !(loginUser instanceof User)) {
			throw new ShopException("[AdminCheck]로그인부터하세요", "../user/login");			
		}
        
		String userId = loginUser.getUserid();
		
		if( !(userId.equals("admin"))) {
			throw new ShopException("[AdminCheck]관리자만 접근가능", "../user/mypage?userid="+userId);			
		}
		return joinPoint.proceed();
	}
}

이렇게 접근처리까지해줌으로써

관리자가아니면 회원목록에 접근조차할수없으며 , 로그인없이 접근할수도없게 됨