有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用Spring Boot在运行时提供静态资源?

我有一个Spring Boot应用程序,它只有一个HTML页面,允许用户上传图像,另一个页面可以查看上传的图像

以下是我的项目结构:

enter image description here

我的Windows电脑工作正常,然后我在运行Spring Boot应用程序的Ubuntu服务器上创建了一个服务,这里的图像上传工作正常,但在另一个HTML页面上,图像没有显示,显示如下:

enter image description here 我试图停止服务并重新启动,图像显示正确!!! 因此,在运行时看不到新图像,但当我重新启动时,图像会出现

我怎样才能解决这个问题

以下是我的网络配置:

@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                 .addResourceLocations("classpath:/static/");
    }
}

这是我的图像保护程序:

public static void saveFile(String uploadDirImg, String fileName, MultipartFile image) throws IOException {
        Path pathForSavingImg = Paths.get("src", "main", "resources", "static", "db_images");
        Path filePath = pathForSavingImg.resolve(fileName);
        image.transferTo(filePath);
         
    }

共 (1) 个答案

  1. # 1 楼答案

    首先,让我们解释一下为什么会发生这种行为。您正在使用Maven来构建和管理您的项目。为了简化,每次构建和运行应用程序时,Maven都会将构建结果输出到/target目录中。您可以在文件系统的/backend/target中找到它

    在应用程序运行时,应用程序从/target文件夹运行,因此类路径是/target/classes/,而不是/src/main/resources。这一点非常重要,因为你正在做的是以下几点(我在课堂上添加了评论):

    @Configuration
    public class WebConfiguration extends WebMvcConfigurationSupport {
    
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry
    
                // here you match any resource path from the URL 
                .addResourceHandler("/**") 
    
                // to search in the classpath:/static/ folder, which in your build
                // is "/target/static" and NOT "/src/main/resources/static"
                .addResourceLocations("classpath:/static/");
        }
    }
    

    我想你现在可以看到这个问题以及对应用行为的解释了。基本上,你在/src/main/resources/static/db_images文件夹中上传文件(图像),而应用程序在运行时在/backend/target/static/db_images文件夹中搜索它们

    重新加载应用程序时,图像会正常工作,因为应用程序会再次重建db_images文件夹,并将其从/src/main/resources/static/复制到/target/static/,可以找到之前的上载

    为了解决这个问题,一个好的建议和一个已知的实践是在项目之外使用一个文件系统文件夹,并通过绝对路径引用它。上传文件夹通常是你想从应用程序的源代码中得到的东西,这是有充分理由的(首先想到的是文件夹的大小)

    所以,如果您有不同的环境,您可以在应用程序中添加一些属性。属性来控制上传路径,如下所示:

    # For Windows OS
    upload.folder.path=D:/db_images/
    

    或者

    # For Unix-like OS
    upload.folder.path=/srv/db_images/
    

    那么你的网络配置应该是这样的:

    @Configuration
    public class WebConfiguration extends WebMvcConfigurationSupport {
    
        @Value("${upload.folder.path}")
        private String uploadFolderPath;
    
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry
                .addResourceHandler("/**") 
                .addResourceLocations("file:" + uploadFolderPath);
        }
    }
    

    当然,图像保护程序应该考虑到这一点,并进行相应的修改

    public static void saveFile(String uploadDirImg, String fileName, MultipartFile image) throws IOException {
            Path pathForSavingImg = Paths.get(uploadFolderPath);
            Path filePath = pathForSavingImg.resolve(fileName);
            image.transferTo(filePath);
             
        }