Giriş
Şu satırı dahil ederiz
Şu satırı dahil ederiz
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
Açıklaması şöyle. Yani HandlerInterceptor arayüzünden kalıtmaktan daha iyi
If you would like to provide a custom implementation and only care for a few of their methods (if you do not want to create empty methods that requires overriding), it is better to implement an adapter.
Bu sınıf yerine AsyncHandlerInterceptor kullanılabilir.
Bize gelen (incoming) istekleri kesmek için kullanılır. Gönderdiğimiz (outgoing) cevapları kesmek için ClientHttpRequestInterceptor kullanılır.
Kullanım
Interceptor şöyle eklenir
Interceptor şöyle eklenir
afterCompletion metodu - HttpServletRequest + HttpServletResponse + handler + Exception@Configurationpublic class RateLimitConfig extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestRateLimiter());}}
handler örneğin RestController sınıfıdır
Örnek
Şöyle yaparız.
postHandle metodu - HttpServletRequest + HttpServletResponse + handler + ModelAndView
Bu metod genellikle preHandle + postHandle şeklinde kullanılır
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception exception) throws Exception {
...
}
Örnek
Elimizde şöyle bir kod olsun. Bu kodda kendi tanımladığımız @RateLimit anotasyonu kullanılıyor
@RestControllerpublic class BankingController { @PublicAccess @ApiOperation("Get All Credit Card products") @RateLimit(limit = 10, key = ALL_CREDIT_PRODUCTS) @RequestMapping(value = ALL_CREDIT_PRODUCTS, method = RequestMethod.GET,
produces = "application/json") public Response<List<Product>> creditCardProducts() { ... } }
Elimizde şöyle bir interceptor olsun
public class RequestRateLimiter extends HandlerInterceptorAdapter {private final ConcurrentHashMap<String,Semaphore> localSemaphoreCache;RequestRateLimiter() {this.localSemaphoreCache = new ConcurrentHashMap<>();}...}
Semaphore tryAacquire için şöyle yaparız. Bu kod çağrılan RestController'da tan ım @RateLimit anotasyonunu okur ve semaphore'u belirtilen sayı kadar kilitler
@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) {if (!(handler instanceof HandlerMethod)) {return true;}HandlerMethod handlerMethod = (HandlerMethod) handler;RateLimit rateLimit = handlerMethod.getMethod().getAnnotation(RateLimit.class);if (rateLimit != null) { // target method annotatedSemaphore localSemaphore = computeIfAbsent(rateLimit.key(), rateLimit.limit());if (!localSemaphore.tryAcquire()) {throw new RuntimeException("Too many calls");}}return true;}private Semaphore computeIfAbsent(String key, int rateLimit) {return localSemaphoreCache.computeIfAbsent(key, keyKey -> new Semaphore(rateLimit));}
Semaphore release için şöyle yaparız
@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {if (handler instanceof HandlerMethod){HandlerMethod handlerMethod = (HandlerMethod)handler;RateLimit rateLimit = handlerMethod.getMethod().getAnnotation(RateLimit.class);if (rateLimit != null) { // target method annotatedSemaphore localSemaphore = localSemaphoreCache.get(rateLimit.key());if (localSemaphore != null) {localSemaphore.release(1);}}}}
Bu metod genellikle preHandle + postHandle şeklinde kullanılır
preHandle metodu - HttpServletRequest + HttpServletResponse + handler
handler örneğin RestController sınıfıdır
Örnek
Şöyle yaparız.
- preHandle() içinde HttpServletRequest nesnesindeki parametreler bende varsa false dönülüyor. Http Status Code ise 301
- postHandle() içinde ise eğer Http Status Code 201 ise bazı parametreler saklanıyor.
Bu kodda halen arka arkaya iki tane istek gelir ve preHandle() çalışırsa problem olabilir, çünkü tam anlamıyla transaction mantığı yok.
public class RequestHandlerInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws IOException, ClassNotFoundException {String correlationId = request.getHeader("correlation-id");if (correlationId != null) {String location = getCachedLocationUri(correlationId);if (location != null) {response.setStatus(301);response.addHeader("correlation-id", correlationId);response.addHeader("Location", location);response.flushBuffer();return false;}}return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws IOException {if (response.getStatus() == 201) {String correlationId = request.getHeader("correlation-id");String location = response.getHeader("Location");putLocationInCache(correlationId, location);}}}
Hiç yorum yok:
Yorum Gönder