Spring AOP적용해보기- Controller 파라미터

2022. 4. 4. 10:11Spring/Spring 실습






 

컨트롤러 메소드로 오는 파라미터가 의도한대로 잘 넘어오는지 콘솔로 확인하고 싶습니다.

freeList 메소드뿐만아니라 freeView에도 적용해본다면 다음과 같이 작성합니다.

 

 FreeBoardController.java

	private Logger logger= LoggerFactory.getLogger(this.getClass());
	
	@RequestMapping("/free/freeList.wow")
	public String freeList(Model model, @ModelAttribute("searchVO") FreeBoardSearchVO searchVO) {
		logger.info("searchVO : {}" , searchVO);   //freeList의 searchVO 확인
		List<FreeBoardVO> freeBoardList = freeBoardService.getBoardList(searchVO);
		model.addAttribute("freeBoardList", freeBoardList);
		return "free/freeList";
	}

	@RequestMapping("/free/freeView.wow")
	public String freeView(Model model, @RequestParam(required = true) int boNo) {
		logger.info("boNo : {}" , boNo);   //freeView의 boNo 확인
        //...
    }

freeList, freeView 뿐만 아니라 다른메소드, 또는 다른컨트롤러에도 적용하려고 한다면

그 때 그 때  logger.info() 라는 코드를 사용해야 합니다.  코드의 중복이 일어날 수 있습니다.

이를 AOP를 적용해서  코드의 중복을 없애고 controller단에서 파라미터를

콘솔에서 확인할 수 있도록 해 봅시다.

 

 

 

먼저 공통기능을 수행할 클래스를 만들자.

CommonControllerParameter.java    (com.study.common.util 패키지)

package com.study.common.util;
import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import com.study.free.web.FreeBoardController;
@Aspect
public class CommonControllerParameter {
	
	private Logger logger=LoggerFactory.getLogger(this.getClass());
		
	@Pointcut("execution(public * com.study.*.web..*(*,..))")     
	// public *,  com.study.*.web 에 모든 메소드 중 (*,..)  파라미터가 1개 이상인 메소드
	//com.study.*.service. context-main에 빈등록 했을 땐  모든 서비스단에 모든 메소드는 됐소  근데  왜  com.study.*.web은 안될까?
	// 여기서 또 중요한게 빈을 context-main에 하면  contextLoaderLister 빈은 
	// dispatcher 서블릿 빈인 @Controller에  접근 못해서... 그래서 aop controller단에 적용할거면 mvc-servlet에 
	private void publicTarget() {
	}
    
    // 또 생각 할게 proceed 전이냐 후에 따라 파라미터 값이 달라질 수 있음.  참조 잘 생각해보자.  메소드안에서 파라미터인 searchVO의 값을 set으로 바꿀 때 
    // 해당 메소드의 파라미터인 searchVO 값을  메소드 실행전에 콘솔에 찍냐, 메소드 실행후에 콘솔에 찍냐는 다르겠지
	@Around("publicTarget()")
	public Object parameter(ProceedingJoinPoint joinPoint) throws Throwable {
		Signature sig = joinPoint.getSignature();
		logger.info("실행 클래스 : {} " ,joinPoint.getTarget().getClass().getSimpleName());
		logger.info("실행 메소드 : {} " ,sig.getName());
		Object[] arr= joinPoint.getArgs();    //그 메소드의 파라미터들 
		// joinPoint.getArgs()은  메소드의 파라미터가 없어도 null을 return하지않음.  길이가 0인 배열 return==> null체크 안해줘도 됨 
		for(Object a : arr) {
        	//파라미터가 null일수도있으니까 체크  
            //메소드에는 매개변수가 정의 되어있지만 그 파라미터가 null로 올 때가 있음
            if(a ==null){
            } else if(!a.getClass().getSimpleName().equals("BindingAwareModelMap")) {     //BindingAwareModelMap은  Model 객체의 구현클래스이름
				logger.info("메소드의 파라미터 : {}" , a.toString());
			}
		}
		try {
			Object result = joinPoint.proceed();
			return result;
		} finally {		
		}
	}

}

@PointCut은 Controller에서 파라미터가 1개 이상인 메소드만 지정해줬다.

또 컨트롤러 메소드에서는 파라미터로 Model model이 있는데

이건  보고싶지않아서 if문으로 처리해줬다.

즉, 실제로 브라우저에서 넘어오는 파라미터(searchVO, boNo 등)들만 확인하려고 한다.

 

이제 CommonControllerParameter클래스를 빈 등록 하도록 하자.

빈 등록은 DispatcherServlet 설정파일이나 ContextLoaderListener 설정파일에서  등록할 수 있다.

다만 CommonControllerParameter 클래스의 빈이 Controller에 접근해서

Controller의 메소드 전후로  공통기능을 수행해야 한다.

이 때  빈을 ContextLoaderListenr에 등록한다면 Controller에 접근할 수 없다.

즉, Controller에 접근하려면 빈을 DispatcherServlet 설정파일에 등록해야한다.

 

 

mvc-servlet.xml  (DispatcherServlet.xml)

	<!-- 공통기능을 수행할 빈 생성 -->
 	<beans:bean id="commonControllerParameter"
		class="com.study.common.util.CommonControllerParameter"></beans:bean>
	<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

이렇게 설정했다면 FreeBoardController에서 log를 찍는 코드는 지워주도록 하자.

 

 

이제 /free/freeList.wow 및 여러URL로 요청하면 콘솔에 다음과같이 파라미터가 찍힌다. 

(DEBUG : 은 mybatis에서 기본적으로 찍히는 내용, 보고싶지 않다면

log4j.xml설정에서 level을 INFO로 바꾸면 된다)

freeList.wow로 요청
freeView.wow로 요청