springboot 图片映射404问题

问题:

今天简单的将springboot项目搭配起来后,想配置一下静态图片的访问。
springboot静态内容默认是/static (or /public or /resources or /META-INF/resources)这四个目录。
如果需要添加映射而不是完全修改的话,可以添加一个WebMvcConfigurer类并重写addResourceHandlers这个方法,如下:

@Configuration
public class ResourceHandler implements WebMvcConfigurer {

    @Value("${upload}")
    private String uploadPattern;
    @Value("${upload.location}")
    private String uploadLocation;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(uploadPattern).addResourceLocations("file:" + uploadLocation);
    }
}
upload.location=D:/uploadFile
upload=/upload/**

配置如上,但是问题来了,通过localhost:8080/upload/xx.png访问后得到的是404的错误页。

解决方案如下:

将upload.location=D:/uploadFile修改为upload.location=D:/uploadFile/

分析

每个请求都会经过DispatcherServlet的doService方法,继而调用doDispatch。
于是断点进入doDispatch:
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
继续下一步发现是调用了HttpRequestHandlerAdapter的handle方法,这个方法又调用了ResourceHttpRequestHandler.handleRequest方法。
看到这里大概明白了,先获取资源,获取不到就404,于是继续跟踪下去。查看getResource方法:

@Override
	public void handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// For very general mappings (e.g. "/") we need to check 404 first
		Resource resource = getResource(request);
	//...
@Nullable
	protected Resource getResource(HttpServletRequest request) throws IOException {
		//...
		Resource resource = this.resolverChain.resolveResource(request, path, getLocations());
		//...
	}

在这里资源为null,继续跟踪。

在这里插入图片描述
善于运用这个可以反复进来方法,不用每次都刷新页面

一路向下debug,到了PathResourceResolver.getResource方法,这里返回的resource为空

@Nullable
	private Resource getResource(String resourcePath, @Nullable HttpServletRequest request,
			List<? extends Resource> locations) {

		//...
				Resource resource = getResource(pathToUse, location);
			//...

进入getResource方法,发现调用是location.createRelative(resourcePath);
实际是FileUrlResource.createRelative

public Resource createRelative(String relativePath) throws MalformedURLException {
        return new FileUrlResource(this.createRelativeURL(relativePath));
    }

在这里createRelativeURL这个方法返回的数据不正常:
在这里插入图片描述
命名映射的是D:/uploadFile/xxx.jpg,怎么就变成了D:/xx.jpg呢,怪不得获取不到资源
进入方法查看:

 protected URL createRelativeURL(String relativePath) throws MalformedURLException {
        if (relativePath.startsWith("/")) {
            relativePath = relativePath.substring(1);
        }

        relativePath = StringUtils.replace(relativePath, "#", "%23");
        return new URL(this.url, relativePath);
    }

URL构造函数:

public URL(URL context, String spec, URLStreamHandler handler)
throws MalformedURLException
{
//...
handler.parseURL
}

实际调用URLStreamHandler.parseURL

if (start < limit) {
            if (spec.charAt(start) == '/') {
                path = spec.substring(start, limit);
            } else if (path != null && path.length() > 0) {
                isRelPath = true;
                int ind = path.lastIndexOf('/');
                String seperator = "";
                if (ind == -1 && authority != null)
                    seperator = "/";
                path = path.substring(0, ind + 1) + seperator +
                         spec.substring(start, limit);

            } else {
                String seperator = (authority != null) ? "/" : "";
                path = seperator + spec.substring(start, limit);
            }
        }

看到这里才明白,int ind = path.lastIndexOf(’/’);这里把我的D:/uploadFile截取为D:/了,怪不得最后返回的是D:/xx.png,这路径都被改了,还怎么能找到资源。至此,发现了问题,于是把upload.location=D:/uploadFile修改为upload.location=D:/uploadFile/即可。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值