我正在使用Javax Transformer类使用xslts转换xml。负载较小时,一切正常。但是,当负载来临时,事情开始破裂。基本上,transformer表现出奇怪的行为,并将其设置为null从而引发异常。
代码
@Service
public class XmlProcessorUtil {
private static final ObjectPool<XPath> pool = new GenericObjectPool<XPath>(new
XPathPoolFactory());
public String transformXmlUsingXsltWithParams(String xsltPath, Document xml,
HashMap<String, String> params) {
Source xslt = new StreamSource(new File(xsltPath));
Source xmlSource = new DOMSource(xml);
return transformXmlUsingXsltWithParams(xslt, xmlSource, params);
}
public String transformXmlUsingXsltWithParams(Source xslt, Source xml, HashMap<String, String> params)
{
String result = "";
StringWriter writer = new StringWriter();
if(xslt == null)
return null;
Transformer transformer = null;
try
{
transformer = TransformerFactory.newInstance().newTransformer(xslt);
}
catch (Exception e)
{
return null;
}
if(params != null && !params.isEmpty())
{
for(String key : params.keySet())
{
if(transformer != null)
transformer.setParameter(key, params.get(key));
}
}
try
{
if(transformer==null) {
LOGGER.info("Transformer is null!!");
}
if(xml==null) {
LOGGER.info("XML is null!!");
}
transformer.transform(xml, new StreamResult(writer));
}
catch (TransformerException e)
{
e.printStackTrace();
return null;
}
result = writer.toString();
return result;
}
}
[在日志中搜索时,有很多实例“ Transformer为空!” 。此外,错误是间歇性的。该类是一个bean,用于转换的方法(transformXmlUsingXsltWithParams)是一个明显的实例方法。毫无例外设置此
transformer = TransformerFactory.newInstance().newTransformer(xslt);
但是转换器仍然为空。
PS:此方法被多个线程高度调用,因此我将转换器用作函数中的局部变量
有人可以提供解决方法。
编辑:
@Bean
TransformerFactory transformerFactory() {
return TransformerFactory.newInstance();
}
@Service
public class XmlProcessorUtil {
private static final ObjectPool<XPath> pool = new GenericObjectPool<XPath>(new XPathPoolFactory());
public static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(XmlProcessorUtil.class);
@Autowired
TransformerFactory transformerFactory ;
public String transformXmlUsingXsltWithParams(String xsltPath, Document xml, HashMap<String, String> params) {
Source xslt = new StreamSource(new File(xsltPath));
Source xmlSource = new DOMSource(xml);
return transformXmlUsingXsltWithParams(xslt, xmlSource, params);
}
public String transformXmlUsingXsltWithParams(Source xslt, Source xml, HashMap<String, String> params)
{
String result = "";
StringWriter writer = new StringWriter();
if(xslt == null)
return null;
Transformer transformer = null;
try
{
transformer = transformerFactory.newTemplates(xslt).newTransformer();
}
catch (Exception e)
{
LOGGER.warn("Error in setting transformer",e);
return null;
}
if(params != null && !params.isEmpty())
{
for(String key : params.keySet())
{
if(transformer != null)
transformer.setParameter(key, params.get(key));
}
}
try
{
if(transformer==null) {
LOGGER.info("Transformer is null!!");
}
if(xml==null) {
LOGGER.info("XML is null!!");
}
transformer.transform(xml, new StreamResult(writer));
}
catch (TransformerException e)
{
e.printStackTrace();
return null;
}
result = writer.toString();
return result;
}
}
尚不完全清楚这里发生了什么,但是您在多线程环境中使用JAXP看起来是错误的。
您应该尝试为整个应用程序创建一个TransformerFactory
实例。您应该为每个样式表创建一个Templates
对象,如果同一样式表将用于多个转换,则将其缓存。并且您应该为每个转换创建一个Transformer
(使用Templates.newTransformer()
),请注意Transformer
只能在单个线程中使用。