在WebFilter中識(shí)別web接口上添加的自定義注解:
Controller的接口如下(@Token是自己建立的注解):
@Token
@GetMapping("/test")
public Mono<String> test() {
return Mono.just("success");
}
WebFilter代碼:
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class TokenFilter implements WebFilter {
@Resource
private RequestMappingHandlerMapping requestMappingHandlerMapping;
private boolean flag;
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpResponse res = exchange.getResponse();
ServerHttpRequest req = exchange.getRequest();
// 獲取請(qǐng)求對(duì)應(yīng)的HandlerMethod
Mono<HandlerMethod> handlerMethodMono = requestMappingHandlerMapping
.getHandler(exchange).cast(HandlerMethod.class);
return handlerMethodMono.zipWhen(handlerMethod -> {
// 判斷Method是否含有對(duì)應(yīng)注解
if (handlerMethod.hasMethodAnnotation(Token.class)) {
MultiValueMap<String, String> params = req.getQueryParams();
HttpHeaders headers = req.getHeaders();
// 從參數(shù)中獲取token
String token = params.getFirst("token");
// 從header獲取token
token = headers.getFirst("token");
// TODO: 校驗(yàn)Token
boolean valid = true;
// 校驗(yàn)通過(guò),過(guò)濾器正常放行
if (valid) return chain.filter(exchange);
}
// TODO: 校驗(yàn)不通過(guò),返回錯(cuò)誤信息
res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));
}).map(Tuple2::getT2);
}
}
一些可能不用在意的點(diǎn):
1、Token.class改成自己對(duì)應(yīng)的注解
flag = handlerMethod.hasMethodAnnotation(Token.class);
2、設(shè)置狀態(tài)碼不是必須的,但這是個(gè)枚舉型,里面可能沒(méi)有一些你想要的奇怪值
res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
3、自定義的返回內(nèi)容要轉(zhuǎn)成byte數(shù)組
byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));
4、你需要的請(qǐng)求參數(shù)可以從這兒取
MultiValueMap<String, String> params = req.getQueryParams();
HttpHeaders headers = req.getHeaders();
5、Debug了幾遍,RequestMappingHandlerMapping的beanName是requestMappingHandlerMapping,他記錄了所有接口地址和對(duì)應(yīng)方法
@Resource
private RequestMappingHandlerMapping requestMappingHandlerMapping;
6、springboot版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/>
</parent>