Java/Spring

@ControllerAdvice

Z_Z 2023. 8. 28. 09:50
반응형

@ControllerAdvice

Spring 에서 공통 및 전역적으로 예외처리, ModelAttribute 등 핸들링 하기 위해

@ControllerAdvice 어노테이션을 사용할 수 있다.

모든 @Controller 또는 @RestController 에 적용되는 컴포넌트이다.

  1. 예외 처리(@ExceptionHandler)
  2. 바인딩 설정(@InitBinder)
  3. 모델 속성 추가(@ModelAttribute)

 

예외처리(@ExceptionHandler)

예외처리를 위한 try-catch 문을 사용하는게 아닌 전역적으로 예외처리를 하고 싶을때 사용한다.

 

package com.obo.controller.global;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionController {
	
	@ExceptionHandler(NullPointerException.class)
	public ResponseEntity<String> nullHandler(NullPointerException ex) {
		return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("NULL 오류 발생");
	}
	
	@ExceptionHandler(Exception.class)
	public ResponseEntity<String> exceptionHandler(Exception ex){
		return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Exception 서버 에러");
	}
}

 

@GetMapping(value = "/main")
public String testMain() {
    System.out.println("testCount : "+testService.testCount());
    String a = null;
    a.substring(1);
    return "test";
}

 

String 변수에 null 을 넣고 해당 String 변수의 값에 접근했을 때 NullPointerException 서버 에러가 발생한다.

전역적으로 @ControllerAdvice 를 사용했고 @ExceptionHandler 에 NullPointerException.class 를 설정했다.

 

결과

 

 

모델 속성 추가(@ModelAttribute)

공통적으로 Front 에 Model 값을 전달해야 할때 사용한다.

 

package com.obo.controller.global;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice
public class GlobalExceptionController {
	
	@ModelAttribute("testValue")
	public String testValue() {
		return "testModelValue";
	}
}

 

window.addEventListener("DOMContentLoaded", (event) => {
    console.log('global model : ',/*[[${testValue}]]*/ "");
});

 

testValue 는 @ModelAttribute 에 설정한 변수명이 된다.

본인은 Thymeleaf 를 사용했기 때문에 /*[[${}]]*/ 문법을 사용했고 아래 결과를 정상적으로 받을 수 있다.

 

결과

 

 

 

사용하게된 계기

본인은 공통적으로 사용하는 변수값을 체크하여 특정 View 에 공통적으로 데이터를 넘겨야 할 상황이 있었다.

그래서 @ControllerAdvice 를 사용했다.

@ControllerAdvice 와 @ModelAttribute 어노테이션을 사용하여 요청 별로 각 Pakcage 경로마다

공통 속성을 추가해야 할 상황에 적절하다.

 

아래와 같이 CommonControllerAdvice 라는 클래스를 생성한다.

 

package com.youth.market.system.handler;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice(basePackages = {"com.youth.market.controller.common"})
public class CommonControllerAdvice {
	
	@ModelAttribute("isModelTest")
	public String addTest(HttpServletRequest request) {
		return "test";
	}
	
}

 

@ControllerAdvice(basePackages = {"com.youth.market.controller.common"})

위와 같이 @ControllerAdvice 의 basePakcages 속성을 통해 공통적으로 값을 넘길 클래스들의 Pakcage  경로를

설정할 수 있다.

 

아래는 ControllerAdvice 어노테이션 인터페이스이다.

 


@ModelAttribute("isModelTest")
public String addTest(HttpServletRequest request) {
    return "test";
}

@ModelAttribute 를 통해 설정한 basePakcages 에 공통 데이터를 전달할 수 있다.

isModelTest 라는 변수 이름으로 test 라는 String 문자열이 공통으로 전달된다.

 

결과

본인은 Thymeleaf 템플릿 엔진을 사용했으므로 /*[[${isModelTest}]]*/ ""; 형태이다.

반응형