본문 바로가기
교육/Spring

Spring 개발자 수업 99일차 - AOP 적용한 게시판 만들기

by yhyuk 2021. 8. 17.
728x90
반응형

AOP 적용한 게시판 만들기

- AOP를 적용해서 게시판 업무인 로그인, 로그아웃, 목록보기, 글쓰기, 글보기를 만들어보자.

- 각 기능 구현은 따로 하지않을 예정(이미 게시판 수업에서 진행했음)

[ 준비 작업 ]

1. 새 프로젝트 생성
- SpringWebAOPTest > "com.test.spring"

2. pom.xml
- 자바 버전, 스프링 버전 수정
- jar x 3개 (AOP) 

3. web.xml
- 확장자변경(*.action)

4. root-context.xml
- MyBatis(X)
- log4j(X)

5. servlet-context.xml
- tiles(X)
- AOP(O) 

6. 파일 생성
- AOPController.java       // 컨트롤러
- Service.java             // 주업무 객체
- Cross.java               // 보조업무 객체
- result.jsp               // 뷰
- DAO.java
- DTO.java

 

[ pom.xml ]

- AOP와 관련된 jar 파일 설정하기

<!-- AOP -->
<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>

 

[ servlet-context.xml ]

- 하단에 위치한 Namespaces 클릭 후 aop를 체크하여 설치한다.

- aop를 체크한 뒤 Source에 돌아오면 aop가 자동적으로 설치된걸 확인할 수 있다.

- beans 태그안에 <aop:aspectj-autoproxy />를 추가한다.

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

	<!-- @Controller와 같은 어노테이션을 사용 가능하게 해주는 선언 -->
	<annotation-driven />
	
	<!-- AOP 설정 > AOP 작업을 어노테이션을 사용할 수 있게 해주는 선언 -->
	<aop:aspectj-autoproxy />
	
	<!-- 단축 경로 사용 -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- 뷰 -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<!-- @Controller 어노테이션을 사용하는 클래스들이 들어있는 최상위 패키지 지정 -->
	<context:component-scan base-package="com.test.spring" />
	
	
</beans:beans>

 

[ AOPController.java ] 

- 주 업무 객체를 생성해 각 페이지 별 업무 분산(위임)하기

- 목록보기(list), 글 쓰기(memberadd), 글 보기(memberview), 로그인(login), 로그아웃(logout)

- 글 쓰기와 글보기에 member를 붙인 이유는 나중에 로그인한 회원만 접속하기 위해 주 업무를 따로 지정하기 위해서 이다.

@Controller
public class AOPController {

	// 주 업무 객체 Service 생성
	@Autowired
	private Service service;
	
	// 목록
	@RequestMapping(value = "/list.action", method = { RequestMethod.GET })
	public String list(HttpServletRequest req, HttpServletResponse resp, HttpSession session) {

		List<DTO> list = service.list();
		
		return "result";
	}
	
	// 쓰기
	@RequestMapping(value = "/add.action", method = { RequestMethod.GET })
	public String memberadd(HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
		
		int result = service.add();
		
		return "result";
	}
	
	// 보기
	@RequestMapping(value = "/view.action", method = { RequestMethod.GET })
	public String memberview(HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
		
		DTO dto = service.get();
		
		return "result";
	}
	
	// 로그인
	@RequestMapping(value = "/login.action", method = { RequestMethod.GET })
	public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
		
		// 회원 인증 구현
		session.setAttribute("id", "hong"); // 인증 티켓 발급 > 로그인
		
		return "result";
	}
	
	// 로그아웃
	@RequestMapping(value = "/logout.action", method = { RequestMethod.GET })
	public String logout(HttpServletRequest req, HttpServletResponse resp, HttpSession session) {
		
		// 로그아웃 성공
		session.removeAttribute("id");
		
		return "result";
	}
	
}

 

[ Service.java ]

- 주 업무 객체

- 따로 기능 구현은 하지 않았습니다.

// 원래는 어노테이션이 그냥 @Service지만, Class이름이랑 동일하여 충돌나기 떄문에 풀네임....
@org.springframework.stereotype.Service
public class Service {
	
	@Autowired
	private DAO dao;
	
	// 주 업무: 목록보기
	public List<DTO> list() {
		return dao.list();
	}
	
	// 주 업무: 글 쓰기
	public int add() {
		return dao.add();
	}

	// 주 업무: 글 보기
	public DTO get() {
		return dao.get();
	}

}

 

[ DAO.java ]

- 저장소 역할을 하며 확인을 위해 print만 넣었습니다. 

- 따로 기능 구현은 하지 않았습니다. 

@Repository
public class DAO {

	public List<DTO> list() {
		System.out.println("list()");
		return null;
	}

	public int add() {
		System.out.println("add()");
		return 0;
	}

	public DTO get() {
		System.out.println("get()");
		return null;
	}

}

 

[ Cross.java ]

- 보조 업무 객체

- 주 업무 객체(Service)에 연결 하기.

- 보조 업무(before, after) 만들기 > 주 업무 실행 시 마다 콘솔화면에 print 출력

@Aspect // 보조 업무 객체 자격 부여
@Component // 의존 주입 대상
public class Cross {
	
	// 주 업무 지정 -> 포인트 컷 지정하기 -> 주 업무 객체 연결
	@Pointcut("execution(public * com.test.spring.Service.*(..))")
	public void pc1() {
		// 구현X
	}
	
	// 보조 업무 생성 + 주 업무 결합(Advice)
	@Before("pc1()")
	public void m1() {
		System.out.println("before 보조 업무를 실행합니다.");
	}
	
	@After("pc1()") 
	public void m2() {
		System.out.println("after 보조 업무를 실행합니다.");
	}

}

 

[ Auth.java ]

- 보조 업무 객체

- 주 업무 객체(Service)에 연결 하기.

- 보조 업무(before로그인 여부 확인) 만들기 > 비 로그인 시 > 팝업창 알림 띄우기

@Aspect
@Component
public class Auth {
	
	// 주 업무 지정 - 글 쓰기(memberadd), 글 보기(memberview)
	@Pointcut("execution(public String com.test.spring.AOPController.member*(..))")
	public void member() {}
	
	// 보조 업무 지정 - 글 쓰기에 접속한 사람이 로그인을 했는지 유무?
	// -> session 필요... -> JoinPoint	
	@Before("member()")
	public void check(JoinPoint joinPoint) {		
				
		// 보조 업무 객체 내에서 request, response, session 등을 얻어오는 방법!!
		HttpServletResponse resp = (HttpServletResponse)joinPoint.getArgs()[1];
		HttpSession session = (HttpSession)joinPoint.getArgs()[2];
		
		// 미 인증 사용자 일때.. 
		if (session.getAttribute("id") == null) {
			try {
				
				resp.setCharacterEncoding("UTF-8");
				PrintWriter writer = resp.getWriter();
				
				writer.print("<html>");
				writer.print("<head>");
				writer.print("<meta charset='UTF-8'>");
				writer.print("</head");
				writer.print("<body>");
				writer.print("<script>");
				writer.print("alert('회원 전용 기능입니다.');");
				writer.print("location.href='/spring/list.action';");
				writer.print("</script>");
				writer.print("</body>");
				writer.print("</html>");
				
				writer.close();
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}

}

 

[ result.jsp ]

- 결과 페이지

<body>
   	<h1>결과 페이지</h1>
   	
   	
   	<div><a href="/spring/list.action">목록보기</a></div>
   	<div><a href="/spring/add.action">글쓰기(회원전용)</a></div>
   	<div><a href="/spring/view.action">글보기</a></div>
   	<div><a href="/spring/login.action">로그인</a></div>
   	<div><a href="/spring/logout.action">로그아웃</a></div>
    
   	<hr />
   	
   	<c:if test="${ empty id }">로그인 전입니다.</c:if>
   	<c:if test="${ not empty id }">${ id } 로그인 상태입니다.</c:if>
</body>

 

[ 결과 화면 ]

- 목록보기를 클릭했을 때

list.action

 

- 비 로그인 시 글쓰기/글보기를 클릭했을 때

add.action, view.action

 

- 로그인 시 현재 상태 변경

login.action

 

[ 정리 ]

  1) AOP를 적용을 위한 준비작업

  pom.xml   - dependency에 AOP 관련 jar 파일 3개 추가
  servlet-context.xml   - Namespace에서 aop 체크
  - bean태그 안에 <aop:aspectj-autoproxy /> 설정 (AOP 관련 어노테이션 사용을 위한 작업)

  2) 기본적인 AOP 작업은 이전 수업과 동일했으며, 새로 배운점은 Auth.java에서 보조 업무 지정을 할 때 글쓰기와 글보기에 접속한 사람의 로그인 유무 확인할 때 했던 작업이다.

   -> JoinPoint 

   -> getArgs()[0, 1, 2]   

   -> 0: req, 1: resp, 2: session 


MEMO>

# 회사에 입사하게 된다면 모르는것을 질문 할 때는 전체 코드를 복사해서 보여주는 형식으로 물어보면 큰일 난다!!
       -> 다른 사람 코드를 내가 보면 잘 모르듯이, 내 코드를 다른 사람이 보면 잘 모른다.
       -> 질문 하기전에 미리 준비 작업을 충분히 한 뒤 잘 정리해서 질문 할 것!

# 스프링은 자체 폴더가 굉장히 많이 존재하는데 스프링 관련 폴더에는 아이콘을 자세히 보면 'S' 표시가 존재한다.

# 마지막 프로젝트 작업 + 이력서, 자소서, 웹 포폴, PPT 포폴 준비... 

 

728x90
반응형

댓글