在 Micronaut 中,类似于 Spring Boot 框架,我们可以对请求添加过滤器,然后在过滤器中实现一些业务,比如添加访问日志等。本文将介绍如何添加一个过滤器,我们以添加一个访问记录的过滤器为例。
首先我们定义一下访问日志的类,代码如下:
@Data
@Slf4j
public class TraceLog {
private static final String TRACE_FORMAT = "[{} - {} - {}][IP:{},Time:{} - {},Cost:{}ms]";
private HttpMethod method;
private String ip;
private URI uri;
private Instant begin;
private Instant end;
private HttpStatus status;
public TraceLog() {
}
public TraceLog(String ip, HttpMethod method, URI uri) {
this.ip = ip;
this.method = method;
this.uri = uri;
this.begin = Instant.now();
}
public void setStatus(HttpStatus httpStatus) {
this.status = httpStatus;
this.end = Instant.now();
}
/**
* 打印请求完整日志
*/
public void print() {
log.info(TRACE_FORMAT, this.method, this.uri, this.status, this.ip, this.begin, this.end, Duration.between(this.begin, this.end).toMillis());
}
}
在日志类中,我们定义了要用到的相关属性以及输出日志的 print 方法。
接着,我们定义一个日志相关的服务类,示例代码如下:
@RequestScope
@Slf4j
public class TraceService {
private TraceLog traceLog;
/**
* 记录请求
*
* @param request
* @return
*/
public Publisher<Boolean> traceBefore(HttpRequest<?> request) {
Callable<Boolean> callable = () -> {
traceLog = new TraceLog(IpUtil.getRequestIp(request), request.getMethod(), request.getUri());
return true;
};
return Mono.fromCallable(callable).subscribeOn(Schedulers.boundedElastic()).flux();
}
public MutableHttpResponse traceAfter(MutableHttpResponse<?> response) {
traceLog.setStatus(response.getStatus());
traceLog.print();
return response;
}
}
在此服务中,我们定义了访问日志需要获取的相关属性,并填充到日志实例中,然后定义了在访问结束后调用 print 方法输出日志。
最后我们定义过滤器,实现对请求的过滤,示例代码如下:
@Filter("/**")
@Slf4j
public class TraceFilter implements HttpServerFilter {
private final TraceService traceService;
public TraceFilter(TraceService traceService) {
this.traceService = traceService;
}
@Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
return Flux.from(traceService.traceBefore(request))
.switchMap(result -> chain.proceed(request))
.map(response -> traceService.traceAfter(response));
}
}
以上需要注意的,过滤器的注解为 @Filter,/** 代表过滤所有请求,如果有特定过滤需求,可以使用 pattern 模式匹配。
以上就是一种过滤器的实现方法。