├── .gitignore ├── bucket4j-spring-boot-starter-example-caffeine ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── giffing │ │ │ └── bucket4j │ │ │ └── spring │ │ │ └── boot │ │ │ └── starter │ │ │ └── examples │ │ │ └── caffeine │ │ │ ├── CaffeineApplication.java │ │ │ └── TestController.java │ └── resources │ │ └── application.yml │ └── test │ ├── java │ └── com │ │ └── giffing │ │ └── bucket4j │ │ └── spring │ │ └── boot │ │ └── starter │ │ └── examples │ │ └── caffeine │ │ └── ServletRateLimitTest.java │ └── resources │ └── application-servlet.yml ├── bucket4j-spring-boot-starter-example-ehcache ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── giffing │ │ └── bucket4j │ │ └── spring │ │ └── boot │ │ └── starter │ │ └── examples │ │ └── ehcache │ │ ├── EhcacheApplication.java │ │ ├── config │ │ └── security │ │ │ ├── SecurityConfig.java │ │ │ └── SecurityService.java │ │ └── controller │ │ ├── DebugMetricHandler.java │ │ └── TestController.java │ └── resources │ ├── application.yml │ └── ehcache.xml ├── bucket4j-spring-boot-starter-example-gateway ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── giffing │ │ └── bucket4j │ │ └── spring │ │ └── boot │ │ └── starter │ │ └── examples │ │ └── gateway │ │ ├── GatewayMetricHandler.java │ │ ├── GatewayMetricHandler2.java │ │ ├── GatewaySampleApplication.java │ │ └── MyController.java │ └── resources │ ├── application.yml │ └── hazelcast.xml ├── bucket4j-spring-boot-starter-example-hazelcast ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── giffing │ │ └── bucket4j │ │ └── spring │ │ └── boot │ │ └── starter │ │ └── examples │ │ └── hazelcast │ │ ├── HazelcastApplication.java │ │ └── TestController.java │ └── resources │ ├── application.yml │ └── hazelcast.xml ├── bucket4j-spring-boot-starter-example-webflux ├── .gitignore ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── giffing │ │ │ │ └── bucket4j │ │ │ │ └── spring │ │ │ │ └── boot │ │ │ │ └── starter │ │ │ │ └── examples │ │ │ │ └── webflux │ │ │ │ ├── MyController.java │ │ │ │ └── WebfluxApplication.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── ehcache.xml │ │ │ └── hazelcast.xml │ └── test │ │ ├── java │ │ └── com │ │ │ └── giffing │ │ │ └── bucket4j │ │ │ └── spring │ │ │ └── boot │ │ │ └── starter │ │ │ └── examples │ │ │ └── webflux │ │ │ └── WebfluxRateLimitTest.java │ │ └── resources │ │ └── application-webflux.yml └── target │ └── classes │ └── application.yml ├── bucket4j-spring-boot-starter-example-zuul ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── giffing │ │ └── bucket4j │ │ └── spring │ │ └── boot │ │ └── starter │ │ └── examples │ │ └── zuul │ │ ├── MyController.java │ │ └── ZuulApplication.java │ └── resources │ ├── application.yml │ └── ehcache.xml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.giffing.bucket4j.spring.boot.starter 7 | bucket4j-spring-boot-starter-examples 8 | ${revision} 9 | .. 10 | 11 | bucket4j-spring-boot-starter-example-caffeine 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-cache 21 | 22 | 23 | com.giffing.bucket4j.spring.boot.starter 24 | bucket4j-spring-boot-starter 25 | 26 | 27 | javax.cache 28 | cache-api 29 | 30 | 31 | com.github.ben-manes.caffeine 32 | caffeine 33 | 34 | 35 | com.github.ben-manes.caffeine 36 | jcache 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/CaffeineApplication.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.caffeine; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class CaffeineApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(CaffeineApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/TestController.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.caffeine; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | public class TestController { 9 | 10 | @GetMapping("hello") 11 | public ResponseEntity hello() { 12 | return ResponseEntity.ok("Hello World"); 13 | } 14 | 15 | @GetMapping("world") 16 | public ResponseEntity world() { 17 | return ResponseEntity.ok("Hello World"); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | security: 7 | enabled: false 8 | spring: 9 | cache: 10 | jcache: 11 | provider: org.ehcache.jsr107.EhcacheCachingProvider 12 | cache-names: 13 | - buckets 14 | caffeine: 15 | spec: maximumSize=1000000,expireAfterAccess=3600s 16 | bucket4j: 17 | enabled: true 18 | filters: 19 | - cache-name: buckets 20 | url: .* 21 | hide-http-response-headers: true 22 | rate-limits: 23 | - bandwidths: 24 | - capacity: 5 25 | time: 1 26 | unit: minutes 27 | fixed-refill-interval: 1 28 | fixed-refill-interval-unit: minutes -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/ServletRateLimitTest.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.caffeine; 2 | 3 | import static org.assertj.core.api.Assertions.fail; 4 | import static org.hamcrest.Matchers.containsString; 5 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | 10 | import java.util.Collections; 11 | import java.util.stream.IntStream; 12 | 13 | import org.junit.jupiter.api.Test; 14 | import org.junit.jupiter.api.extension.ExtendWith; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 17 | import org.springframework.boot.test.context.SpringBootTest; 18 | import org.springframework.http.HttpStatus; 19 | import org.springframework.test.context.ActiveProfiles; 20 | import org.springframework.test.context.junit.jupiter.SpringExtension; 21 | import org.springframework.test.web.servlet.MockMvc; 22 | 23 | @ExtendWith(SpringExtension.class) 24 | @SpringBootTest 25 | @AutoConfigureMockMvc 26 | @ActiveProfiles("servlet") // Like this 27 | public class ServletRateLimitTest { 28 | 29 | @Autowired 30 | private MockMvc mockMvc; 31 | 32 | @Test 33 | public void helloTest() throws Exception { 34 | String url = "/hello"; 35 | IntStream.rangeClosed(1, 5) 36 | .boxed() 37 | .sorted(Collections.reverseOrder()) 38 | .forEach(counter -> { 39 | successfulWebRequest(url, counter - 1); 40 | }); 41 | 42 | blockedWebRequestDueToRateLimit(url); 43 | } 44 | 45 | 46 | @Test 47 | public void worldTest() throws Exception { 48 | String url = "/world"; 49 | IntStream.rangeClosed(1, 10) 50 | .boxed() 51 | .sorted(Collections.reverseOrder()) 52 | .forEach(counter -> { 53 | successfulWebRequest(url, counter - 1); 54 | }); 55 | 56 | blockedWebRequestDueToRateLimit(url); 57 | } 58 | 59 | private void successfulWebRequest(String url, Integer remainingTries) { 60 | try { 61 | this.mockMvc 62 | .perform(get(url)) 63 | .andExpect(status().isOk()) 64 | .andExpect(header().longValue("X-Rate-Limit-Remaining", remainingTries)) 65 | .andExpect(content().string(containsString("Hello World"))); 66 | } catch (Exception e) { 67 | e.printStackTrace(); 68 | fail(e.getMessage()); 69 | } 70 | } 71 | 72 | private void blockedWebRequestDueToRateLimit(String url) throws Exception { 73 | this.mockMvc 74 | .perform(get(url)) 75 | .andExpect(status().is(HttpStatus.TOO_MANY_REQUESTS.value())) 76 | .andExpect(content().string(containsString("{ \"message\": \"Too many requests!\" }"))); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-caffeine/src/test/resources/application-servlet.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cache: 3 | cache-names: 4 | - buckets_test 5 | caffeine: 6 | spec: maximumSize=1000000,expireAfterAccess=3600s 7 | bucket4j: 8 | enabled: true 9 | filters: 10 | - cache-name: buckets_test 11 | url: ^(/hello).* 12 | rate-limits: 13 | - bandwidths: 14 | - capacity: 5 15 | time: 10 16 | unit: seconds 17 | - cache-name: buckets_test 18 | url: ^(/world).* 19 | rate-limits: 20 | - bandwidths: 21 | - capacity: 10 22 | time: 10 23 | unit: seconds -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.giffing.bucket4j.spring.boot.starter 5 | bucket4j-spring-boot-starter-examples 6 | ${revision} 7 | .. 8 | 9 | bucket4j-spring-boot-starter-example-ehcache 10 | 11 | 12 | 13 | com.giffing.bucket4j.spring.boot.starter 14 | bucket4j-spring-boot-starter 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-actuator 19 | 20 | 21 | io.micrometer 22 | micrometer-registry-prometheus 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-cache 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-security 35 | 36 | 37 | com.fasterxml.jackson.core 38 | jackson-core 39 | 40 | 41 | com.fasterxml.jackson.core 42 | jackson-databind 43 | 44 | 45 | org.ehcache 46 | ehcache 47 | 48 | 49 | org.projectlombok 50 | lombok 51 | true 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-deploy-plugin 61 | 62 | true 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/EhcacheApplication.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.ehcache; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class EhcacheApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(EhcacheApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/config/security/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.ehcache.config.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 | 10 | @Configuration 11 | @EnableWebSecurity 12 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 13 | 14 | @Override 15 | protected void configure(HttpSecurity http) throws Exception { 16 | http.authorizeRequests().antMatchers("/unsecure").permitAll(); 17 | http.authorizeRequests().antMatchers("/login").permitAll(); 18 | http.authorizeRequests().antMatchers("/secure").hasAnyRole("ADMIN", "USER"); 19 | } 20 | 21 | @Autowired 22 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 23 | auth.inMemoryAuthentication().withUser("admin").password("123").roles("ADMIN"); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/config/security/SecurityService.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.ehcache.config.security; 2 | 3 | import org.springframework.security.core.Authentication; 4 | import org.springframework.security.core.context.SecurityContextHolder; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | public class SecurityService { 9 | 10 | public String username() { 11 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 12 | if(authentication == null) { 13 | return null; 14 | } 15 | String name = authentication.getName(); 16 | if(name == "anonymousUser") { 17 | return null; 18 | } 19 | return name; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/controller/DebugMetricHandler.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.ehcache.controller; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import org.springframework.stereotype.Component; 7 | 8 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricHandler; 9 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricTagResult; 10 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricType; 11 | 12 | @Component 13 | public class DebugMetricHandler implements MetricHandler { 14 | 15 | @Override 16 | public void handle(MetricType type, String name, long tokens, List tags) { 17 | System.out.println(String.format("type: %s; name: %s; tags: %s", 18 | type, 19 | name, 20 | tags 21 | .stream() 22 | .map(mtr -> mtr.getKey() + ":" + mtr.getValue()) 23 | .collect(Collectors.joining(",")))); 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.ehcache.controller; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.context.SecurityContextHolder; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | @RestController 16 | @RequestMapping("/") 17 | public class TestController { 18 | // http.authorizeRequests().antMatchers("/unsecure").permitAll(); 19 | // http.authorizeRequests().antMatchers("/login").permitAll(); 20 | // http.authorizeRequests().antMatchers("/secure").hasAnyRole("ADMIN","USER"). 21 | 22 | @GetMapping("unsecure") 23 | public ResponseEntity unsecure() { 24 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 25 | return ResponseEntity.ok().build(); 26 | } 27 | 28 | @GetMapping("login") 29 | public ResponseEntity login() { 30 | 31 | Collection grantedAuthorities = new ArrayList(); 32 | GrantedAuthority grantedAuthority = new GrantedAuthority() { 33 | //anonymous inner type 34 | public String getAuthority() { 35 | return "ROLE_USER"; 36 | } 37 | }; 38 | grantedAuthorities.add(grantedAuthority); 39 | 40 | Authentication auth = new UsernamePasswordAuthenticationToken(new User("admin"), null, grantedAuthorities); 41 | SecurityContextHolder.getContext().setAuthentication(auth); 42 | 43 | return ResponseEntity.ok().build(); 44 | } 45 | 46 | @GetMapping("secure") 47 | public ResponseEntity secure() { 48 | return ResponseEntity.ok().build(); 49 | } 50 | 51 | public static class User { 52 | public String username; 53 | 54 | public User(String username) { 55 | this.username = username; 56 | } 57 | 58 | public String getUsername() { 59 | return username; 60 | } 61 | 62 | public void setUsername(String username) { 63 | this.username = username; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return username; 69 | } 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | prometheus: 7 | enabled: true 8 | spring: 9 | cache: 10 | jcache: 11 | config: classpath:ehcache.xml 12 | bucket4j: 13 | enabled: true 14 | filters: 15 | - cache-name: buckets 16 | filter-method: servlet 17 | filter-order: -10 18 | url: .* 19 | metrics: 20 | tags: 21 | - key: USERNAME 22 | expression: "@securityService.username() != null ? @securityService.username() : 'anonym'" 23 | - key: URL 24 | expression: getRequestURI() 25 | rate-limits: 26 | - bandwidths: 27 | - capacity: 30 28 | time: 1 29 | unit: minutes 30 | - cache-name: buckets 31 | filter-method: servlet 32 | filter-order: 1 33 | url: .* 34 | metrics: 35 | tags: 36 | - key: USERNAME 37 | expression: "@securityService.username() != null ? @securityService.username() : 'anonym'" 38 | - key: URL 39 | expression: getRequestURI() 40 | rate-limits: 41 | - execute-condition: "@securityService.username() == 'admin'" 42 | expression: "@securityService.username()?: getRemoteAddr()" 43 | bandwidths: 44 | - capacity: 30 45 | time: 1 46 | unit: minutes 47 | - execute-condition: "@securityService.username() != 'admin'" 48 | expression: "@securityService.username()?: getRemoteAddr()" 49 | bandwidths: 50 | - capacity: 5 51 | time: 1 52 | unit: minutes -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-ehcache/src/main/resources/ehcache.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 3600 9 | 10 | 1000000 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 2.6.2 11 | 12 | 13 | 14 | com.giffing.bucket4j.spring.boot.starter 15 | bucket4j-spring-boot-starter-example-gateway 16 | 0.0.1-SNAPSHOT 17 | 18 | 11 19 | 2021.0.0 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-actuator 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-webflux 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-gateway 34 | 35 | 36 | com.giffing.bucket4j.spring.boot.starter 37 | bucket4j-spring-boot-starter 38 | 0.5.2 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-cache 43 | 44 | 45 | javax.cache 46 | cache-api 47 | 48 | 49 | com.github.vladimir-bukhtoyarov 50 | bucket4j-hazelcast 51 | 7.0.0 52 | 53 | 54 | com.hazelcast 55 | hazelcast 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-devtools 61 | runtime 62 | true 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-test 67 | test 68 | 69 | 70 | 71 | 72 | 73 | 74 | org.springframework.cloud 75 | spring-cloud-dependencies 76 | ${spring-cloud.version} 77 | pom 78 | import 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-maven-plugin 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/gateway/GatewayMetricHandler.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.gateway; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricHandler; 8 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricTagResult; 9 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricType; 10 | 11 | 12 | @Component 13 | public class GatewayMetricHandler implements MetricHandler { 14 | 15 | @Override 16 | public void handle(MetricType type, String name, long tokens, List tags) { 17 | System.out.println(type); 18 | System.out.println(name); 19 | System.out.println(tokens); 20 | System.out.println("################"); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/gateway/GatewayMetricHandler2.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.gateway; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricHandler; 8 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricTagResult; 9 | import com.giffing.bucket4j.spring.boot.starter.context.metrics.MetricType; 10 | 11 | 12 | @Component 13 | public class GatewayMetricHandler2 implements MetricHandler { 14 | 15 | @Override 16 | public void handle(MetricType type, String name, long tokens, List tags) { 17 | System.out.println(type); 18 | System.out.println(name); 19 | System.out.println(tokens); 20 | System.out.println("################"); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/gateway/GatewaySampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.cloud.gateway.route.RouteLocator; 7 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | @SpringBootApplication 11 | @EnableCaching 12 | public class GatewaySampleApplication { 13 | 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(GatewaySampleApplication.class, args); 17 | } 18 | 19 | @Bean 20 | public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { 21 | //@formatter:off 22 | return builder.routes() 23 | .route(p -> p 24 | .path("/get") 25 | .filters(f -> f.addRequestHeader("Hello", "World")) 26 | .uri("http://httpbin.org:80")) 27 | .build(); 28 | //@formatter:on 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/gateway/MyController.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.gateway; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import reactor.core.publisher.Mono; 9 | 10 | @RestController 11 | @RequestMapping 12 | public class MyController { 13 | 14 | @GetMapping("/hello") 15 | public Mono hello( 16 | @RequestParam(defaultValue = "World") String name) { 17 | return Mono.just("Hello") 18 | .flatMap(s -> Mono 19 | .just(s + ", " + name + "!\n") 20 | ); 21 | } 22 | 23 | @GetMapping("/world") 24 | public Mono world( 25 | @RequestParam(defaultValue = "World") String name) { 26 | return Mono.just("Hello") 27 | .flatMap(s -> Mono 28 | .just(s + ", " + name + "!\n") 29 | ); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: cache: type: jcache jcache: provider: com.hazelcast.cache.impl.HazelcastServerCachingProvider config: classpath:hazelcast.xml 2 | management: 3 | endpoints: 4 | web: 5 | exposure: 6 | include: "*" 7 | bucket4j: 8 | filters: 9 | - metrics: 10 | types: 11 | - consumed-counter 12 | - rejected-counter 13 | - cache-name: buckets 14 | filter-method: gateway 15 | url: .* 16 | filter-order: -100000 17 | rate-limits: 18 | - bandwidths: 19 | - capacity: 5 20 | time: 10 21 | unit: seconds fixed-refill-interval: 1 fixed-refill-interval-unit: minutes 22 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-gateway/src/main/resources/hazelcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 120 9 | BINARY 10 | CREATE_ON_UPDATE 11 | true 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-hazelcast/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-hazelcast/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.giffing.bucket4j.spring.boot.starter 7 | bucket4j-spring-boot-starter-examples 8 | ${revision} 9 | .. 10 | 11 | bucket4j-spring-boot-starter-example-hazelcast 12 | 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-cache 22 | 23 | 24 | com.giffing.bucket4j.spring.boot.starter 25 | bucket4j-spring-boot-starter 26 | 27 | 28 | com.hazelcast 29 | hazelcast 30 | 31 | 32 | com.hazelcast 33 | hazelcast-spring 34 | 35 | 36 | com.hazelcast 37 | hazelcast-client 38 | 3.12.12 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-actuator 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-hazelcast/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/hazelcast/HazelcastApplication.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.hazelcast; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class HazelcastApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(HazelcastApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-hazelcast/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/hazelcast/TestController.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.hazelcast; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/") 10 | public class TestController { 11 | 12 | @GetMapping 13 | public ResponseEntity helloWorld() { 14 | return ResponseEntity.ok().build(); 15 | } 16 | 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-hazelcast/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | security: 3 | enabled: false 4 | spring: 5 | main: allow-bean-definition-overriding: true 6 | cache: 7 | type: jcache 8 | jcache: 9 | provider: com.hazelcast.cache.impl.HazelcastServerCachingProvider 10 | config: classpath:hazelcast.xml 11 | bucket4j: 12 | enabled: true 13 | filters: 14 | - cache-name: buckets 15 | url: .* 16 | rate-limits: 17 | - bandwidths: 18 | - capacity: 5 19 | time: 10 20 | unit: seconds -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-hazelcast/src/main/resources/hazelcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 120 9 | BINARY 10 | CREATE_ON_UPDATE 11 | true 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.giffing.bucket4j.spring.boot.starter 7 | bucket4j-spring-boot-starter-examples 8 | ${revision} 9 | .. 10 | 11 | bucket4j-spring-boot-starter-example-webflux 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-webflux 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-cache 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-actuator 25 | 26 | 27 | com.giffing.bucket4j.spring.boot.starter 28 | bucket4j-spring-boot-starter 29 | 30 | 31 | javax.cache 32 | cache-api 33 | 34 | 35 | com.github.vladimir-bukhtoyarov 36 | bucket4j-hazelcast 37 | 38 | 39 | com.hazelcast 40 | hazelcast 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | generate build info 56 | 57 | build-info 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/webflux/MyController.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.webflux; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import reactor.core.publisher.Mono; 9 | 10 | @RestController 11 | @RequestMapping 12 | public class MyController { 13 | 14 | @GetMapping("/hello") 15 | public Mono hello( 16 | @RequestParam(defaultValue = "World") String name) { 17 | return Mono.just("Hello") 18 | .flatMap(s -> Mono 19 | .just(s + ", " + name + "!\n") 20 | ); 21 | } 22 | 23 | @GetMapping("/world") 24 | public Mono world( 25 | @RequestParam(defaultValue = "World") String name) { 26 | return Mono.just("Hello") 27 | .flatMap(s -> Mono 28 | .just(s + ", " + name + "!\n") 29 | ); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/webflux/WebfluxApplication.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.webflux; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class WebfluxApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(WebfluxApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | bucket4j: 7 | enabled: true 8 | filters: 9 | - metrics: 10 | types: 11 | - consumed-counter 12 | - rejected-counter 13 | - cache-name: buckets 14 | filter-method: webflux 15 | url: .* 16 | filter-order: 1 17 | rate-limits: 18 | - bandwidths: 19 | - capacity: 5 20 | time: 10 21 | unit: seconds 22 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/main/resources/ehcache.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 3600 9 | 10 | 1000000 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/main/resources/hazelcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 120 10 | BINARY 11 | true 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/webflux/WebfluxRateLimitTest.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.webflux; 2 | 3 | import java.util.Collections; 4 | import java.util.stream.IntStream; 5 | 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.extension.ExtendWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.context.ApplicationContext; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.test.context.ActiveProfiles; 14 | import org.springframework.test.context.junit.jupiter.SpringExtension; 15 | import org.springframework.test.web.reactive.server.WebTestClient; 16 | 17 | @ExtendWith(SpringExtension.class) 18 | @SpringBootTest 19 | @ActiveProfiles("webflux") // Like this 20 | public class WebfluxRateLimitTest { 21 | 22 | @Autowired 23 | ApplicationContext context; 24 | 25 | WebTestClient rest; 26 | 27 | @BeforeEach 28 | public void setup() { 29 | this.rest = WebTestClient 30 | .bindToApplicationContext(this.context) 31 | .configureClient() 32 | .build(); 33 | } 34 | 35 | @Test 36 | public void helloTest() throws Exception { 37 | String url = "/hello"; 38 | IntStream.rangeClosed(1, 5) 39 | .boxed() 40 | .sorted(Collections.reverseOrder()) 41 | .forEach(counter -> { 42 | successfulWebRequest(url, counter - 1); 43 | }); 44 | 45 | blockedWebRequestDueToRateLimit(url); 46 | } 47 | 48 | 49 | @Test 50 | public void worldTest() throws Exception { 51 | String url = "/world"; 52 | IntStream.rangeClosed(1, 10) 53 | .boxed() 54 | .sorted(Collections.reverseOrder()) 55 | .forEach(counter -> { 56 | System.out.println(counter); 57 | successfulWebRequest(url, counter - 1); 58 | }); 59 | 60 | blockedWebRequestDueToRateLimit(url); 61 | } 62 | 63 | private void successfulWebRequest(String url, Integer remainingTries) { 64 | rest 65 | .get() 66 | .uri(url) 67 | .exchange() 68 | .expectStatus().isOk() 69 | .expectHeader().valueEquals("X-Rate-Limit-Remaining", String.valueOf(remainingTries)); 70 | } 71 | 72 | private void blockedWebRequestDueToRateLimit(String url) throws Exception { 73 | rest 74 | .get() 75 | .uri(url) 76 | .exchange() 77 | .expectStatus().isEqualTo(HttpStatus.TOO_MANY_REQUESTS) 78 | .expectBody().jsonPath("error", "Too many requests!"); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/src/test/resources/application-webflux.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cache: 3 | cache-names: 4 | - buckets_test 5 | caffeine: 6 | spec: maximumSize=1000000,expireAfterAccess=3600s 7 | bucket4j: 8 | enabled: true 9 | filters: 10 | - cache-name: buckets_test 11 | filter-method: webflux 12 | url: ^(/hello).* 13 | rate-limits: 14 | - bandwidths: 15 | - capacity: 5 16 | time: 10 17 | unit: seconds 18 | - cache-name: buckets_test 19 | filter-method: webflux 20 | url: ^(/world).* 21 | rate-limits: 22 | - bandwidths: 23 | - capacity: 10 24 | time: 10 25 | unit: seconds -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-webflux/target/classes/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | bucket4j: 7 | enabled: true 8 | filters: 9 | - metrics: 10 | types: 11 | - consumed-counter 12 | - rejected-counter 13 | - cache-name: buckets 14 | filter-method: webflux 15 | url: .* 16 | filter-order: 1 17 | rate-limits: 18 | - bandwidths: 19 | - capacity: 5 20 | time: 10 21 | unit: seconds 22 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-zuul/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .classpath 4 | .project 5 | .idea/ 6 | *.iml 7 | .factorypath 8 | .apt_generated 9 | .springBeans -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-zuul/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.giffing.bucket4j.spring.boot.starter 6 | bucket4j-spring-boot-starter-examples 7 | ${revision} 8 | .. 9 | 10 | bucket4j-spring-boot-starter-example-zuul 11 | 12 | 13 | Finchley.SR7 14 | 15 | 16 | 17 | 18 | com.giffing.bucket4j.spring.boot.starter 19 | bucket4j-spring-boot-starter 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-actuator 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-cache 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-netflix-core 36 | 1.4.4.RELEASE 37 | 38 | 39 | org.ehcache 40 | ehcache 41 | 42 | 43 | org.projectlombok 44 | lombok 45 | true 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-devtools 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-zuul/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/zuul/MyController.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.zuul; 2 | 3 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @EnableZuulProxy 9 | @RequestMapping 10 | public class MyController { 11 | 12 | @RequestMapping 13 | public String available() { 14 | return "Spring in Action"; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-zuul/src/main/java/com/giffing/bucket4j/spring/boot/starter/examples/zuul/ZuulApplication.java: -------------------------------------------------------------------------------- 1 | package com.giffing.bucket4j.spring.boot.starter.examples.zuul; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class ZuulApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ZuulApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-zuul/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoints: 3 | web: 4 | exposure: 5 | include: "*" 6 | spring: 7 | application: 8 | name: myservice 9 | cache: 10 | jcache: 11 | config: classpath:ehcache.xml 12 | bucket4j: 13 | enabled: true 14 | filters: 15 | - cache-name: buckets 16 | filter-method: zuul 17 | url: /myservice 18 | filter-order: -10000 19 | rate-limits: 20 | - filter-key-type: ip 21 | expression: "@securityService.username()?: getRemoteAddr()" 22 | bandwidths: 23 | - capacity: 10 24 | time: 1 25 | unit: minutes 26 | zuul: 27 | routes: 28 | myservice: 29 | url: http://localhost:8090 30 | -------------------------------------------------------------------------------- /bucket4j-spring-boot-starter-example-zuul/src/main/resources/ehcache.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 3600 9 | 10 | 1000000 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.giffing.bucket4j.spring.boot.starter 6 | bucket4j-spring-boot-starter-examples 7 | ${revision} 8 | pom 9 | 10 | bucket4j-spring-boot-starter-examples 11 | Spring Boot Starter für Bucket4J 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 2.6.2 17 | 18 | 19 | 20 | 21 | bucket4j-spring-boot-starter-example-ehcache 22 | bucket4j-spring-boot-starter-example-zuul 23 | bucket4j-spring-boot-starter-example-hazelcast 24 | bucket4j-spring-boot-starter-example-caffeine 25 | bucket4j-spring-boot-starter-example-webflux 26 | bucket4j-spring-boot-starter-example-gateway 27 | 28 | 29 | 30 | 0.0.1-SNAPSHOT 31 | UTF-8 32 | UTF-8 33 | 1.8 34 | 35 | 36 | 37 | 38 | 39 | com.giffing.bucket4j.spring.boot.starter 40 | bucket4j-spring-boot-starter 41 | 0.5.2 42 | 43 | 44 | com.github.vladimir-bukhtoyarov 45 | bucket4j-core 46 | 7.0.0 47 | 48 | 49 | com.github.vladimir-bukhtoyarov 50 | bucket4j-jcache 51 | 7.0.0 52 | 53 | 54 | com.github.vladimir-bukhtoyarov 55 | bucket4j-hazelcast 56 | 7.0.0 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-maven-plugin 67 | 68 | 69 | 70 | 71 | 72 | --------------------------------------------------------------------------------