一个场景:给一个系统增加维护模式,这个模式下的系统所有接口均返回一个状态和描述,例如:{code:307,msg:当前维护中}。另外,如果请求的header中如果包含某个字段,则认为该次请求可跳过维护模式,并正常请求接口。
当前系统使用了Spring Reactive Security实现,因此Servlet的Filter无法使用,好在是Reactive Web也有过滤器:org.springframework.web.server.WebFilter
。
实现WebFilter接口
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Mono;
public class MaintenanceModeFilter implements WebFilter {
private static final String MAINTENANCE_HEADER = "X-Maintenance-Staff";
@Value("{maintenance.enable:false}")
private boolean enabled;
@Value("{maintenance.message:处于维护模式中}")
private String message;
@Override
public Mono filter(ServerWebExchange exchange, WebFilterChain chain) {
if (!enabled) {
return chain.filter(exchange);
}
HttpHeaders headers = exchange.getRequest().getHeaders();
if (headers.containsKey(MAINTENANCE_HEADER)){
return chain.filter(exchange);
}
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
String respStr = "{\"code\":\"307\", \"msg\":\""+message+"\"}";
DataBuffer buffer = response.bufferFactory().wrap(respStr.getBytes());
return response.writeWith(Mono.just(buffer));
}
}
然后使用ServerHttpSecurity.addFilterAt(WebFilter filter, int order)
将上面的MaintenanceModeFilter添加到制定位置即可。
这里我主要想记录的是如果在WebFilter直接返回自定义内容。
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
String respStr = "{\"code\":\"307\", \"msg\":\""+message+"\"}";
DataBuffer buffer = response.bufferFactory().wrap(respStr.getBytes());
return response.writeWith(Mono.just(buffer));
熟悉Netty的都知道DataBuffer是一种另拷贝实现,与日常写ServletFilter稍微有些差异。