使用 iTextPdf FontFactory 从 /WEB-INF/resources/fonts/foobar.ttf 加载字体
Load Font from /WEB-INF/resources/fonts/foobar.ttf with iTextPdf FontFactory
这个问题几乎说明了一切。我得到以下异常:
ExceptionConverter: java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
Caused By: java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
at com.itextpdf.text.io.RandomAccessSourceFactory.createByReadingToMemory(RandomAccessSourceFactory.java:263)
at com.itextpdf.text.io.RandomAccessSourceFactory.createBestSource(RandomAccessSourceFactory.java:173)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.<init>(RandomAccessFileOrArray.java:148)
at com.itextpdf.text.pdf.TrueTypeFont.process(TrueTypeFont.java:641)
at com.itextpdf.text.pdf.TrueTypeFont.<init>(TrueTypeFont.java:375)
at com.itextpdf.text.pdf.BaseFont.getAllFontNames(BaseFont.java:1229)
at com.itextpdf.text.FontFactoryImp.register(FontFactoryImp.java:446)
at com.itextpdf.text.FontFactory.register(FontFactory.java:341)
at bean.createPdf.makePdf(createPdf.java:358)
at bean.auswahl.buttonProbenbegleitschein(auswahl.java:188)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.el.parser.AstValue.invoke(AstValue.java:254)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:148)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at org.apache.myfaces.trinidad.component.UIXComponentBase.broadcast(UIXComponentBase.java:1113)
at org.apache.myfaces.trinidad.component.UIXCommand.broadcast(UIXCommand.java:179)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at oracle.adf.view.rich.event.ProxyEvent.broadcastWrappedEvent(ProxyEvent.java:72)
at oracle.adf.view.rich.component.fragment.UIXRegion.broadcast(UIXRegion.java:124)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at org.apache.myfaces.trinidad.component.WrapperEvent.broadcastWrappedEvent(WrapperEvent.java:82)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.run(ContextSwitchingComponent.java:168)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent._processPhase(ContextSwitchingComponent.java:510)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.broadcast(ContextSwitchingComponent.java:171)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at org.apache.myfaces.trinidad.component.WrapperEvent.broadcastWrappedEvent(WrapperEvent.java:82)
at oracle.adf.view.rich.component.fragment.UIXInclude.broadcast(UIXInclude.java:111)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at org.apache.myfaces.trinidad.component.WrapperEvent.broadcastWrappedEvent(WrapperEvent.java:82)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.run(ContextSwitchingComponent.java:168)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent._processPhase(ContextSwitchingComponent.java:510)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.broadcast(ContextSwitchingComponent.java:171)
at oracle.adf.view.rich.component.fragment.UIXInclude.broadcast(UIXInclude.java:115)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._invokeApplication(LifecycleImpl.java:1074)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:402)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:225)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:346)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.adf.model.servlet.ADFBindingFilter.doFilter(ADFBindingFilter.java:192)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:105)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:502)
at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:60)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:502)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:327)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:229)
at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at de.lkvsh.rdv.portal.authlib.servlet.PortalFilter.doFilter(PortalFilter.java:116)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.security.jps.ee.http.JpsAbsFilter.run(JpsAbsFilter.java:137)
at java.security.AccessController.doPrivileged(Native Method)
at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:315)
at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:460)
at oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:120)
at oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:217)
at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:81)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:220)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3436)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3402)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2285)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2201)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1572)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:255)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
字体文件的物理位置是/WEB-INF/resources/fonts/CALIBRI.TTF
据我所知,iTextPDf FontFactory
.
无法在资源中找到它
java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
我认为 iText 库直接在 WEB-INF 文件夹下而不是 /WEB-INF/resources 下寻找字体。
基于source code of iText's RandomAccessSourceFactory#createBestSource()
, the FontFactory#register()
只能取代表有效(相对)磁盘文件系统路径的路径,或资源URL(例如HTTPURL或classpath URL),不是 WAR 资源路径。您实际上提供了 WAR 资源路径,您通常只能将其传递给 ServletContext#getResource()
、getResourceAsStream()
、getRealPath()
和 getRequestDispatcher()
。
有几种方法可以让它工作:
借助ServletContext#getRealPath()
:
将WAR资源路径转换为绝对磁盘文件系统路径
String path = getServletContext().getRealPath("/WEB-INF/resources/fonts/foobar.ttf");
FontFactory.register(path);
需要注意的是,此方法非常不可移植且依赖于环境。其中,当服务器配置为将 WAR 直接扩展到内存而不是本地磁盘文件系统或使用虚拟文件系统时,这将失败。例如,默认情况下,它可能适用于 Tomcat,但可能不适用于 WebLogic。您的堆栈跟踪确认您正在使用 WebLogic。 getRealPath()
默认总是 return null
.
的可能性很大
将字体文件移出 /WEB-INF
文件夹,以便可以通过 HTTP URL 公开访问。前提是您可以将整个 /resources
文件夹向上移动一层,在 /WEB-INF
之外,并且字体可以通过 http://localhost:8080/context/resources/fonts/foobar.ttf
访问(首先在普通的网络浏览器中进行测试以确保),然后只需提供正是那条路。
String path = "http://localhost:8080/context/resources/fonts/foobar.ttf";
FontFactory.register(path);
如有必要,您可以动态构造 http://localhost:8080/context
(基础 URL),如下所示:
String url = request.getRequestURL().toString();
String baseURL = url.substring(0, url.length() - request.getRequestURI().length()) + request.getContextPath();
String path = baseURL + "/resources/fonts/foobar.ttf";
FontFactory.register(path);
需要注意的是,默认情况下,世界上任何人都可以下载它,即使只是猜测 URL。
将字体文件移动到 class 路径。 IE。确保它最终在所有 Java class 文件和 class 资源文件(例如属性文件)中的 /WEB-INF/classes
中结束。假设包名只是 fonts
。如果您使用的是 Maven,只需将其放入 /main/resources/fonts/foobar.ttf
。如果您使用的 "plain vanilla" Web 项目只有一个 src
文件夹,您可以在其中放置所有 Java 包和 class 源文件,然后创建一个包 fonts
并将 foobar.ttf
文件放在那里。然后你可以提供 /fonts/foobar.ttf
.
的路径
String path = "/fonts/foobar.ttf";
FontFactory.register(path);
这显然是首选方式。
如果 none 以上选项适用,最后的办法是在 File#createTempFile()
in container managed temporary folder, grabbing the WAR resource contents by ServletContext#getResourceAsStream()
的帮助下创建一个临时文件,将其写入临时文件并最终提供绝对值临时文件路径。
String tempDir = (String) getServletContext().getAttribute(ServletContext.TEMPDIR);
File tempFile = File.createTempFile("foobar-", ".ttf", new File(tempDir));
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/resources/fonts/foobar.ttf");
Files.copy(input, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
String path = tempFile.getAbsolutePath();
FontFactory.register(path);
注意:以上答案假定代码放在 "plain" Java EE servlet class 中。如果您使用的是 JSF——正如堆栈跟踪所确认的那样——您可以通过 ExternalContext#getContext()
, the HttpServletRequest
by ExternalContext#getRequest()
, the ServletContext
attributes by ExternalContext#getApplicationMap()
, the real path by ExternalContext#getRealPath()
, and the resource stream by ExternalContext#getResourceAsStream()
.
获得 ServletContext
这个问题几乎说明了一切。我得到以下异常:
ExceptionConverter: java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
Caused By: java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
at com.itextpdf.text.io.RandomAccessSourceFactory.createByReadingToMemory(RandomAccessSourceFactory.java:263)
at com.itextpdf.text.io.RandomAccessSourceFactory.createBestSource(RandomAccessSourceFactory.java:173)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.<init>(RandomAccessFileOrArray.java:148)
at com.itextpdf.text.pdf.TrueTypeFont.process(TrueTypeFont.java:641)
at com.itextpdf.text.pdf.TrueTypeFont.<init>(TrueTypeFont.java:375)
at com.itextpdf.text.pdf.BaseFont.getAllFontNames(BaseFont.java:1229)
at com.itextpdf.text.FontFactoryImp.register(FontFactoryImp.java:446)
at com.itextpdf.text.FontFactory.register(FontFactory.java:341)
at bean.createPdf.makePdf(createPdf.java:358)
at bean.auswahl.buttonProbenbegleitschein(auswahl.java:188)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.el.parser.AstValue.invoke(AstValue.java:254)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:148)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at org.apache.myfaces.trinidad.component.UIXComponentBase.broadcast(UIXComponentBase.java:1113)
at org.apache.myfaces.trinidad.component.UIXCommand.broadcast(UIXCommand.java:179)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at oracle.adf.view.rich.event.ProxyEvent.broadcastWrappedEvent(ProxyEvent.java:72)
at oracle.adf.view.rich.component.fragment.UIXRegion.broadcast(UIXRegion.java:124)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at org.apache.myfaces.trinidad.component.WrapperEvent.broadcastWrappedEvent(WrapperEvent.java:82)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.run(ContextSwitchingComponent.java:168)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent._processPhase(ContextSwitchingComponent.java:510)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.broadcast(ContextSwitchingComponent.java:171)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at org.apache.myfaces.trinidad.component.WrapperEvent.broadcastWrappedEvent(WrapperEvent.java:82)
at oracle.adf.view.rich.component.fragment.UIXInclude.broadcast(UIXInclude.java:111)
at org.apache.myfaces.trinidad.component.UIXComponent.broadcastInContext(UIXComponent.java:364)
at org.apache.myfaces.trinidad.component.WrapperEvent.broadcastWrappedEvent(WrapperEvent.java:82)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.run(ContextSwitchingComponent.java:168)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent._processPhase(ContextSwitchingComponent.java:510)
at oracle.adf.view.rich.component.fragment.ContextSwitchingComponent.broadcast(ContextSwitchingComponent.java:171)
at oracle.adf.view.rich.component.fragment.UIXInclude.broadcast(UIXInclude.java:115)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._invokeApplication(LifecycleImpl.java:1074)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:402)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:225)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:346)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.adf.model.servlet.ADFBindingFilter.doFilter(ADFBindingFilter.java:192)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:105)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:502)
at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:60)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:502)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:327)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:229)
at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at de.lkvsh.rdv.portal.authlib.servlet.PortalFilter.doFilter(PortalFilter.java:116)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.security.jps.ee.http.JpsAbsFilter.run(JpsAbsFilter.java:137)
at java.security.AccessController.doPrivileged(Native Method)
at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:315)
at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:460)
at oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:120)
at oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:217)
at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:81)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:220)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3436)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3402)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2285)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2201)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1572)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:255)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
字体文件的物理位置是/WEB-INF/resources/fonts/CALIBRI.TTF
据我所知,iTextPDf FontFactory
.
java.io.IOException: /fonts/CALIBRI.TTF not found as file or resource.
我认为 iText 库直接在 WEB-INF 文件夹下而不是 /WEB-INF/resources 下寻找字体。
基于source code of iText's RandomAccessSourceFactory#createBestSource()
, the FontFactory#register()
只能取代表有效(相对)磁盘文件系统路径的路径,或资源URL(例如HTTPURL或classpath URL),不是 WAR 资源路径。您实际上提供了 WAR 资源路径,您通常只能将其传递给 ServletContext#getResource()
、getResourceAsStream()
、getRealPath()
和 getRequestDispatcher()
。
有几种方法可以让它工作:
借助
将WAR资源路径转换为绝对磁盘文件系统路径ServletContext#getRealPath()
:String path = getServletContext().getRealPath("/WEB-INF/resources/fonts/foobar.ttf"); FontFactory.register(path);
需要注意的是,此方法非常不可移植且依赖于环境。其中,当服务器配置为将 WAR 直接扩展到内存而不是本地磁盘文件系统或使用虚拟文件系统时,这将失败。例如,默认情况下,它可能适用于 Tomcat,但可能不适用于 WebLogic。您的堆栈跟踪确认您正在使用 WebLogic。
的可能性很大getRealPath()
默认总是 returnnull
.将字体文件移出
/WEB-INF
文件夹,以便可以通过 HTTP URL 公开访问。前提是您可以将整个/resources
文件夹向上移动一层,在/WEB-INF
之外,并且字体可以通过http://localhost:8080/context/resources/fonts/foobar.ttf
访问(首先在普通的网络浏览器中进行测试以确保),然后只需提供正是那条路。String path = "http://localhost:8080/context/resources/fonts/foobar.ttf"; FontFactory.register(path);
如有必要,您可以动态构造
http://localhost:8080/context
(基础 URL),如下所示:String url = request.getRequestURL().toString(); String baseURL = url.substring(0, url.length() - request.getRequestURI().length()) + request.getContextPath(); String path = baseURL + "/resources/fonts/foobar.ttf"; FontFactory.register(path);
需要注意的是,默认情况下,世界上任何人都可以下载它,即使只是猜测 URL。
将字体文件移动到 class 路径。 IE。确保它最终在所有 Java class 文件和 class 资源文件(例如属性文件)中的
的路径/WEB-INF/classes
中结束。假设包名只是fonts
。如果您使用的是 Maven,只需将其放入/main/resources/fonts/foobar.ttf
。如果您使用的 "plain vanilla" Web 项目只有一个src
文件夹,您可以在其中放置所有 Java 包和 class 源文件,然后创建一个包fonts
并将foobar.ttf
文件放在那里。然后你可以提供/fonts/foobar.ttf
.String path = "/fonts/foobar.ttf"; FontFactory.register(path);
这显然是首选方式。
如果 none 以上选项适用,最后的办法是在
File#createTempFile()
in container managed temporary folder, grabbing the WAR resource contents byServletContext#getResourceAsStream()
的帮助下创建一个临时文件,将其写入临时文件并最终提供绝对值临时文件路径。String tempDir = (String) getServletContext().getAttribute(ServletContext.TEMPDIR); File tempFile = File.createTempFile("foobar-", ".ttf", new File(tempDir)); InputStream input = getServletContext().getResourceAsStream("/WEB-INF/resources/fonts/foobar.ttf"); Files.copy(input, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); String path = tempFile.getAbsolutePath(); FontFactory.register(path);
注意:以上答案假定代码放在 "plain" Java EE servlet class 中。如果您使用的是 JSF——正如堆栈跟踪所确认的那样——您可以通过 ExternalContext#getContext()
, the HttpServletRequest
by ExternalContext#getRequest()
, the ServletContext
attributes by ExternalContext#getApplicationMap()
, the real path by ExternalContext#getRealPath()
, and the resource stream by ExternalContext#getResourceAsStream()
.
ServletContext