考虑以下代码(完全基于飞碟的“入门”代码,保留其权利):
package flyingsaucerpdf;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.xhtmlrenderer.pdf.ITextRenderer;
public class PDFMaker {
public static void main(String[] args) throws Exception {
new PDFMaker().go();
}
public void go() throws Exception {
String inputFile = "sample.html";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
}
}
几个事实:
但是,当通过URLClassLoader从现有的Web应用程序加载时,它将失败并显示以下错误:
由以下原因引起:org.w3c.dom.DOMException:NAMESPACE_ERR:试图以对名称空间不正确的方式创建或更改对象。
在org.apache.xerces.dom.AttrNSImpl.setName(未知来源)
在org.apache.xerces.dom.AttrNSImpl。(来源不明)
在org.apache.xerces.dom.CoreDocumentImpl.createAttributeNS(未知来源)
在org.apache.xerces.dom.ElementImpl.setAttributeNS(未知来源)
在org.apache.xml.utils.DOMBuilder.startElement(DOMBuilder.java:307)
…另外19个
在错误的位置寻找了一段时间后(例如,我怀疑是xalan / xerces
jars,创建了一个孩子优先/父母最后的类加载器,但仍然失败了),我终于缩小了根本原因:
似乎加载我的代码的Web应用程序具有旧的 xalan.jar ,规范版本1.2
我做了一些测试,以独立的方式运行了上面的代码(之前运行良好),但是这次我将Web应用程序中的 xalan.jar
添加到了它的类路径和bingo中,这与Web应用程序场景中的错误相同
因此,我检查了那个旧的xalan.jar并想知道,什么会导致JVM加载它的旧的xalan实现而不是JDK的实现?毕竟,我的子优先级类加载器也是最后一个父级加载器,例如中间的系统,要说:在父级之前搜索系统类加载器(以避免加载父级覆盖的JDK
jar,就像这种情况下,父级的xalan.jar覆盖了JDK的xalan实现)
然后,有些事情引起了我的注意-文件 xalan.jar / META-INF / services /中 名为
javax.xml.transform.TransformerFactory的 内容如下:
org.apache.xalan.processor.TransformerFactoryImpl
因此,我立即在eclipse中按下Ctrl
+ T
并寻找完整的限定名称…仅在 xalan.jar中 !
然后,我仅搜索“ TransformerFactoryImpl”,这就是JDK的功能:
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
容易看出差异
因此,如果您读到这里,我的底线问题是: 如何使我的TransformerFactory使用JDK的实现而不是旧的Xalan的实现?
(我无法从加载我的代码的网络应用中删除该jar)
答案似乎比我想的要简单。
在您的类加载器中,将此文件夹添加到类路径(不需要jar): /META-INF/services/
在其中创建一个名为 javax.xml.transform.TransformerFactory
编辑它,并将其设置为以下内容: com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
而已!
为什么行得通?请参阅Java用来加载Xalan实现的此类。
请注意,对于该特定的“ META-
INF”条目,它似乎事实上是父后(或子优先)加载器(与常规Java类加载器的工作方式相反,例如,父先/子后)。如果我错了纠正我
摘录自 javax.xml.datatype.FactoryFinder
/*
* Try to find provider using Jar Service Provider Mechanism
*
* @return instance of provider class if found or null
*/
private static Object findJarServiceProvider(String factoryId)
throws ConfigurationError
{
String serviceId = "META-INF/services/" + factoryId;
InputStream is = null;
// First try the Context ClassLoader
ClassLoader cl = ss.getContextClassLoader();
if (cl != null) {
is = ss.getResourceAsStream(cl, serviceId);
// If no provider found then try the current ClassLoader
if (is == null) {
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}
} else {
// No Context ClassLoader, try the current
// ClassLoader
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}
if (is == null) {
// No provider found
return null;
}
...
因此,在我的主程序中,我运行以下内容。 它总是返回false,这意味着它没有找到'dummydevice' 在我的eclipse项目中,我在'src'处创建了一个名为META-INF的文件夹,在它下面创建了一个名为'services'的子文件夹。 我做对了吗?我看到的每一个关于SPI的例子都是关于加载JAR的。我不是在加载一个JAR,我是想在同一个项目中运行一个类。这个方法只适用于装入罐子吗?我希
我的CharsetProvider的类是在文件中指定的,该文件位于中,所有GET都正常加载并按预期工作。 然而,现在我也在android上使用lib,但是charset没有加载到android-app中。 我如何整合我的字符集,使它可以像预期的那样在一个Android应用程序中使用? 目前我正在做这样的变通: 这是可行的,但在我看来是无效的,因为每次我尝试用自己的charset进行这样的解码时,都
有没有一种方法可以用Maven在Meta-INF/services中创建自定义服务文件?这就是您使用Ant的方法:https://ant.apache.org/manual/tasks/jar.html 我知道在我的源代码中创建一个resources/meta-inf/并放置我想要的任何服务文件是可能的。然后,Maven会自动将这些文件拉到我的JAR中。这不能解决我的问题。 在我的源代码中有多个版
我正在Eclipse中处理一个Java项目,该项目是使用Maven构建的。我使用的是一个旧项目中的一些循环代码,其中一个类在JAR的文件夹中查找一个具有特定名称的文件,然后解析该文件的文本。在这个特定的示例中,它查找一个具有Java接口名称的文件,然后从文件内部获取实现的类名。
问题内容: 我正在使用Eclipse构建Java项目,该项目是使用Maven构建的。我使用的是旧项目中的一些再生代码,这些类之一在JAR文件夹中查找具有特定名称的文件,然后解析该文件的文本。在此特定示例中,它将查找具有Java接口名称的文件,然后从文件内部获取实现的类名称。 因此,基本上我想做的是 在JAR的“ META-INF / services”文件夹中包含一个文件名(X)和一行文本(Y)的
我正在Eclipse中处理一个Java项目,该项目是使用Maven构建的。我使用的是一个旧项目中回收的代码,其中一个类在JAR的文件夹中查找具有特定名称的文件,然后解析该文件的文本。在这个特定的例子中,它查找一个名为Java接口的文件,然后从文件中获取实现的类名。 所以基本上,我要做的是在JAR的“META-INF/services”文件夹中包含一个文件,文件名为(X),一行文本为(Y)。我猜这应