当前位置:   article > 正文

spring boot 虚拟路径url中文无法访问_springboot 虚拟url

springboot 虚拟url

springboot 2.6.+中文资源名称无法访问,英文正常_我是一座离岛的博客-CSDN博客

原因:
从2.6.0开始Spring MVC 处理程序映射匹配请求路径的默认策略已从 AntPathMatcher 更改为PathPatternParser。
基本可以确定是这个更改导致的,不知道是不是bug,更改之后具体的不知道改动了哪些,能力有限,暂时未知
springboot一般配置资源是这样:

  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3.     @Override
  4.     public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/files/**").addResourceLocations("file:E:/FileUpload/HmiInterface/";
  5.     }
  6. }


一点分析:
从addResourceHandlers追踪,最终发现会到ResourceHttpRequestHandler,通过ResourceHttpRequestHandler调试发现,在使用PathPatternParser 后,现在传进来的url是原始的未decode过的url,但是UrlPathHelper 默认设置是decodeURL的,这就导致重复进行了一次encode----------ResourceHttpRequestHandler.java-------------
 

  1.   @Nullable
  2.     protected Resource getResource(HttpServletRequest request) throws IOException {
  3.         //这里获取的path是原始的encode的URL,而小于2.6版本会根据UrlPathHelper 里设置的decodeurl会有不同的值
  4.         String path = (String)request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
  5.         if (path == null) {
  6.             throw new IllegalStateException("Required request attribute '" + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
  7.         } else {
  8.             path = this.processPath(path);
  9.             if (StringUtils.hasText(path) && !this.isInvalidPath(path)) {
  10.                 if (this.isInvalidEncodedPath(path)) {
  11.                     return null;
  12.                 } else {
  13.                     Assert.notNull(this.resolverChain, "ResourceResolverChain not initialized.");
  14.                     Assert.notNull(this.transformerChain, "ResourceTransformerChain not initialized.");
  15.                     //这里调用到PathResourceResolver
  16.                     Resource resource = this.resolverChain.resolveResource(request, path, this.getLocations());
  17.                     if (resource != null) {
  18.                         resource = this.transformerChain.transform(request, resource);
  19.                     }
  20.                     return resource;
  21.                 }
  22.             } else {
  23.                 return null;
  24.             }
  25.         }
  26.     }


-----------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,所以找不到文件
           

  1. Charset charset = (Charset)this.locationCharsets.getOrDefault(location, StandardCharsets.UTF_8);
  2.             StringBuilder sb = new StringBuilder();
  3.             StringTokenizer tokenizer = new StringTokenizer(path, "/");
  4.             while(tokenizer.hasMoreTokens()) {
  5.                 String value = UriUtils.encode(tokenizer.nextToken(), charset);
  6.                 sb.append(value);
  7.                 sb.append('/');
  8.             }
  9.             if (!path.endsWith("/")) {
  10.                 sb.setLength(sb.length() - 1);
  11.             }
  12.             return sb.toString();
  13.         } else {
  14.             return path;
  15.         }
  16.     }
  17. private boolean shouldEncodeRelativePath(Resource location) {
  18.         return location instanceof UrlResource && this.urlPathHelper != null && this.urlPathHelper.isUrlDecode();
  19.     }


这就导致在AbstractFileResolvingResource.java getFile的时候获取不到文件了

  1. public File getFile() throws IOException {
  2.         URL url = this.getURL();
  3.         return url.getProtocol().startsWith("vfs") ? AbstractFileResolvingResource.VfsResourceDelegate.getResource(url).getFile() : ResourceUtils.getFile(url, this.getDescription());
  4.     }


因为这里ResourceUtils去获取文件时解码出来的是我们请求的原始的encodeurl,还需要在decode一次才是真正的文件名,所以我们可以关闭decode,但是这样会影响到哪些地方 未知解决办法:
1.UrlPathHelper 设置不decodeurl

  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3.     @Override
  4.     public void configurePathMatch(PathMatchConfigurer configurer) {
  5.         UrlPathHelper urlPathHelper=new UrlPathHelper();
  6.         urlPathHelper.setUrlDecode(false);
  7.         urlPathHelper.setDefaultEncoding(StandardCharsets.UTF_8.name());
  8.         configurer.setUrlPathHelper(urlPathHelper);
  9.     }
  10.     @Override
  11.     public void addResourceHandlers(ResourceHandlerRegistry registry) {  registry.addResourceHandler("/files/**").addResourceLocations("file:E:/FileUpload/HmiInterface/");
  12.     }
  13. }


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 中文路径

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/336776
推荐阅读
相关标签
  

闽ICP备14008679号