[Spring 3.2] Interceptor에서 Controller의 어노테이션 체크하기

Published on: 2013. 12. 2. 19:45 by krespo

인증이 필요한 서비스를 개발할 경우, Interceptor에서 로그인 유무를 확인하는 로직을 추가하여 각 컨트롤러에 인증 로직을 추가로 작성하지 않도록 할수 있습니다.


만약 이때 어떤 컨트롤러의 메소드는 로그인을 체크하고 어떤 컨트롤러의 메소드에는 로그인을 체크하지 않도록 하려면 어떻게 해야 할까요?


스프링 3.2 부터는 mvc:interceptor 부분에 exclude-mapping 이라는 엘리먼트가 추가되어 기존의 스프링 버전보다 쉽게 인터셉터의 적용을 제외시킬수 있습니다.

<mvc:interceptor> <mvc:mapping path="/**"/> <exclude-mapping path="/info/**"/> <bean class="net.krespo.interceptor.LoginCheckInterceptor" /> </mvc:interceptor>

이렇게 exclude-mapping을 사용하면 LoginCheckInterceptor는 /info/ 로 시작하는 컨트롤러에 인터셉터 적용을 제외 시킬수 있습니다.


그런데 만약 /info/my는 로그인 인터셉터를 수행시키고 /info/test는 로그인 인터셉터를 수행시키려면 어떻게 해야할까요?


물론 exclude-mapping을 여러개 등록하면 되지만 로그인이 필요하지 않은 컨트롤러가 생길때마다 exclude-mapping을 선언하는것이 귀찮게 느껴질겁니다.


이럴때는 임의의 어노테이션을 생성하여 인증이 필요하지 않은 컨트롤러의 메소드에 어노테이션을 붙이고, 어노테이션 유무를 인터셉터에서 확인하여 로그인을 할지 안할지를 하면 좀더 편하게 개발을 진행할 수 있을것 같습니다.


이제부터 본격적으로 인터셉터에서 컨트롤러의 어노테이션을 체크하는 방법을 알아보도록 하겠습니다.


1. 어노테이션 생성

package net.krespo.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoLoginCheck {
}

NoLoginCheck라는 어노테이션을 생성하였습니다. 이 어노테이션을 사용하여 어노테이션을 메소드에 추가를 했으면 로그인 체크를 하고, 어노테이션이 없으면 로그인 체크를 하지 않도록 할것입니다.


2. 컨트롤러에 어노테이션 추가


@Controller
public class MyController {
	
	@RequestMapping("/my/info")
	@NoLoginCheck 
	public ModelAndView myInfo(){
		...
	}
	
}

3. Interceptor에서 어노테이션 체크하기

public class LoginInterceptor extends WebContentInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {
		//@NoCheckLogin 어노테이션이 컨트롤러에 사용되었는지 체크함
		NoCheckLogin usingAuth = ((HandlerMethod) handler).getMethodAnnotation(NoCheckLogin.class);

		//NoCheckLogin 어노테이션이 없음으로 무조건 로그인 체크
		if(usingAuth == null) {
			//TODO 로그인 체크
		}
		//NoCheckLogin 어노테이션이 없음으로 로그인 체크 하지 않음
		else {
			//TODO 추가작업
		}
	}	
}

가장 중요한 부분은 preHandler 메소드의 handler Object를 HandlerMethod로 타입케스팅 하는 부분입니다. 이렇게 HandlerMethod로 바꾼 handler오브젝트의 getMethodAnnotation을 통해서 앞으로 실행될 컨트롤러의 메소드에 해당 어노테이션이 추가가 되었는지 안되어 있는지를 확인할 수 있습니다.


위 내용은 스프링 3.2에서 확인해 보았습니다. 그러나 스프링 3.0에서는 해당 handler Object를 HandlerMethod의 오브젝트가 아닌 앞으로 실행시킬 컨트롤러오브젝트(위의 예제에서는 LoginController)가 반환이 됨으로 위의 코드는 3.0에서는 사용할 수가 없습니다~(3.1에서는 체크를 해보지 못했습니다. 3.1에서 사용해 보신 분께서는 댓글로 알려주세요~^^)

행인 | 2016.03.14 14:07 | PERMALINK | EDIT/DEL | REPLY
interface명은 NoLoginCheck 이고, class 에서는 NoCheckLogin 으로 쓰고있어요. 오타발견
행인 | 2016.03.14 17:01 | PERMALINK | EDIT/DEL | REPLY
스프링 4.2 로 테스트했는데, jsp에서 resources의 자원을 사용할 때 마찬가지로 cannot be cast to ~ 에러가 나네요. 빼면 정상인데.. 이상하죠? try catch 로 걸어두면 자원을 불러오긴하는데 콘솔에는 여전히 에러가 나와요
Name
Password
Homepage
Secret

[Spring 3.2] @ControllerAdvice를 이용한 익셉션 처리

Published on: 2013. 11. 29. 19:23 by krespo

스프링 프레임웍 3.2 이상부터 @ControllerAdvice라는 어노테이션이 추가 되었습니다. 이 어노테이션을 사용하면 간단하게 익셉션 발생시 작업을 처리할 수가 있습니다.


방법은 간단합니다. 설정파일에 아래와 같이 설정합니다. 아래의 설정 내용은 따로 설명하지 않겠습니다.

<annotation-driven />
<context:component-scan base-package="net.krespo" >

이후 적당한 위치에 클래스를 하나 생성하여 @ControllerAdvice를 붙여주면 됩니다.

package net.krespo.handler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;


@ControllerAdvice
public class AnnotationExceptionHandler {
	@ExceptionHandler(Exception.class)
	public void handleException(Exception e) {
		System.out.println("exception");
	}
	
	@ExceptionHandler(RuntimeException.class) 
	public ModelAndView handleRuntimeException(RuntimeException e) {
		ModelAndView mnv = new ModelAndView("exceptionHandler");
		mnv.addObject("data", e.getMessage());
		
		return mnv;
	}
}

클래스에는 @ControllerAdvice를 선언해 주고 각 메소드 마다 @ExceptionHandler라는 어노테이션으로 어떤익셉션을 처리할 것인지를 선언해 주면 됩니다.


익셉션을 처리하는 메소드는 익셉션 파라미터를 받을 수 있습니다. 그래서 개발자가 익셉션에 메세지를 담아서 던지면 해당 메세지를 각 핸들러 메소드에서 확인할수 있습니다.


또한 리턴값으로는 void부터 ModelAndView까지 다양하게 리턴할수 있어 익셉션을 처리하는데 편리하게 사용할 수 있습니다.

Name
Password
Homepage
Secret

[JUnit4] @FixMethodOrder를 사용한 테스트 메소드 실행 순서 결정하기

Published on: 2013. 11. 29. 18:53 by krespo

JUnit 4.11버전 부터 @FixMethodOrder 라는 어노테이션이 생겼습니다. 

이 어노테이션은 테스트 메소드의 실행 순서의 기준을 잡을수 있도록 해줍니다.


@FixMethodOrder는 3가지 정렬 옵션을 가지고 있습니다.

 속성

설명 

 MethodSorters.DEFAULT

HashCode를 기반으로 순서가 결정되기 때문에 사용자가 예측하기 힘듭니다.

 MethodSorters.JVM

JVM에서 리턴되는 순으로 실행됩니다. 때에 따라서 실행시 변경됩니다.

 MethodSorters.NAME_ASCENDING

메소드 명을 오름차순으로 정렬한 순서대로 실행됩니다.


위의 옵션은 테스트케이스에서 아래와 같이 사용하시면 됩니다.


@FixMethodOrder(MethodSorters.DEFAULT)
public class JunitOrderTest {
	@Test
	public void test1() {
		System.out.println("Test1 Run!!");
	}
	@Test
	public void test2() {
		System.out.println("Test2 Run!!");
	}
}

Name
Password
Homepage
Secret

[Redis] Redis GUI Tool - Redis Desktop Manager를 소개합니다

Published on: 2013. 11. 27. 17:17 by krespo

Oracle의 SQL Developer, MySQL의 MySQL WorkBench같이 Redis도 Redis Desktop Manager라는 툴이 존재합니다. 

Redis Desktop Manager는 Windows 뿐만 아니라 Linux, Mac OS X까지 지원해주고 있습니다.



설치하는 방법은 간단합니다.


다운로드 받은 exe파일을 더블클릭하면 간단하게 설치가 완료됩니다. 

설치가 완료된 후 Redis Desktop Manager를 실행해 보면 이런 화면이 뜨게 됩니다.



이 화면에서 왼쪽 하단에 있는 Add New Connection을 선택하여 Redis 서버의 정보를 입력합니다.



위의 화면에 레디스 서버 정보를 모두 입력하면 간단하게 서버가 추가가 됩니다.



추가된 서버를 더블클릭하게 되면 서버와 커넥션이 맺어지고 간단하게 Redis의 DB와 해당 DB에 들어가있는 데이터를 한눈에 파악할 수 있습니다.



뿐만 아니라 레디스 서버 정보에서 오른쪽 마우스클 클릭하면 Console 이란 메뉴가 나오는데 이메뉴를 선택하면 레디스 커맨드를 직업 입력할 수가 있습니다.



위에서 쓴 대로 기능 자체는 매우 심플합니다만 레디스 서버를 사용하기에는 크게 부족하지는 않는것 같습니다

Name
Password
Homepage
Secret