通过HTTP POST请求调用JAX-WS Webservice的操作,我们通常以下面的示例的格式获取响应:
<?xml version="1.0" encoding="UTF-8" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:helloResponse xmlns:ns2="http://test/">
<return>Hello Foo!</return>
</ns2:helloResponse>
</S:Body>
</S:Envelope>
我想删除和/或修改服务器端的SOAP消息响应的XML声明版本,即我想从我的WS的响应中删除/修改此部分:
<?xml version="1.0" encoding="UTF-8" ?>
我尝试使用JAX-WS SOAPMessage处理程序删除它(请参阅下面的代码),但它不起作用。
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(isRequest) {
try {
final SOAPMessage message = context.getMessage();
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
message.saveChanges();
context.setMessage(message);
} catch (SOAPException e) {
return false;
}
}
return true;
}
我做错了什么?这甚至可能吗?如果是,您是否有任何关于如何删除XML声明或修改它的版本(到XML 1.1)的建议,例如??
非常感谢任何帮助!
答案 0 :(得分:1)
要在JAX-WS服务的响应中删除XML声明(应该不需要,但我们都遇到了那个发誓它破坏了系统的集成方,对吗?) ,很难找到一个通用的解决方案。在我调试的实现中,大多数假设您想要声明,并无条件地添加它。
我能提出的最安全的方法是在JAX-WS范围之外采取这种困境。相反,可以使用servlet过滤器来修改由JAX-WS实现生成的servlet响应。
这段代码(与Servlet 3.0兼容)创建了一个简单的过滤器,它使用ServletResponseWrapper来修改响应,就在它被发送回客户端之前。为了更好地衡量,它只对“text / xml”内容进行操作。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
/**
* A servlet filter that allows one to strip the XML declaration from xml-based
* responses.
*
* @author Guus der Kinderen.
*/
@WebFilter( "/*" )
public class XmlDeclarationFilter implements Filter
{
public void doFilter( ServletRequest request,
ServletResponse response,
FilterChain chain )
throws ServletException, IOException
{
try ( final Writer out = response.getWriter() )
{
// Will hold original response.
final Wrapper wrapper = new Wrapper((HttpServletResponse) response );
// Proceed with the request (will populate wrapper).
chain.doFilter( request, wrapper );
// Process the populated wrapper.
if ( wrapper.getContentType().contains( "text/xml" ) )
{
// Modify the original content (strip the XML declaration).
final String regex = "(?s)^\\s*\\<\\?xml.*?>";
final String original = wrapper.toString();
final String modified = original.replaceFirst( regex, "" );
// Adjust the content length value to account for any changes.
response.setContentLength( modified.length() );
// Send out the modified content as a response.
out.write( modified );
}
else
{
// Send out the original content, unmodified.
out.write( wrapper.toString() );
}
}
}
/**
* A response wrapper that buffers all output, and makes it available as
* a String.
*
* @author Guus der Kinderen.
*/
public class Wrapper extends HttpServletResponseWrapper
{
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
public Wrapper( HttpServletResponse response )
{
super( response );
}
public String toString()
{
try
{
return baos.toString( "utf-8" );
}
catch ( UnsupportedEncodingException e )
{
return baos.toString();
}
}
@Override
public PrintWriter getWriter()
{
return new PrintWriter( baos );
}
@Override
public ServletOutputStream getOutputStream() throws IOException
{
return new ServletOutputStream()
{
@Override
public void write( int b ) throws IOException
{
baos.write( b );
}
};
}
}
public void init( FilterConfig config ) throws ServletException
{
}
public void destroy()
{
}
}
答案 1 :(得分:0)
你真的需要删除xml声明吗?
如果我发送没有xml声明的soap消息,我有一种情况可行。 如果我发送带有xml声明的soap消息,则会返回此错误:
org.xml.sax.SAXParseException: The XML declaration must end with "?>"
我也尝试设置WRITE_XML_DECLARATION但没有成功。
我的解决方案是设置这两个NamespaceDeclaration:
SOAPEnvelope env = sp.getEnvelope();
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
有关完整的解决方案说明,请参阅Removing XML declaration in JAX-WS message