JAXB.marshal阻止webservice调用

时间:2017-09-01 17:58:47

标签: java spring spring-boot jaxb webservicetemplate

我正在使用Spring WebserviceTemplate对服务进行SOAP调用。我运行了性能测试,看看它在负载下的表现如何。我还有一个拦截器,用于将我的传入请求中的头参数复制到我正在调用的服务中。

@Component
public class HeaderPropagationInterceptor implements ClientInterceptor {

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        SoapMessage request = (SoapMessage) messageContext.getRequest();
        Result result = request.getSoapHeader().getResult();
        JAXB.marshal(getRequestHeader(), result);
        return true;
    }

当我运行性能测试时,我看到以下语句阻塞4-5秒

JAXB.marshal(getRequestHeader(), result);

这可能是阻塞的原因吗?

1 个答案:

答案 0 :(得分:3)

JAXB实用程序类将在第一次调用时创建JAXBContext(昂贵的操作)。它将被弱缓存,这意味着如果内存不足,则可以回收上下文,并在以下调用中重新创建。你真的应该创建你的上下文并明确地保持它。这样的事情(正如其他人的评论中已经建议的那样)可以解决你的问题:

@Component
public class HeaderPropagationInterceptor implements ClientInterceptor
{
    private JAXBContext jaxbContext;

    @PostConstruct
    public void createJaxbContext() {
        try {
            jaxbContext = JAXBContext.newInstance(RequestHeader.class);
        }
        catch(JAXBException e) {
            throw new IllegalStateException("Unable to create JAXBContext.", e);
        }
    }

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        SoapMessage request = (SoapMessage) messageContext.getRequest();
        Result result = request.getSoapHeader().getResult();
        jaxbContext.createMarshaller().marshal(getRequestHeader(), result);
        return true;
    }
}

您必须将RequestHeader.class替换为代码使用的实际类。如果需要进一步提高性能,也可以使用线程本地来重用marshaller,但是你应该做进一步的分析来验证这确实是一个瓶颈。祝你的项目好运!