短信预约-IT技能 免费直播动态提醒
基于Ant路径匹配规则AntPathMatcher的注意事项
目录
- AntPathMatcher前言
- 基本规则
- 注意事项
- 测试用例
- spring url匹配工具类----AntPathMatcher
AntPathMatcher前言
(1)SpringMVC的路径匹配规则是依照Ant的来的,实际上不只是SpringMVC,整个Spring框架的路径解析都是按照Ant的风格来的;
(2)AntPathMatcher不仅可以匹配Spring的@RequestMapping路径,也可以用来匹配各种字符串,包括文件路径等。
基本规则
(1)? 匹配一个字符(除过操作系统默认的文件分隔符)
(2)* 匹配0个或多个字符
(3)**匹配0个或多个目录
(4){spring:[a-z]+} 将正则表达式[a-z]+匹配到的值,赋值给名为 spring 的路径变量.
(PS:必须是完全匹配才行,在SpringMVC中只有完全匹配才会进入controller层的方法)
注意事项
(1)匹配文件路径,需要匹配某目录下及其各级子目录下所有的文件,使用*而非*.*,因为有的文件不一定含有文件后缀;
(2)匹配文件路径,使用AntPathMatcher创建一个对象时,需要注意AntPathMatcher也有有参构造,传递路径分隔符参数pathSeparator,对于文件路径的匹配来说,则需要根据不同的操作系统来传递各自的文件分隔符,以此防止匹配文件路径错误。源码截图如下:
可以看到,AntPathMatcher默认路径分隔符为“/”,而在匹配文件路径时,需要注意Windows下路径分隔符为“\”,Linux下为“/”,写法即为:
AntPathMatcher matcher = new AntPathMatcher(File.separator);
AntPathMatcher matcher = new AntPathMatcher(System.getProperty("file.separator"));
(3)最长匹配规则(has more characters),即越精确的模式越会被优先匹配到。例如,URL请求/app/dir/file.jsp,现在存在两个路径匹配模式*.jsp和/app/dir**", "/testing/testing"));
assertTrue(pathMatcher.match("*", "/testing/testing"));
assertTrue(pathMatcher.match("/blabla", "/bla/testing/testing/bla"));
assertTrue(pathMatcher.match("/blabla", "/bla/testing/testing/bla/bla"));
assertTrue(pathMatcher.match("test", "/bla/bla/test"));
assertTrue(pathMatcher.match("/bla**/bla", "/bla/bla/bla/bla/bla/bla"));
assertTrue(pathMatcher.match("/bla*bla/test", "/blaXXXbla/test"));
assertTrue(pathMatcher.match("*bla", "/bla/bla/bla/bbb"));
assertTrue(pathMatcher.match("**/bla**/bla**/bla**/bla**/bla**/bla**/bla**/blabla", "/x/x/x/"));
assertTrue(pathMatcher.match("/foo/bar/**", "/foo/bar")) ;
assertTrue(pathMatcher.match("", ""));
assertTrue(pathMatcher.match("/{bla}.*", "/testing.html"));
spring url匹配工具类----AntPathMatcher
在gateway进行授权认证时,有些请求url需要过滤掉,针对带/service/{id}/user-info这种带操作符的请求,需要特殊处理----AntPathMatcher就上场啦
具体使用场景
1.登录授权验证:过滤掉登录请求,一些资源获取请求
2.请求接口日志打印:过滤掉文件上传和下载的一些请求,requestBody里的文件流会被异常修改
具体代码:
请求body的二次写入
@Component
public class CachePostBodyFilter implements GlobalFilter, Ordered {
private final List<HttpMessageReader<?>> messageReaders;
public CachePostBodyFilter() {
this.messageReaders = HandlerStrategies.withDefaults().messageReaders();
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
if (FilterUrl.excludeUrls(new FilterUrl(request.getPath().toString(), request.getMethod()))) {
return chain.filter(exchange);
}
if (Objects.equals(request.getMethod(), HttpMethod.POST)) {
ServerRequest serverRequest = ServerRequest.create(exchange,
messageReaders);
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(body -> {
exchange.getAttributes().put(RequestConstants.REQUEST_BODY, body);
return Mono.just(body);
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
// the new content type will be computed by bodyInserter
// and then set in the request decorator
headers.remove(HttpHeaders.CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext()).
then(Mono.defer(() -> {
ServerHttpRequest decorator = decorate(exchange, headers,
outputMessage);
return chain.filter(exchange.mutate().request(decorator).build());
}));
}
return chain.filter(exchange);
}
ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers,
CachedBodyOutputMessage outputMessage) {
return new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(headers);
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
}
@Override
public int getOrder() {
return -8;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FilterUrl {
private String url;
private HttpMethod method;
public static boolean excludeUrls(FilterUrl targetUrl) {
List<FilterUrl> excludeUrls = Lists.newArrayList();
excludeUrls.add(new FilterUrl("/api/v1/service/users", HttpMethod.POST));
excludeUrls.add(new FilterUrl("/api/v1/service/terms/{termId}/export", HttpMethod.GET));
AntPathMatcher antPathMatcher = new AntPathMatcher();
return excludeUrls.stream()
.anyMatch(url -> antPathMatcher.match(url.getUrl(), targetUrl.getUrl()) && url.getMethod().equals(targetUrl.getMethod()));
}
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341