CXF使用拦截器和XSLT转换消息内容

还是接着上次的WebService接口设计的问题,为了提高易用性,需要在接收到消息的时候按照指定的xslt把接收到的soap消息转换为期望的格式。这样对客户端来说更加友好,但是服务器端的工作无疑是加大了呵呵。本着公司服务为先的理念,再难再险也要上啊。

 

参考了cxf自带的例子(configuration_interceptor),然后加上了自己需要的xslt转换功能,就这样大功告成了。整个过程基本上还是比较顺利的。

 

客户端发过来的soap消息为:

Xml代码 复制代码
  1. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  
  2.     <soap:Body>  
  3.         <ns2:process1 xmlns:ns2="http://ws.test/">  
  4.             <ns2:process>  
  5.                 <version>0</version>  
  6.                 <name>test</name>  
  7.                 <category>website.test</category>  
  8.                 <arg0><userName>username</userName><extension>extension</extension></arg0>  
  9.             </ns2:process>  
  10.         </ns2:process1>  
  11.     </soap:Body>  
  12. </soap:Envelope>  

 

转换使用的xslt内容如下:test.xsl

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  
  3.     <xsl:template match="/">  
  4.         <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">  
  5.                 <xsl:copy-of select="/soapenv:Envelope/soap:Header"/>  
  6.             <soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  
  7.                 <ns2:process1 xmlns:ns2="http://ws.test/">  
  8.                     <ns2:process>  
  9.                                     <!--把version字段在原来值的基础上,在前面加个1-->  
  10.                         <version >1<xsl:value-of select="/soapenv:Envelope/soap:Body/ns2:process1/ns2:process/version"/></version>  
  11.                         <xsl:copy-of select="/soapenv:Envelope/soap:Body/ns2:process1/ns2:process/name"/>  
  12.                         <xsl:copy-of select="/soapenv:Envelope/soap:Body/ns2:process1/ns2:process/category"/>  
  13.                         <xsl:copy-of select="/soapenv:Envelope/soap:Body/ns2:process1/ns2:process/arg0"/>  
  14.                     </ns2:process>  
  15.                 </ns2:process1>  
  16.             </soap:Body>  
  17.         </soapenv:Envelope>  
  18.   
  19.     </xsl:template>  
  20. </xsl:stylesheet>  

 可以看到,这里只是简单的将原有的version值前面加了个1然后就完事了。顺带着提一下,本人对xslt的了解不多,只是随便写了一个马马虎虎能用的,如果有高人看见了这个东东感到胃部不适的话请告诉我该怎么样写更好呵呵。谢了先

 

负责XSLT转换的类XSLTTransfomer.java:

Java代码 复制代码
  1. import java.io.File;   
  2.   
  3. import javax.xml.transform.Transformer;   
  4. import javax.xml.transform.TransformerException;   
  5. import javax.xml.transform.TransformerFactory;   
  6. import javax.xml.transform.stream.StreamSource;   
  7.   
  8. import org.dom4j.Document;   
  9. import org.dom4j.io.DocumentResult;   
  10. import org.dom4j.io.DocumentSource;   
  11.   
  12. public class XSLTTransfomer {   
  13.   
  14.     public static Document transformDocument(Document document, File styleSheet)   
  15.             throws TransformerException {   
  16.         TransformerFactory factory = TransformerFactory.newInstance();   
  17.         Transformer transformer = factory.newTransformer(new StreamSource(   
  18.                 styleSheet));   
  19.   
  20.         DocumentSource source = new DocumentSource(document);   
  21.         DocumentResult result = new DocumentResult();   
  22.         transformer.transform(source, result);   
  23.   
  24.         Document transformedDoc = result.getDocument();   
  25.   
  26.         return transformedDoc;   
  27.     }   
  28. }  
import java.io.File;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

import org.dom4j.Document;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;

public class XSLTTransfomer {

	public static Document transformDocument(Document document, File styleSheet)
			throws TransformerException {
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer transformer = factory.newTransformer(new StreamSource(
				styleSheet));

		DocumentSource source = new DocumentSource(document);
		DocumentResult result = new DocumentResult();
		transformer.transform(source, result);

		Document transformedDoc = result.getDocument();

		return transformedDoc;
	}
}

 

CXF拦截器的类:XLSTInterceptor.java

Java代码 复制代码
  1. import java.io.ByteArrayInputStream;   
  2. import java.io.File;   
  3. import java.io.InputStream;   
  4.   
  5. import org.apache.commons.logging.Log;   
  6. import org.apache.commons.logging.LogFactory;   
  7. import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;   
  8. import org.apache.cxf.interceptor.Fault;   
  9. import org.apache.cxf.message.Message;   
  10. import org.apache.cxf.phase.AbstractPhaseInterceptor;   
  11. import org.apache.cxf.phase.Phase;   
  12. import org.dom4j.Document;   
  13. import org.dom4j.io.SAXReader;   
  14.   
  15. import test.xml.XSLTTransfomer;   
  16.   
  17. public class XLSTInterceptor extends AbstractPhaseInterceptor<Message> {   
  18.     Log logger = LogFactory.getLog(XLSTInterceptor.class);   
  19.   
  20.     public XLSTInterceptor() {   
  21.                //这里的设置相当要紧,阶段不同,拿到的内容会完全的不同。切记切记!!!   
  22.         super(Phase.PRE_STREAM);   
  23.         addBefore(SoapPreProtocolOutInterceptor.class.getName());   
  24.     }   
  25.   
  26.     public void handleMessage(Message message) throws Fault {   
  27.   
  28.         try {   
  29.             InputStream in = message.getContent(InputStream.class);   
  30.             SAXReader reader = new SAXReader();   
  31.             Document document = reader.read(in);   
  32.                        //这里只是简单的从硬盘上把文件读进来了,具体实现的时候要按自己的需要来实现   
  33.             Document result = XSLTTransfomer.transformDocument(document, new File("E://soa//test.xsl"));   
  34.             message.setContent(InputStream.class,new ByteArrayInputStream(result.asXML().getBytes()));   
  35.   
  36.         } catch (Exception e) {   
  37.             e.printStackTrace();   
  38.         }   
  39.     }   
  40.   
  41. }  
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;

import test.xml.XSLTTransfomer;

public class XLSTInterceptor extends AbstractPhaseInterceptor<Message> {
	Log logger = LogFactory.getLog(XLSTInterceptor.class);

	public XLSTInterceptor() {
               //这里的设置相当要紧,阶段不同,拿到的内容会完全的不同。切记切记!!!
		super(Phase.PRE_STREAM);
		addBefore(SoapPreProtocolOutInterceptor.class.getName());
	}

	public void handleMessage(Message message) throws Fault {

		try {
			InputStream in = message.getContent(InputStream.class);
			SAXReader reader = new SAXReader();
			Document document = reader.read(in);
                       //这里只是简单的从硬盘上把文件读进来了,具体实现的时候要按自己的需要来实现
			Document result = XSLTTransfomer.transformDocument(document, new File("E://soa//test.xsl"));
			message.setContent(InputStream.class,new ByteArrayInputStream(result.asXML().getBytes()));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
Java代码 复制代码
  1. super(Phase.PRE_STREAM);这一句相当要紧,一定要设置对了。不然肯定达不到你想要的效果。  
super(Phase.PRE_STREAM);这一句相当要紧,一定要设置对了。不然肯定达不到你想要的效果。
Phase Functions
RECEIVE Transport level processing
(PRE/USER/POST)_STREAM Stream level processing/transformations
READ This is where header reading typically occurs.
(PRE/USER/POST)_PROTOCOL Protocol processing, such as JAX-WS SOAP handlers
UNMARSHAL Unmarshalling of the request
(PRE/USER/POST)_LOGICAL Processing of the umarshalled request
PRE_INVOKE Pre invocation actions
INVOKE Invocation of the service
POST_INVOKE Invocation of the outgoing chain if there is one

 

上面是cxf官方文档里面对各个阶段的解释。大家可以参考一下。

 

怎么样设置cxf的拦截器就不提了,免得大家以为我在侮辱大家的智商呵呵。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值