赞
踩
springboot 2.6.+中文资源名称无法访问,英文正常_我是一座离岛的博客-CSDN博客
原因:
从2.6.0开始Spring MVC 处理程序映射匹配请求路径的默认策略已从 AntPathMatcher 更改为PathPatternParser。
基本可以确定是这个更改导致的,不知道是不是bug,更改之后具体的不知道改动了哪些,能力有限,暂时未知
springboot一般配置资源是这样:
- @Configuration
- public class WebConfig implements WebMvcConfigurer {
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/files/**").addResourceLocations("file:E:/FileUpload/HmiInterface/";
- }
- }
一点分析:
从addResourceHandlers追踪,最终发现会到ResourceHttpRequestHandler,通过ResourceHttpRequestHandler调试发现,在使用PathPatternParser 后,现在传进来的url是原始的未decode过的url,但是UrlPathHelper 默认设置是decodeURL的,这就导致重复进行了一次encode----------ResourceHttpRequestHandler.java-------------
- @Nullable
- protected Resource getResource(HttpServletRequest request) throws IOException {
- //这里获取的path是原始的encode的URL,而小于2.6版本会根据UrlPathHelper 里设置的decodeurl会有不同的值
- String path = (String)request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
- if (path == null) {
- throw new IllegalStateException("Required request attribute '" + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
- } else {
- path = this.processPath(path);
- if (StringUtils.hasText(path) && !this.isInvalidPath(path)) {
- if (this.isInvalidEncodedPath(path)) {
- return null;
- } else {
- Assert.notNull(this.resolverChain, "ResourceResolverChain not initialized.");
- Assert.notNull(this.transformerChain, "ResourceTransformerChain not initialized.");
- //这里调用到PathResourceResolver
- Resource resource = this.resolverChain.resolveResource(request, path, this.getLocations());
- if (resource != null) {
- resource = this.transformerChain.transform(request, resource);
- }
-
- return resource;
- }
- } else {
- return null;
- }
- }
- }
-----------PathResourceResolver.java-----------------private String encodeOrDecodeIfNecessary(String path, @Nullable HttpServletRequest request, Resource location) {
if (this.shouldDecodeRelativePath(location, request)) {
return UriUtils.decode(path, StandardCharsets.UTF_8);
} else if (this.shouldEncodeRelativePath(location) && request != null) {//因为UrlPathHelper 默认是decodeURL的,理论上这里的path应该是decode过的,所以这里会进行encode一次,便于查找文件时decode回来,但是现在这里的path都是encode过的,并不是原始的url,不论你UrlPathHelper 设置decode还是关闭,这就导致后面查文件的时候decode回来的是encode的url,所以找不到文件
- Charset charset = (Charset)this.locationCharsets.getOrDefault(location, StandardCharsets.UTF_8);
- StringBuilder sb = new StringBuilder();
- StringTokenizer tokenizer = new StringTokenizer(path, "/");
-
- while(tokenizer.hasMoreTokens()) {
- String value = UriUtils.encode(tokenizer.nextToken(), charset);
- sb.append(value);
- sb.append('/');
- }
-
- if (!path.endsWith("/")) {
- sb.setLength(sb.length() - 1);
- }
-
- return sb.toString();
- } else {
- return path;
- }
- }
- private boolean shouldEncodeRelativePath(Resource location) {
- return location instanceof UrlResource && this.urlPathHelper != null && this.urlPathHelper.isUrlDecode();
- }
这就导致在AbstractFileResolvingResource.java getFile的时候获取不到文件了
- public File getFile() throws IOException {
- URL url = this.getURL();
- return url.getProtocol().startsWith("vfs") ? AbstractFileResolvingResource.VfsResourceDelegate.getResource(url).getFile() : ResourceUtils.getFile(url, this.getDescription());
- }
因为这里ResourceUtils去获取文件时解码出来的是我们请求的原始的encodeurl,还需要在decode一次才是真正的文件名,所以我们可以关闭decode,但是这样会影响到哪些地方 未知解决办法:
1.UrlPathHelper 设置不decodeurl
- @Configuration
- public class WebConfig implements WebMvcConfigurer {
-
- @Override
- public void configurePathMatch(PathMatchConfigurer configurer) {
- UrlPathHelper urlPathHelper=new UrlPathHelper();
- urlPathHelper.setUrlDecode(false);
- urlPathHelper.setDefaultEncoding(StandardCharsets.UTF_8.name());
- configurer.setUrlPathHelper(urlPathHelper);
- }
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/files/**").addResourceLocations("file:E:/FileUpload/HmiInterface/");
- }
- }
2.使用原来的AntPathMatcher (推荐)
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
能力有限,往上不是很好去调试了,不知道这算不算是bug吧,等待后续观察。
————————————————
版权声明:本文为CSDN博主「我是一座离岛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ngl272/article/details/122458262
使用springboot访问本地电脑资源,并解决中文路径无法访问的问题_il_持之以恒_li的博客-CSDN博客_springboot 中文路径
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。