본문 바로가기
공부/프로그래밍

[SpringBoot2.x] Interceptor 안에 발생한 Exception, ControllerAdvice 로 관리하기.

by demonic_ 2018. 8. 4.
반응형

react + springboot 로 개발하던 중, axios 를 이용해 호출하는데 Interceptor에서 에러가 있어 Exception을 던졌는데, ControllerAdvice에서 캐치가 안되었다. 그래서 테스트를 해보니 조건부로 되었는데 아직 확실히는 못찾았다. 아마 CORS 때문에 그런거라 추측중이다.


- postman 등 이용해 호출 => ControllerAdvice 에 캐치 가능 

- react에 axios 호출 => ControllerAdvice에 캐치가 안됨.

그래서 Interceptor 에서 throw Exception 을 하지 않고 에러페이지로 전달하는 방식으로 처리했다.



여기서는 총 4개의 파일을 다룬다.

1. WebConfig.java => Interceptor 등록 클래스

2. TestInterceptor.java => Interceptor 실행 클래스

3. TestControllerAdvice.java => ControllerAdvice 설정 클래스

4. TestController => 테스트 하기위한 Controller 클래스




1. WebConfig.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
 
    @Autowired
    private TestInterceptor testInterceptor;
 
    // Interceptor에서 제외되는 URL 주소
    private static final String[] EXCLUDE_PATHS = {
            "/api/error",
    };
 
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(testInterceptor)
                .addPathPatterns("/api/**")
                .excludePathPatterns(EXCLUDE_PATHS);
    }
}
 
cs



2. TestInterceptor.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("@ Interceptor 진입");
        String param1 = request.getParameter("param1");
 
        if(param1 == null){
                // request 에 message와 exception클래스 명을 넣은다음 컨트롤러에서 맞는 컨트롤을 리턴하도록 처리했다.
            request.setAttribute("message""유효하지 않은 토큰입니다");
            request.setAttribute("exceptionClass""Exception");
            request.getRequestDispatcher("/api/error").forward(request, response);
        }else if(!param1.equals("test")){
            throw new Exception("파라미터 값이 잘못되었습니다.\n기대값: test, 받은값: " + param1);
        }
 
        return true;
    }
}
cs



3. TestControllerAdvice.java


1
2
3
4
5
6
7
8
9
10
11
12
13
@RestControllerAdvice
public class TestControllerAdvice {
 
    @ExceptionHandler(Exception.class)
    public Map handlerException(Exception e){
        e.printStackTrace();
        Map result = new HashMap();
        result.put("code""ERR");
        result.put("message""어드바이스 에러 테스트");
 
        return result;
    }
}
cs



4. TestController.java


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
32
33
34
35
36
37
38
39
40
41
42
43
@RestController
public class TestController {
 
    /**
     * 에러가 전달받아 처리하는 메서드.
     * @param request
     * @throws Exception
     */
    @CrossOrigin
    @GetMapping("/api/error")
    @ResponseBody
    public void apiError(HttpServletRequest request) throws Exception {
        String message = (String) request.getAttribute("message");
        String exception = (String) request.getAttribute("exceptionClass");
 
        if(exception.equals("UnauthorizedException")){
            throw new RuntimeException(message);
        } else if(exception.equals("CustomException")){
            throw new IOException(message);
        } else {
            throw new Exception(message);
        }
    }
 
 
    @CrossOrigin
    @GetMapping("/api/test")
    @ResponseBody
    public Map test(HttpServletRequest request){
        System.out.println("==================== 테스트");
 
        Enumeration<String> e = request.getHeaderNames();
        while(e.hasMoreElements()){
            String key = e.nextElement();
            System.out.println("============== " + key + " : " + request.getHeader(key));
        }
 
        Map result = new HashMap();
        result.put("code""0000");
        result.put("message""인증테스트 성공");
        return result;
    }
}
cs







해당 코드는 Github 에 올려두었습니다.

https://github.com/lemontia/IntercepterTest


반응형

댓글