수업(국비지원)/Mybatis

[MYBATIS] (MVC 2) 예외 처리ItemException, UserController 수정

byeolsub 2023. 4. 21. 21:13

📌 ItemController.java 내용 수정

package controller;

import java.util.List;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
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 exception.ItemException;
import logic.Item;
import logic.ShopService;

/*
 * @Controller : 객체화 대상이 되는 클래스
 *    - Controller 기능 : url의 요청시 호출되는 클래스 
 */

@Controller //@Component(객체를 만들어주는) + Controller 기능
@RequestMapping("item") // <http://localhost:8088/springmvc1/item> 호출이 들어오면 실행
public class ItemController {
	@Autowired //ShopService 객체를 주입.
	private ShopService service;
	
//http://localhost:8088/springmvc1/item/list 요청시 호출되는 메서드
	@RequestMapping("list")
	public ModelAndView list() {
		//1. ModelAndView : 데이터값 + 뷰 정보를 저장하고 있는 객체
		ModelAndView mav = new ModelAndView();
		//itemList : db의 item 테이블의 모든 데이터를 Item 객체들로 저장하고 있는 객체
		List<Item> itemList = service.itemList();
		mav.addObject("itemList",itemList); //데이터 저장.
		//뷰의 이름은 기본적으로 요청 url의 정보로 설정된다 : "item/list" 설정
		return mav;
	}
	//http://localhost:8088/springmvc1/item/detail?id=1
	@RequestMapping("detail")
	public ModelAndView detail(Integer id) {
		//request.getParameter("id") = id 매개변수명 == 파라미터 이름
		ModelAndView mav = new ModelAndView();
		//item :  id에 해당하는 db의 레코드 정보를 한개 저장하는 객체
		Item item = service.getItem(id);
		mav.addObject("item",item);
		return mav;
	}
	//http://localhost:8088/springmvc1/item/create
	@RequestMapping("create")
	public ModelAndView create() {
		ModelAndView mav = new ModelAndView();
		mav.addObject(new Item());
		return mav;
	}
	/*
       @Valid : 유효성 검사.(입력값 검증)
        - item : item 객체의 프로퍼티와 요청파라미터의 이름이 같은 것을 item 객체에 저장.
                 입력된 파라미터의 값들을 저장하고 있는 객체.
        - bresult : item 객체에 유효성 검증의 결과 저장 객체.
     -        
    */
	@RequestMapping("register")
	public ModelAndView register(@Valid Item item, BindingResult bresult,HttpServletRequest request) {
		//"item/create" : 뷰의 이름을 설정.
		ModelAndView mav = new ModelAndView("item/create");
		if(bresult.hasErrors()) { //유효성 검증에 오류가 있는지 ?
			mav.getModel().putAll(bresult.getModel()); //bresult.getModel() : item 객체를 그대로 전달
		return mav;
	} 
		//item : 요청 파라미터, 업로드된 파일의 내용 저장 객체
		//request : 요청 객체. (위치를 가져 오고자)
		service.itemCreate(item,request);
		mav.setViewName("redirect:list");
		return mav;
	}
//http://localhost:8088/springmvc1/item/update?id=1
	/*
	 *  RequestMapping : get, post 방식이든 싱행
	 *  GetMapping : get 방식 호출 시 실행
	 *  PostMapping : post 방식 호출 시 실행
	 *  @GetMapping("update") : item/update 요청 정보가 get 방식 호출
	 */

	//{"update","delete"} : get 방식 요청중 update,delete 요청시 호출되는 메서드가 같음
	// update 요청 시 : update.jsp
	// delete 요청 시 : delete.jsp
	@GetMapping({"update","delete"})
	public ModelAndView updateForm(Integer id) {
		ModelAndView mav = new ModelAndView();
		//item : id에 해당하는 데이터를 db에서 읽어서 저장
		Item item = service.getItem(id);
		mav.addObject("item",item);
		return mav;
	}
	/*
	 * 1. 입력값 유효성 검증
	 * 2. db에 내용 수정. 파일 업로드.
	 * 3. update 완료시 list 재요청 하기
	 */
	
	@PostMapping("update")
	public ModelAndView update(@Valid Item item, BindingResult bresult, HttpServletRequest request) { 
	    System.out.println(item);
	    ModelAndView mav = new ModelAndView();
	    if(bresult.hasErrors()) { //입력값에서 오류가 발생한 경우.
		   mav.getModel().putAll(bresult.getModel()); //bresult.getModel() : item 객체를 그대로 전달
	       return mav;
        } 
	    service.itemUpdate(item,request);
	    mav.setViewName("redirect:list");
	    return mav;
	}
	//id에 해당하는 상품을 db에서 삭제
	**@RequestMapping("delete")
	public String delete (Integer id) { //뷰만 리턴(데이터는 보내지 않음.)
		try {
			service.itemDelete(id);	
		} catch(DataIntegrityViolationException e) {
			throw new ItemException("주문된 상품이므로 삭제 할 수 없습니다.","list");
		}
		return "redirect:list";
	}**
}

 

📌 ItemException.java 생성

package exception;

public class ItemException extends RuntimeException {
	private String url;
	public ItemException(String msg, String url) {
		super(msg);
		this.url = url;
	}
	public String getUrl() {
		return url;
	}
}

 

 📌 spring-mvc.xml 내용 추가

<?xml version="1.0" encoding="UTF-8" ?>
<!-- /src/main/resources/spring-mvc.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:websocket="http://www.springframework.org/schema/websocket"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop.xsd
   http://www.springframework.org/schema/mvc
   http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!-- css,js,html 웹에서 제공되는 파일의 기본 기능 제외  -->
<mvc:default-servlet-handler /> 

<!-- controller,logic,dao 패키지를 먼저 scan해서 @Component 를 가진 클래스의 객체 생성 -->
<context:component-scan base-package="controller,logic,dao,aop" />

<!-- web 환경에서 객체 주입을 위한 설정 : @Autowired,@Controller... 기능 사용  -->
<mvc:annotation-driven />

<!-- AOP 기능 수행 하도록 설정 -->
<aop:aspectj-autoproxy />

<!-- "viewResolver" 뷰결정자 : jsp 페이지의 위치 지정  -->
<bean id="viewResolver"
     class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass">
     <value>org.springframework.web.servlet.view.JstlView</value>
  </property>
  
<!-- item/list : WEB-INF/view/item/list.jsp : 뷰 지정 -->
  <property name="prefix"><value>/WEB-INF/view/</value></property>
  <property name="suffix"><value>.jsp</value></property>
</bean>   

<!-- 파일 업로드 설정  
   요청시 enctype="multipart/form-data" 형식인 경우 작동.
   
   p:maxUploadSize="104854600" : 100M 최대 업로드 가능한 크기 설정.
   p:maxInMemorySize="10485460" : 10M까지는 메모리에 파일의 내용을 저장.  
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
 p:maxUploadSize="104854600" p:maxInMemorySize="10485460"></bean>

<!-- message 코드값을 저장한 properties 파일을 설정. : messages.properties
     message 처리를 위한 설정  -->
<bean id="messageSource"
  class="org.springframework.context.support.ResourceBundleMessageSource">
  <property name="basenames">
    <list><value>messages</value></list>
  </property>
</bean>

<!-- 예외처리 -->
<bean id="exceptionHandler" 
     class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <property name="exceptionMappings">
    <value>exception.LoginException=exception
           exception.ItemException=exception
    </value>
  </property>
</bean>
</beans>

📌 UserController.java 수정

package controller;

import java.util.List;
import java.util.Map;

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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import exception.LoginException;
import logic.Sale;
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) {
		ModelAndView mav = new ModelAndView();
		//회원 정보를 조회하여 user 이름으로 뷰 전달
		User user = service.getUser(id);
		//주문 정보를 조회하여 뷰에 전달
		List<Sale> salelist = service.salelist(id);
		mav.addObject("user", user); //사용자 정보
		mav.addObject("salelist", salelist); //주문 목록
		return mav;
	}
	@GetMapping({"update","delete"})
	public ModelAndView idCheckUser(String id, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		//회원 정보를 조회하여 user 이름으로 뷰 전달
		User user = service.getUser(id);
		mav.addObject("user", user);
		return mav;
	}
	@PostMapping("update")
	public ModelAndView idcheckUpdate (@Valid User user, BindingResult bresult, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		if(bresult.hasErrors()) {
			mav.getModel().putAll(bresult.getModel());
			bresult.reject("error.update.user");
			return mav;
		}
		//비밀번호 검증 : 로그인된 정보의 비밀번호로 검증.
		User loginUser = (User)session.getAttribute("loginUser");
		if(!loginUser.getPassword().equals(user.getPassword())) {
			mav.getModel().putAll(bresult.getModel());
			bresult.reject("error.login.password");
			return mav;
		}
		//비밀번호 일치인 경우 : DB에 내용을 수정
		try {
			service.userUpdate(user);
			//session에 로그인 정보 수정
			session.setAttribute("loginUser", user);
			mav.setViewName("redirect:mypage?id=" + user.getUserid());
		} catch (Exception e) {
			e.printStackTrace();
			throw new LoginException("고객 정보 수정 실패","update?id=" + user.getUserid());
		}
	return mav;
	}
	@PostMapping("delete")
	public ModelAndView idcheckdelete (String password,String userid, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		//관리자인 경우 탈퇴 불가
		if(userid.equals("admin")) throw new LoginException("관리자는 탈퇴가 불가능합니다.","mypage?id=" + userid);
		User loginUser = (User)session.getAttribute("loginUser"); //로그인된 비밀번호 검증
		if(!password.equals(loginUser.getPassword())) { //비밀번호 불일치
			throw new LoginException("비밀번호를 확인하세요.","delete?id=" + userid);
		} 
		 //로그인된 비밀번호 검증 : 일치 시
		 try { 
			service.userDelete(userid);
		} catch (Exception e) { //예외 발생
			e.printStackTrace();
			throw new LoginException("탈퇴시 오류 발생","delete?id=" + userid);
		} 
		 //탈퇴가 성공한 경우
	    if(loginUser.getUserid().equals("admin")) { //관리자가 탈퇴시
	    	mav.setViewName("redirect:../admin/list");
	    } else { //일반 사용자 본인 탈퇴
	    	mav.setViewName("redirect:login");
	    	session.invalidate(); //session 초기화
	    	return mav;
	    }
	    return mav;
	}
	@GetMapping("password")
	public String loginCheckPassword(HttpSession session) {
		return null;
	}
	/*
	 *  1. 로그인 검증
	 *  2. 파라미터값을 Map 객체에 저장 
	 *         @RequestParam : 요청 파라미터를 Map 객체로 저장하도록하는 어노테이션
	 *         req.put("password",password의 파라미터값)
	 *         req.put("chgpass",chgpass의 파라미터값)
	 *         req.put("chgpass2",chgpass2의 파라미터값)
	 *  3. 현재 비밀번호와 입력된 비밀번호 검증
	 *     불일치 : 오류메세지 출력, password 페이지 이동 
	 *  4. 일치 : db 수정
	 *  5. 성공 : 로그인 정보 변경, mypage 페이지 이동
	 *     실패 : 오류메세지 출력, password 페이지 이동       
	 */
	@PostMapping("password")
	public ModelAndView loginCheckPasswordRtn(@RequestParam Map<String, String> req, HttpSession session) {
		User loginUser = (User)session.getAttribute("loginUser"); //입력된 현재 비밀번호와 로그인된 정보의 비밀번호 일치 확인?
		//req.get("password") : 현재 비밀번호
		//loginUser.getPassword() : 등록된 비밀번호
		if(!req.get("password").equals(loginUser.getPassword())) {
			throw new LoginException("비밀번호 오류 입니다.", "password");
		}
		//비밀번호가 일치하는 경우
		ModelAndView mav = new ModelAndView();
		try {
			//loginUser.getUserid() : 로그인 사용자 아이디
			//req.get("chgpass") : 변경할 비밀번호
			service.userChgPass(loginUser.getUserid(), req.get("chgpass")); //db 변경 완료
			loginUser.setPassword(req.get("chgpass")); //session의 loginUser객체의 비밀번호 수정
			mav.addObject("message","비밀번호가 변경 되었습니다.");
			mav.setViewName("redirect: login");
		} catch (Exception e) { //예외 발생
			e.printStackTrace();
			throw new LoginException("비밀번호 수정 시 db 오류 발생","password");
		} 
		return mav;
	}
	/*
	 * "{url}search" : *search 인 요청인 경우 호출되는 메서드
	 * @PathVariable String url :{url}값을 매개변수로 전달.
	 * 
	 * <http://localhost:8088/springmvc1/user/idsearch>
	 * url : id 값 저장
	 * 
	 * <http://localhost:8088/springmvc1/user/pwsearch>
	 * url : pw 값 저장
	 */
	@PostMapping("{url}search")
	public ModelAndView search(User user, BindingResult bresult, @PathVariable String url) {
		ModelAndView mav = new ModelAndView();
		String code = "error.userid.search"; //아이디를 찾을 수 없습니다.
		String title = "아이디";
		if(user.getEmail() == null || user.getEmail().equals("")) { //email 값이 없을 때.
			//rejectValue : 프로퍼티 별(컬럼별)로 오류 메세지 저장
			// <form:errors path="email" /> 영역에 오류 메세지 출력
			bresult.rejectValue("email", "error.required"); //@Valid에서 처리해주는 방식.
		}
		if(user.getPhoneno() == null || user.getPhoneno().equals("")) {
			// <form:errors path="phoneno" /> 영역에 오류 메세지 출력
			bresult.rejectValue("phoneno", "error.required"); //message.properties에서 처리.
		}
		if(url.equals("pw")) {
			title = "비밀번호";
			code = "error.password.search"; //비밀번호를 찾을 수 없습니다. 메세지의 코드값
			if(user.getUserid() == null || user.getUserid().equals("")) {
				bresult.rejectValue("userid", "error.required");
			}
		}
		if(bresult.hasErrors()) { //rejectValue 함수로 오류가 존재
			mav.getModel().putAll(bresult.getModel());
			return mav;
		}
		//정상적인 입력인 경우
		**String result = null;
			//result : 사용자 id, 또는 비밀번호 값
			//user : 화면에서 입력된 파라미터 값 저장 (email. phoneno, userid)
			result = service.getSearch(user,url);
			if(result == null) {
				bresult.reject(code);
				mav.getModel().putAll(bresult.getModel());
				return mav;
			}**
		mav.addObject("result",result);
		mav.addObject("title",title);
		mav.setViewName("/user/search"); //  /WEB-INF/view/user/search.jsp 
		return mav;
	}
}