티스토리 뷰

Programming/Spring

ControllerAdvice

Albothyl 2019. 4. 1. 12:29

특정 범위에 포함된 모든 Controller에서 발생하는 Exception을 전역처리할 때 ControllerAdvice를 사용한다.

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

@Slf4j
// 일반적인 Controller의 전역 exception 처리
@ControllerAdvice(basePackages="com.java,some",
                  basePackageClasses={ Some1.class, Some2.class }, 
                  assignableTypes=SomeController.class
                  annotations=SomeAnnotation.class)
// or 더 구체적으로 Controller의 특징을 표현할 경우
@RestControllerAdvice(basePackages="com.java,some",
                  basePackageClasses={ Some1.class, Some2.class }, 
                  assignableTypes=SomeController.class
                  annotations=SomeAnnotation.class)
// controllerAdvice의 우선순위가 필요한 경우.
@Order(Ordered.LOWEST_PRECEDENCE)
public class ExceptionHandler {
	
	@Value("${redirect.web.url}")
	private String redirectWebUrl;

	@ExceptionHandler(value = { XXXX_Exception.class })
	public ResponseEntity<Object> handleAccessDeniedException(Exception exception, WebRequest request) {
		log.error("###### Exception catch: {}", exception.getMessage());
		return new ResponseEntity<>("Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
	}

	@ExceptionHandler(XXXX_Exception.class)
	public ModelAndView handleRemainAllException(Exception execption) {
		log.error("Landing Link Exception : {}", execption.getMessage(), execption);
		return new ModelAndView("redirect:" + redirectWebUrl);
	}
    
	// 하나의 handler method에서 특정 조건에 따라 modelAndVeiw와 Json을 리턴하는 경우
	@ExceptionHandler(XXXX_Exception.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public ModelAndView internalError(Exception exception, HttpServletRequest request) {
		if (isWebRequest(request)) {
			return createErrorMessageJsonView(exception.getMessage());
		}

		return new ModelAndView("forward:/resources/err500.html");
	}

	private boolean isWebRequest(HttpServletRequest request) {
		if (StringUtils.startsWith(request.getRequestURI(), "/web")) {
			return true;
		}

		return false;
	}

	@NotNull
	private ModelAndView createErrorMessageJsonView(String exceptionMessage) {
	    //ModelAndView의 name이 "jsonView"이면 jackson은 modelAndView를 json으로 변환해서 리턴한다. 아래 설정 참조
		ModelAndView modelAndView = new ModelAndView("jsonView");
		modelAndView.addObject("message", exceptionMessage);
		return modelAndView;
	}
}


//SomeConfig Class: modelAndView를 json으로 변환해서 리턴하기 위한 설정
@Bean
public MappingJackson2JsonView jsonView() {
	return new MappingJackson2JsonView();
}

특정 Controller에 종속되어 exception을 처리할 경우, Controller에 handler 메소드를 만들고 @ExceptionHnalder annotation으로 Exception을 처리를 지정한다.

@Controller
public class SomeController {
    ...
        
    @ExceptionHandler(value = { IllegalArgumentException.class, IllegalStateException.class })
    public ModelAndView someControllerExceptionHandler(Exception exception) {
        final ModelAndView modelAndView = new ModelAndView("/error/404");
        modelAndView.addObject("exception", exception);
        
        return modelAndView;
    }
}

'Programming > Spring' 카테고리의 다른 글

Enhanced Registrar  (0) 2019.04.12
@Enable + Registrar  (0) 2019.04.11
Request Param Validate (JSR-303)  (0) 2019.03.30
AOP  (0) 2019.03.27
Request Proxy  (0) 2019.03.27
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함