컨트롤러 메소드로 오는 파라미터가 의도한대로 잘 넘어오는지 콘솔로 확인하고 싶습니다.
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로 바꾸면 된다)