Logging Filter
⭐ 필터 실행 순서와 종료 순서는 역순

package com.example.apigatewayservice.filter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class LoggingFilter extends AbstractGatewayFilterFactory<LoggingFilter.Config> {
public LoggingFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Logging Filter basemessage: {}", config.getBaseMessage());
if(config.isPreLogger()){
log.info("Logging Pre Filter : request_id = {}", request.getId());
}
//Custom Post Filter
return chain.filter(exchange).then(Mono.fromRunnable(()-> {
if (config.isPostLogger()) {
log.info("Logging Post Filter : request_code = {}", response.getStatusCode());
}
}));
}, Ordered.HIGHEST_PRECEDENCE);
return filter;
}
@Data
public static class Config {
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
💡 OrderedGatewayFilter
- GatewayFilter는 인스턴스이므로 직접 사용 불가능하기 때문에
OrderedGatewayFilter를 사용.➡
OrderedGatewayFilter내부- 생성자 구현을 위해
GatewayFilter와order지정 필요하여filter()메서드 구현- 객체
ServerWebExchange는 Server Request, Response를 사용하게 도와줌 ➡ Response, Request 정보를 알 수 있음
💡 Ordered.HIGHEST_PRECEDENCE
- 컴포넌트나 빈의 로드 순서를 정의할 때 사용
- Ordered.HIGHEST_PRECEDENCE : 가장 높은 우선순위
- Ordered.LOWEST_PRECEDENCE : 가장 낮은 순위 (기본 값)
(🔗 출처: 스프링부트 Controller Advice 우선순위 지정)
spring:
application:
name: apigateway-service
cloud:
gateway:
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
- CustomFilter
# - AddRequestHeader=first-request,first-request-header2
# - AddResponseHeader=first-response,first-response-header2
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
- name: CustomFilter
- name: LoggingFilter
args:
baseMessage: Hi, there.
preLogger: true
postLogger: true
# - AddRequestHeader=second-request,second-request-header2
# - AddResponseHeader=second-response,second-response-header2
default-filters:
- name: GlobalFilter
args:
baseMessage: Spring Cloud Gateway Global Filter
preLogger: true
postLogger: true
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
- Logging Filter는 Second-service에만 적용
- 파라미터값이 있을 경우에는 - 를 사용하여 구분 필요
# 파라미터값 없음 spring: cloud: gateway: routes: - id: second-service uri: http://localhost:8082/ predicates: - Path=/second-service/** filters: name: CustomFilter name: LoggingFilter # 파라미터값 있음 spring: cloud: gateway: routes: - id: second-service uri: http://localhost:8082/ predicates: - Path=/second-service/** filters: - name: CustomFilter - name: LoggingFilter args: baseMessage: Hi, there. preLogger: true postLogger: true
first-service 실행 시
✅ first-service에는 Logging Filter를 적용하지 않았기 때문에 콘솔에 Logging 관련하여 메시지가 뜨지 않음second-service 실행 시
✅ Logging Filter가 먼저 실행된 이유?Ordered.HIGHEST_PRECEDENCE 를 사용하여 Logging Filter의 우선순위를 가장 높게 설정했기 때문에 가장 먼저 실행됨