BankApp - Intercepter 활용

Gun·2023년 9월 22일

Spring Boot - BankApp

목록 보기
20/25
💡 학습목표
   1. AuthIntercepter 구현 클래스 만들기 
   2. WebMvcConfig 구현 클래스 만들기 
   3. 코드 수정 - 인증 처리 일괄 적용 하기  (AccountController 수정) 
HandlerInterceptor 는 spring boot MVC 에서 제공하는 인터셉터로
AOP 개념과는 다르게 서블릿 필터처럼 동작 합니다. 
즉, 클라언트의 요청이 컨트롤러에 도달하기 전에 인터셉터 요청/응답을 가로채어 필요한 로직을 수행할 수 있습니다.

반면, AOP(Aspect-Orented Programming)은 관점 지향 프로그래밍으로 횡단 관심사를
핵심 관심사(core concerns) 분리하여 구현하는 기법입니다.

따라서 HandlerInterceptor 는 AOP 와는 개념적으로 다르지만 AOP 유사한 효과를 얻을 수 있는 기능 입니다.

1. AuthIntercepter 구현 클래스 만들기

AuthInterceptor.java


package com.tencoding.bank.config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.tencoding.bank.handler.exception.CustomRestfulException;
import com.tencoding.bank.repository.model.User;
import com.tencoding.bank.util.Define;

@Component // IoC 대상 - 싱글톤으로 관리 된다.
public class AuthInterceptor implements HandlerInterceptor{
	
	
	// Controller 들어가기 전에 호출 되는 메서드
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle() 메서드 호출");
		HttpSession session = request.getSession();
		User principal = (User)session.getAttribute(Define.PRINCIPAL);
		if(principal == null) {
			throw new CustomRestfulException("로그인을 먼저 해주세요.", HttpStatus.UNAUTHORIZED);
		}
		return true;
	}
	
	// 뷰가 렌더링 되기 전에 호출되는 메서드
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}

//	// 요청 처리가 완료된 후, 즉, 뷰 렌더링이 완료된 후에 호출되는 메서드
//	@Override
//	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
//			@Nullable Exception ex) throws Exception {
//	}
	
}

2. WebMvcConfig 구현 클래스 만들기

WebMvcConfig.java


package com.tencoding.bank.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component // IoC 대상 - 2개 이상의 빈을 등록해야 할 때 사용
public class WebMvcConfig implements WebMvcConfigurer{
	
	// DI 처리
	@Autowired
	private AuthInterceptor authInterceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(authInterceptor)
		.addPathPatterns("/account/**");
	}
	
}

3. 코드 수정 - 인증 처리 일괄 적용 하기 (AccountController 수정)

AccountController.java


package com.tencoding.bank.controller;

import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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 com.tencoding.bank.dto.DepositFormDto;
import com.tencoding.bank.dto.HistoryDto;
import com.tencoding.bank.dto.SaveFormDto;
import com.tencoding.bank.dto.TransferFormDto;
import com.tencoding.bank.dto.WithDrawFormDto;
import com.tencoding.bank.handler.exception.CustomRestfulException;
import com.tencoding.bank.repository.model.Account;
import com.tencoding.bank.repository.model.User;
import com.tencoding.bank.service.AccountService;
import com.tencoding.bank.util.Define;

@Controller
@RequestMapping("/account")
public class AccountController {
	
	@Autowired
	private HttpSession session;
	@Autowired
	private AccountService accountService;
	
	// 계좌 목록 페이지
	// http://localhost:80/account/list
	
	@GetMapping("/list")
	public String list(Model model) {
		User user = (User)session.getAttribute(Define.PRINCIPAL);
		
		List<Account> accountList = accountService.readAccountList(user.getId());
		
		if(accountList.isEmpty()) {
			model.addAttribute("accountList", null);
		} else {
			model.addAttribute("accountList", accountList);
		}
		
		return "account/list";
	}
	
	
	// 계좌 생성 페이지
	// http://localhost:80/account/save
	// /account/save - 화면 이동
	/**
	 * 계좌 생성 페이지 이동
	 */
	@GetMapping("/save")
	public String save() {
		// 1. 인증 여부 확인

		
		return "account/save";
	}
	
	/**
	 * 계좌 생성 로직 구현
	 * @return
	 */
	@PostMapping("/save")
	public String saveProc(SaveFormDto saveFormDto) {
		// 1. 인증 검사
		User user = (User)session.getAttribute(Define.PRINCIPAL);
		// 2. 유효성 검사
		if(saveFormDto.getNumber() == null
				|| saveFormDto.getNumber().isEmpty()) {
			throw new CustomRestfulException("계좌번호를 입력해주세요.", HttpStatus.BAD_REQUEST);
		}
		
		if(saveFormDto.getPassword() == null
				|| saveFormDto.getPassword().isEmpty()) {
			throw new CustomRestfulException("비밀번호를 입력해주세요.", HttpStatus.BAD_REQUEST);
		}
		
		if(saveFormDto.getBalance() == null 
				|| saveFormDto.getBalance() < 0) {
			throw new CustomRestfulException("잘못된 입력입니다.", HttpStatus.BAD_REQUEST);
		}
		// 3. 서비스 호출
		accountService.creatAccount(saveFormDto, user.getId());
		return "redirect:/account/list";
	}
	
	// 출금 페이지
	// http://localhost:80/account/withdraw
	
	@GetMapping("/withdraw")
	public String withdraw() {
		// 1. 인증 여부 확인

		
		return "account/withdraw";
	}
	
	// body -> String --> amount=1000&wAccountId=10&......
	@PostMapping("/withdraw")
	public String withdrawProc(WithDrawFormDto withDrawFormDto) {
		// 1. 인증 여부 확인
		User user = (User)session.getAttribute(Define.PRINCIPAL);
		
		// 2. 유효성 검사
		if(withDrawFormDto.getAmount() == null) {
			throw new CustomRestfulException("금액을 입력해주세요.", HttpStatus.BAD_REQUEST);
		}
		if(withDrawFormDto.getAmount() <= 0) {
			throw new CustomRestfulException("잘못된 금액입니다.", HttpStatus.BAD_REQUEST);
		}
		if(withDrawFormDto.getWAccountNumber() == null
				|| withDrawFormDto.getWAccountNumber().isEmpty()) {
			throw new CustomRestfulException("출금 계좌번호를 확인해주세요.", HttpStatus.BAD_REQUEST);
		}
		if(withDrawFormDto.getWAccountPassword() == null
				|| withDrawFormDto.getWAccountPassword().isEmpty()) {
			throw new CustomRestfulException("출금 계좌 비밀번호를 확인해주세요.", HttpStatus.BAD_REQUEST);
		}
		
		accountService.updateAccountWithdraw(withDrawFormDto, user.getId());
		
		
		return "redirect:/account/list";
	}
	
	// 입금 페이지
	// http://localhost:80/account/deposit
	
	@GetMapping("/deposit")
	public String deposit() {
		// 1. 인증 여부 확인

		return "account/deposit";
	}
	
	@PostMapping("/deposit")
	public String depositProc(DepositFormDto depositFormDto) {
		// 1. 인증 여부 확인

		// 2. 유효성 검사
		if(depositFormDto.getAmount() == null) {
			throw new CustomRestfulException("금액을 입력해주세요.", HttpStatus.BAD_REQUEST);
		}
		if(depositFormDto.getAmount() <= 0) {
			throw new CustomRestfulException("잘못된 금액입니다.", HttpStatus.BAD_REQUEST);
		}
		if(depositFormDto.getDAccountNumber() == null
				|| depositFormDto.getDAccountNumber().isEmpty()) {
			throw new CustomRestfulException("입금 계좌번호를 입력해주세요.", HttpStatus.BAD_REQUEST);
		}
		
		accountService.updateAccountDeposit(depositFormDto);
		return "redirect:/account/list";
	}
	
	// 이체 페이지
	// http://localhost:80/account/transfer
	
	@GetMapping("/transfer")
	public String transfer() {
		// 1. 인증 여부 확인

		return "account/transfer";
	}
	
	
	// 1. 이체 금액 0원 이상 입력 여부 확인
	// 2. 출금 계좌 번호 입력 여부 확인
	// 3. 입금 계좌 번호 입력 여부 확인
	// 4. 출금 계좌 비밀 번호 입력 여부 확인
	
	@PostMapping("/transfer")
	public String transferProc(TransferFormDto transferFormDto) {
		// 1. 인증 여부 확인
		User user = (User)session.getAttribute(Define.PRINCIPAL);
		
		// 2. 유효성 검사
		if(transferFormDto.getAmount() == null) {
			throw new CustomRestfulException("이체 금액을 입력해주세요.", HttpStatus.BAD_REQUEST);
		}
		if(transferFormDto.getAmount() <= 0) {
			throw new CustomRestfulException("이체 금액이 0원 이하일 수 없습니다.", HttpStatus.BAD_REQUEST);
		}
		if(transferFormDto.getWAccountNumber() == null
				|| transferFormDto.getWAccountNumber().isEmpty()) {
			throw new CustomRestfulException("출금 계좌번호를 확인해주세요.", HttpStatus.BAD_REQUEST);
		}
		if(transferFormDto.getDAccountNumber() == null
				|| transferFormDto.getDAccountNumber().isEmpty()) {
			throw new CustomRestfulException("입금 계좌번호를 확인해주세요.", HttpStatus.BAD_REQUEST);
		}
		if(transferFormDto.getWAccountPassword() == null
				|| transferFormDto.getWAccountPassword().isEmpty()) {
			throw new CustomRestfulException("출금 계좌 비밀번호를 확인해주세요.", HttpStatus.BAD_REQUEST);
		}
		// 3. 서비스 호출
		accountService.updateAccountTransfer(transferFormDto, user.getId());
		
		return "redirect:/account/list";
	}
	
	// TODO - 수정하기
	// 상세 보기 페이지
	// http://localhost:80/account/detail/1?type=all,deposit,withdraw
	@GetMapping("/detail/{id}")
	public String detail(@PathVariable Integer id,
			@RequestParam(name = "type", defaultValue = "all", required = false) String type, Model model) {
		// Todo - 주소 설계 추가하기
		
		// 1. 인증 여부 확인
		User user = (User)session.getAttribute(Define.PRINCIPAL);
				
		// 서비스 호출
		Account account = accountService.readAccount(id);
		List<HistoryDto> historyList = accountService.readHistoryListByAccount(id, type);
		model.addAttribute("principal", user);
		model.addAttribute("account", account);
		model.addAttribute("historyList", historyList);
		System.out.println(historyList);
		// Account <-
		// List -> History <-
		
		
		return "account/detail";
	}
}

0개의 댓글