diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java index 1c81e3ef..0f072175 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java @@ -139,6 +139,9 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor throw new RuntimeException(e); } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof RuntimeException) { + throw (RuntimeException) e.getTargetException(); + } throw new RuntimeException(e); } } diff --git a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java index fe1a107c..46232382 100644 --- a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java +++ b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java @@ -20,6 +20,8 @@ import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate; import com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor; import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse; import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException; +import com.alibaba.csp.sentinel.slots.block.flow.FlowException; import org.junit.Test; @@ -29,7 +31,11 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertEquals; @@ -39,326 +45,403 @@ import static org.junit.Assert.assertEquals; */ public class SentinelRestTemplateTests { - @Test(expected = BeanCreationException.class) - public void testFbkMethod() { - new AnnotationConfigApplicationContext(TestConfig1.class); - } + @Test(expected = BeanCreationException.class) + public void testFbkMethod() { + new AnnotationConfigApplicationContext(TestConfig1.class); + } - @Test(expected = BeanCreationException.class) - public void testFbkClass() { - new AnnotationConfigApplicationContext(TestConfig2.class); - } + @Test(expected = BeanCreationException.class) + public void testFbkClass() { + new AnnotationConfigApplicationContext(TestConfig2.class); + } - @Test(expected = BeanCreationException.class) - public void testblkMethod() { - new AnnotationConfigApplicationContext(TestConfig3.class); - } + @Test(expected = BeanCreationException.class) + public void testblkMethod() { + new AnnotationConfigApplicationContext(TestConfig3.class); + } - @Test(expected = BeanCreationException.class) - public void testblkClass() { - new AnnotationConfigApplicationContext(TestConfig4.class); - } + @Test(expected = BeanCreationException.class) + public void testblkClass() { + new AnnotationConfigApplicationContext(TestConfig4.class); + } - @Test - public void testNormal() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - TestConfig5.class); - assertEquals("RestTemplate size was wrong", 1, - context.getBeansOfType(RestTemplate.class).size()); - } + @Test + public void testNormal() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + TestConfig5.class); + assertEquals("RestTemplate size was wrong", 1, + context.getBeansOfType(RestTemplate.class).size()); + } - @Test(expected = BeanCreationException.class) - public void testBlkMethodExists() { - new AnnotationConfigApplicationContext(TestConfig6.class); - } + @Test(expected = BeanCreationException.class) + public void testBlkMethodExists() { + new AnnotationConfigApplicationContext(TestConfig6.class); + } - @Test(expected = BeanCreationException.class) - public void testFbkMethodExists() { - new AnnotationConfigApplicationContext(TestConfig7.class); - } + @Test(expected = BeanCreationException.class) + public void testFbkMethodExists() { + new AnnotationConfigApplicationContext(TestConfig7.class); + } - @Test(expected = BeanCreationException.class) - public void testBlkReturnValue() { - new AnnotationConfigApplicationContext(TestConfig8.class); - } + @Test(expected = BeanCreationException.class) + public void testBlkReturnValue() { + new AnnotationConfigApplicationContext(TestConfig8.class); + } - @Test(expected = BeanCreationException.class) - public void testFbkReturnValue() { - new AnnotationConfigApplicationContext(TestConfig9.class); - } + @Test(expected = BeanCreationException.class) + public void testFbkReturnValue() { + new AnnotationConfigApplicationContext(TestConfig9.class); + } - @Test - public void testNormalWithoutParam() { - new AnnotationConfigApplicationContext(TestConfig10.class); - } + @Test + public void testNormalWithoutParam() { + new AnnotationConfigApplicationContext(TestConfig10.class); + } - @Test(expected = BeanCreationException.class) - public void testUrlClnMethod() { - new AnnotationConfigApplicationContext(TestConfig11.class); - } + @Test(expected = BeanCreationException.class) + public void testUrlClnMethod() { + new AnnotationConfigApplicationContext(TestConfig11.class); + } - @Test(expected = BeanCreationException.class) - public void testUrlClnClass() { - new AnnotationConfigApplicationContext(TestConfig12.class); - } + @Test(expected = BeanCreationException.class) + public void testUrlClnClass() { + new AnnotationConfigApplicationContext(TestConfig12.class); + } - @Test(expected = BeanCreationException.class) - public void testUrlClnMethodExists() { - new AnnotationConfigApplicationContext(TestConfig13.class); - } + @Test(expected = BeanCreationException.class) + public void testUrlClnMethodExists() { + new AnnotationConfigApplicationContext(TestConfig13.class); + } - @Test(expected = BeanCreationException.class) - public void testUrlClnReturnValue() { - new AnnotationConfigApplicationContext(TestConfig14.class); - } + @Test(expected = BeanCreationException.class) + public void testUrlClnReturnValue() { + new AnnotationConfigApplicationContext(TestConfig14.class); + } - @Configuration - public static class TestConfig1 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Test + public void testExceptionHandler4Fallback() { + new AnnotationConfigApplicationContext(TestConfig15.class); + } - @Bean - @SentinelRestTemplate(fallback = "fbk") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } - @Configuration - public static class TestConfig2 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig1 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(fallbackClass = ExceptionUtil.class) - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(fallback = "fbk") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig3 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig2 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(blockHandler = "blk") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(fallbackClass = ExceptionUtil.class) + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig4 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig3 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class) - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(blockHandler = "blk") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig5 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig4 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException", fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException", urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class) + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig6 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig5 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException1") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException", fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException", urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig7 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig6 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException1") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException1") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig8 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig7 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException2") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException1") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig9 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig8 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException2") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException2") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig10 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig9 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate - RestTemplate restTemplate() { - return new RestTemplate(); - } + @Bean + @SentinelRestTemplate(fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException2") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Bean - @SentinelRestTemplate - RestTemplate restTemplate2() { - return new RestTemplate(); - } - } + @Configuration + public static class TestConfig10 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Configuration - public static class TestConfig11 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Bean + @SentinelRestTemplate + RestTemplate restTemplate() { + return new RestTemplate(); + } - @Bean - @SentinelRestTemplate(urlCleaner = "cln") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate + RestTemplate restTemplate2() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig12 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig11 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class) - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(urlCleaner = "cln") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig13 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig12 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean1") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class) + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - @Configuration - public static class TestConfig14 { - @Bean - SentinelBeanPostProcessor sentinelBeanPostProcessor( - ApplicationContext applicationContext) { - return new SentinelBeanPostProcessor(applicationContext); - } + @Configuration + public static class TestConfig13 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - @Bean - @SentinelRestTemplate(urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean2") - RestTemplate restTemplate() { - return new RestTemplate(); - } - } + @Bean + @SentinelRestTemplate(urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean1") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - public static class ExceptionUtil { - public static SentinelClientHttpResponse handleException(HttpRequest request, - byte[] body, ClientHttpRequestExecution execution, BlockException ex) { - System.out.println("Oops: " + ex.getClass().getCanonicalName()); - return new SentinelClientHttpResponse("Oops"); - } + @Configuration + public static class TestConfig14 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - public static void handleException2(HttpRequest request, byte[] body, - ClientHttpRequestExecution execution, BlockException ex) { - System.out.println("Oops: " + ex.getClass().getCanonicalName()); - } + @Bean + @SentinelRestTemplate(urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean2") + RestTemplate restTemplate() { + return new RestTemplate(); + } + } - public static SentinelClientHttpResponse fallbackException(HttpRequest request, - byte[] body, ClientHttpRequestExecution execution, BlockException ex) { - System.out.println("Oops: " + ex.getClass().getCanonicalName()); - return new SentinelClientHttpResponse("Oops fallback"); - } + @Configuration + public static class TestConfig15 { + @Bean + SentinelBeanPostProcessor sentinelBeanPostProcessor( + ApplicationContext applicationContext) { + return new SentinelBeanPostProcessor(applicationContext); + } - public static void fallbackException2(HttpRequest request, byte[] body, - ClientHttpRequestExecution execution, BlockException ex) { - System.out.println("Oops: " + ex.getClass().getCanonicalName()); - } - } + @Bean + @SentinelRestTemplate(fallbackClass = TestConfig15.class, + fallback = "fallbackHandler", + blockHandlerClass = TestConfig15.class, + blockHandler = "flowHandler") + RestTemplate restTemplate() { + return new RestTemplate(); + } - public static class UrlCleanUtil { - public static String clean(String url) { - return url; - } + @Bean + public SentinelRestTemplateExceptionHandler globalExceptionHandler() { + return new SentinelRestTemplateExceptionHandler(); + } + + public static SentinelClientHttpResponse flowHandler(HttpRequest request, + byte[] body, + ClientHttpRequestExecution execution, + BlockException exception) { + if (exception instanceof FlowException) { + throw new SentinelRestTemplateFlowException(exception.getMessage(), exception); + } + return new SentinelClientHttpResponse("Oops flowHandler"); + } + + public static SentinelClientHttpResponse fallbackHandler(HttpRequest request, + byte[] body, + ClientHttpRequestExecution execution, + BlockException exception) { + if (exception instanceof DegradeException) { + throw new SentinelRestTemplateDegradeException(exception.getMessage(), exception); + } + return new SentinelClientHttpResponse("Oops fallback"); + } + + public static class SentinelRestTemplateFlowException extends RuntimeException { + SentinelRestTemplateFlowException(String message, Throwable cause) { + super(message, cause); + } + } + + public static class SentinelRestTemplateDegradeException extends RuntimeException { + SentinelRestTemplateDegradeException(String message, Throwable cause) { + super(message, cause); + } + } + + @ControllerAdvice + public class SentinelRestTemplateExceptionHandler { + + @ExceptionHandler(SentinelRestTemplateFlowException.class) + public ResponseEntity restTemplateFlowExceptionHandler(SentinelRestTemplateFlowException exception) { + return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body("PS: have a rest."); + } + + @ExceptionHandler(SentinelRestTemplateDegradeException.class) + public ResponseEntity restTemplateDegradeExceptionHandler(SentinelRestTemplateDegradeException exception) { + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("PS: " + HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase()); + } + } + } + + public static class ExceptionUtil { + public static SentinelClientHttpResponse handleException(HttpRequest request, + byte[] body, ClientHttpRequestExecution execution, BlockException ex) { + System.out.println("Oops: " + ex.getClass().getCanonicalName()); + return new SentinelClientHttpResponse("Oops"); + } + + public static void handleException2(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution, BlockException ex) { + System.out.println("Oops: " + ex.getClass().getCanonicalName()); + } + + public static SentinelClientHttpResponse fallbackException(HttpRequest request, + byte[] body, ClientHttpRequestExecution execution, BlockException ex) { + System.out.println("Oops: " + ex.getClass().getCanonicalName()); + return new SentinelClientHttpResponse("Oops fallback"); + } + + public static void fallbackException2(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution, BlockException ex) { + System.out.println("Oops: " + ex.getClass().getCanonicalName()); + } + + } + + public static class UrlCleanUtil { + public static String clean(String url) { + return url; + } + + public static void clean2(String url) { + } + } - public static void clean2(String url) { - } - } }