如何在 Spring Boot 中获取静态资源 (js, css) 作为 ClassPathResource?
How to get static resource (js, css) as ClassPathResource in Spring Boot?
我需要能够从 Spring 引导模板生成 PDF。为此,我使用了一个 PDF 渲染库 (FlyingSaucer),它大部分都能正确完成这项工作。但是,存在一个问题:当我在页面上有 "href" 标签时,当 PDF 渲染器尝试渲染 HTML 时,它们无法正确解析。例如,如果我有以下代码:
<link rel="stylesheet" type="text/css" th:href="@{/css/index.css}" />
它在浏览器中正确解析,但是当我尝试使用以下代码将其作为 ClassPath 资源检索时:
new ClassPathResource("/css/index").getInputStream()
Spring开机提示文件不存在。这对我来说很奇怪,因为我认为 Spring Boot 会将所有静态内容添加到类路径中。
下面是我项目的文件夹结构,(我认为)遵循正确的 Spring 引导约定:
我能否获得某些 Spring 资源的句柄(通过自动装配、应用程序上下文等)来解析这些 URL,就像浏览器请求它们时所做的那样?我可能可以通过将 "resources/static/" 硬编码到 url 字符串的开头来解决这个问题,但我更喜欢更动态的解决方案。
使用这个:
new ClassPathResource("static/css/index.css").getInputStream();
在尝试了各种解决方案之后,我设法想出了一个,尽管 Amant Simgh 给出了答案,但它不需要我对任何路径进行硬编码。我在我的解决方案中加入了很多东西(使用图像、部署到 tomcat 容器、运行 "bootRun"、使用 webjars),它似乎在每种情况下都有效。
在内部,Spring Boot 使用 ResourceHttpRequestHandler class 来解析资源。这允许 Spring 引导应用程序 @Autowire ResourceHttpRequestHandler bean。因此,为了从后端从 java 代码中获取静态资源,您可以执行以下操作:
@Autowired
ResourceHttpRequestHandler resourceHandler;
String uri = "/css/mycss.css";
Resource resource;
for (ResourceResolver resourceResolver : resourceHandler.getResourceResolvers())
{
resource = resourceResolver.resolveResource(null, uri, resourceHandler.getLocations(), null);
if (resource != null)
break;
}
这基本上就是 Spring当您请求静态资源时 Boot 正在做的事情。
重要提示:如果您的应用程序有上下文路径(即,您部署了一个 "myapp" 应用程序,那么上下文路径将为“/myapp/”),那么您必须从 URI 中删除上下文路径在上面的例子中。幸运的是,这可以通过以下方式轻松完成:
ServletContext context = // get servlet context somehow
String uriWithoutContext = uri.replace(context.getContextPath(), "");
我需要能够从 Spring 引导模板生成 PDF。为此,我使用了一个 PDF 渲染库 (FlyingSaucer),它大部分都能正确完成这项工作。但是,存在一个问题:当我在页面上有 "href" 标签时,当 PDF 渲染器尝试渲染 HTML 时,它们无法正确解析。例如,如果我有以下代码:
<link rel="stylesheet" type="text/css" th:href="@{/css/index.css}" />
它在浏览器中正确解析,但是当我尝试使用以下代码将其作为 ClassPath 资源检索时:
new ClassPathResource("/css/index").getInputStream()
Spring开机提示文件不存在。这对我来说很奇怪,因为我认为 Spring Boot 会将所有静态内容添加到类路径中。
下面是我项目的文件夹结构,(我认为)遵循正确的 Spring 引导约定:
我能否获得某些 Spring 资源的句柄(通过自动装配、应用程序上下文等)来解析这些 URL,就像浏览器请求它们时所做的那样?我可能可以通过将 "resources/static/" 硬编码到 url 字符串的开头来解决这个问题,但我更喜欢更动态的解决方案。
使用这个:
new ClassPathResource("static/css/index.css").getInputStream();
在尝试了各种解决方案之后,我设法想出了一个,尽管 Amant Simgh 给出了答案,但它不需要我对任何路径进行硬编码。我在我的解决方案中加入了很多东西(使用图像、部署到 tomcat 容器、运行 "bootRun"、使用 webjars),它似乎在每种情况下都有效。
在内部,Spring Boot 使用 ResourceHttpRequestHandler class 来解析资源。这允许 Spring 引导应用程序 @Autowire ResourceHttpRequestHandler bean。因此,为了从后端从 java 代码中获取静态资源,您可以执行以下操作:
@Autowired
ResourceHttpRequestHandler resourceHandler;
String uri = "/css/mycss.css";
Resource resource;
for (ResourceResolver resourceResolver : resourceHandler.getResourceResolvers())
{
resource = resourceResolver.resolveResource(null, uri, resourceHandler.getLocations(), null);
if (resource != null)
break;
}
这基本上就是 Spring当您请求静态资源时 Boot 正在做的事情。
重要提示:如果您的应用程序有上下文路径(即,您部署了一个 "myapp" 应用程序,那么上下文路径将为“/myapp/”),那么您必须从 URI 中删除上下文路径在上面的例子中。幸运的是,这可以通过以下方式轻松完成:
ServletContext context = // get servlet context somehow
String uriWithoutContext = uri.replace(context.getContextPath(), "");