cxf拦截器。
cxf把整个通信过程分为很多个时期,不同时期做的处理不同。所以在使用拦截器的时候,没有选对时期,就拦截不到对象。
在做拦截器的时候,首先你要了解到cxf拦截器自身做了什么事情,然后你可以在该拦截器之前或之后做某事。
拦截分为2个段,请求和相应
•AttachmentInInterceptor Parse the mime headers for mime boundaries, finds the "root" part and resets the input stream to it, and stores the other parts in a collection of Attachments
•StaxInInterceptor Creates an XMLStreamReader from the transport InputStream on the Message
•ReadHeadersInterceptor Parses the SOAP headers and stores them on the Message
•SoapActionInInterceptor Parses "soapaction" header and looks up the operation if a unique operation can be found for that action.
•MustUnderstandInterceptor Checks the MustUnderstand headers, its applicability and process it, if required
•SOAPHandlerInterceptor SOAP Handler as per JAX-WS
•LogicalHandlerInInterceptor Logical Handler as per JAX-WS
•CheckFaultInterceptor Checks for fault, if present aborts interceptor chain and invokes fault handler chain
•URIMappingInterceptor Can handle HTTP GET, extracts operation info and sets the same in the Message
•DocLiteralnInterceptor Examines the first element in the SOAP body to determine the appropriate Operation (if soapAction did not find one) and calls the Databinding to read in the data.
•SoapHeaderInterceptor Perform databinding of the SOAP headers for headers that are mapped to parameters
•WrapperClassInInterceptor For wrapped doc/lit, the DocLiteralInInterceptor probably read in a single JAXB bean. This interceptor pulls the individual parts out of that bean to construct the Object[] needed to invoke the service.
•SwAInInterceptor For Soap w/ Attachments, finds the appropriate attachments and assigns them to the correct spot in the parameter list.
•HolderInInterceptor For OUT and IN/OUT parameters, JAX-WS needs to create Holder objects. This interceptor creates the Holders and puts them in the parameter list.
•ServiceInvokerInInterceptor Actually invokes the service.
上面是cxf自带的拦截请求阶段的拦截器。
假如我要获取SOAP的body内容,我就要知道,body内容在哪里。
显然易见body的内容在stream里面,但是我们不能读stream,因为后面的拦截器会解析stream,如StaxInInterceptor拦截器把stream变成了Reader。若你自己解析了,则inputStream关闭,StaxInInterceptor解析时就报错。
body内容一定会转换成输入参数的,因为你服务方法使用的就是转换好了的参数。所以继续找拦截器,什么时候转换成了你想要的参数。这时,你可以找到DocLiteralInInterceptor拦截器,你可以看它的源码。它把body里面的内容都放到了MessageContentsList。所以你在这个拦截器后面去拦截,然后获取body内容。
但是还是有个问题,因为你根据message.getContent(MessageContentsList.class)是拿不到的,你debug的时候可以看到message里面content存放的是代理对象,而且还是方法代理对象。
因为方法调用时候,已经转换成我们要的参数。而pre-invoke是在调用方法前做处理,所以你可以在这里做拦截器,拦截body内容。因为参数存在content里面是代理对象,所以你只能遍历content去获取内容。
public UserInterceptor() {
super(Phase.PRE_INVOKE);
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
HttpServletRequest request = (HttpServletRequest) message
.get(AbstractHTTPDestination.HTTP_REQUEST);
String ipAddress = request.getRemoteAddr(); // 取客户端IP地址
String username = null;
String password = null;
Set s = message.getContentFormats();
Iterator classIterator = s.iterator();
while (classIterator.hasNext()) {
Class c = (Class) classIterator.next();
Object o = message.getContent(c);
if (o instanceof MessageContentsList) {
MessageContentsList values = (MessageContentsList) o;
System.out.println(values);
for (int i = 0; i < values.size(); i++) {
try {
Object paramters = values.get(i);
String value = paramters.toString();
String[] strs = value.split(";");
username = strs[0];
password = strs[1];
System.out.println(paramters);
break;
} catch (Exception e) {
}
}
break;
}
}
我这里密码和账户是放在对象里面,然后对象作为服务的参数,也就是放在body里面。因为我的webservice服务不止一个方法,并且各个方法的参数不一样(参数是一个对象,但对象不同)。所以values.get(i)就不能直接转换成你的对象,若只一个方法,就可以直接转换成对象。反正值都是存在MessageContentsList里面,具体怎么就看你自己的实现了。
invoke时期做拦截器,此时你的方法已经调用完毕。也就是先执行方法,然后执行拦截器。若你想获得返回值,则需要用到
Exchange ex = message.getExchange();
Message outMessage = ex.getOutMessage();
exchange类的价值就体现出来了,若想在response阶段的拦截器获取请求参数,应该也是这样去获得吧。
一般super(Phase.PRE_INVOKE);是把你的拦截器放在该时期的最前面,你可以再后面加addAfter,或addBefore。就可以选择你的拦截器在该时段,哪个拦截后,或前。如果你配置了日志,可以看到控制台输出了cxf拦截器出现流程。