在WebFilter中識別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();
// 獲取請求對應(yīng)的HandlerMethod
Mono<HandlerMethod> handlerMethodMono = requestMappingHandlerMapping
.getHandler(exchange).cast(HandlerMethod.class);
return handlerMethodMono.zipWhen(handlerMethod -> {
// 判斷Method是否含有對應(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: 校驗Token
boolean valid = true;
// 校驗通過零渐,過濾器正常放行
if (valid) return chain.filter(exchange);
}
// TODO: 校驗不通過,返回錯誤信息
res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));
}).map(Tuple2::getT2);
}
}
一些可能不用在意的點:
1、Token.class改成自己對應(yīng)的注解
flag = handlerMethod.hasMethodAnnotation(Token.class);
2、設(shè)置狀態(tà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、你需要的請求參數(shù)可以從這兒取
MultiValueMap<String, String> params = req.getQueryParams();
HttpHeaders headers = req.getHeaders();
5堡僻、Debug了幾遍,RequestMappingHandlerMapping的beanName是requestMappingHandlerMapping疫剃,他記錄了所有接口地址和對應(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>