Pour utiliser MDC avec Spring WebFlux, utilisez le contexte J'ai écrit sur l'histoire de la propagation de MDC entre les applications. Je vais. La connaissance de l'article ci-dessus est requise en termes de contenu.
Les microservices qui sont populaires de nos jours présentent diverses complications, dont l'une est le journal. Il existe une demande naturelle pour que la communication qui coule d'un système -> système B -> système C soit transformée en un seul journal plus tard, et diverses méthodes ont été utilisées pour résoudre ce problème. (Spring Sleuth, etc.)
De la même manière, il y avait une demande pour nous laisser prendre en charge diverses informations de débogage ensemble, et notre système était juste pris dedans.
Cette fois, je reprendrai l'une des méthodes introduites dans Passing Context with Spring Web Flux
.
Pour écrire brièvement ce que fait WebFilter, que je présenterai à partir de maintenant
--Pour la demande, j'ai obtenu tous les HttpHeaders avec le préfixe X-MDC-
, j'ai enlevé le préfixe et l'ai mis dans le contexte. La valeur clé du contexte est la constante CONTEXT_MAP
.
--Pour la réponse, la valeur tirée de la constante CONTEXT_MAP
est renvoyée avec le préfixe X-MDC-
.
MdcHeaderFilter.java
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import reactor.util.context.Context;
import java.util.Map;
import static java.util.stream.Collectors.toMap;
import static jp.co.example.helper.LogHelper.*;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MdcHeaderFilter implements WebFilter {
private static final String MDC_HEADER_PREFIX = "X-MDC-";
@Override
public Mono<Void> filter(
ServerWebExchange ex,
WebFilterChain chain) {
ex.getResponse().beforeCommit(
() -> addContextToHttpResponseHeaders(ex.getResponse())
);
return chain.filter(ex)
.subscriberContext(
ctx -> addRequestHeadersToContext(ex.getRequest(), ctx)
);
}
private Context addRequestHeadersToContext(
final ServerHttpRequest request,
final Context context) {
final Map<String, String> contextMap = request
.getHeaders().toSingleValueMap().entrySet()
.stream()
.filter(x -> x.getKey().startsWith(MDC_HEADER_PREFIX))
.collect(
toMap(v -> v.getKey().substring(MDC_HEADER_PREFIX.length()),
Map.Entry::getValue
)
);
//Par exemple, si vous souhaitez mettre un cookie, vous pouvez le faire
String cookie = request.getCookies().containsKey("EXAMPLE") ?
request.getCookies().getFirst("EXAMPLE").getValue() : "none";
contextMap.put("example-cookie", cookie);
return context.put(CONTEXT_MAP, contextMap);
}
private Mono<Void> addContextToHttpResponseHeaders(
final ServerHttpResponse res) {
return Mono.subscriberContext().doOnNext(ctx -> {
if (!ctx.hasKey(CONTEXT_MAP)) return;
final HttpHeaders headers = res.getHeaders();
ctx.<Map<String, String>>get(CONTEXT_MAP).forEach(
(key, value) -> headers.add(MDC_HEADER_PREFIX + key, value)
);
}).then();
}
}
C'est très simple à faire, mais c'est polyvalent. Il peut également être utilisé lorsque vous devez utiliser un certain cookie comme information utilisateur pour le débogage, comme notre système ~~ F ● ck ~~.
Ne vous laissez pas prendre par la réponse que vous donnez à vos clients!