沒想到要弄這么一個東西。
起初只是想用interceptor記錄一下webservice調用日志,后來卻被要求在頁面展示。
展示容易,但只是展示webservice的地址無法讓用戶從中明白什么。
那么我可以把url和具體說明作為一對鍵值,但是這對鍵值配置到哪里比較好?
文件? db? 我不想每增加一個方法就到別的地方再配置一次鍵值,寫到注解也許是個不錯的方法。
這就需要我在方法被調用后在獲得對應的Method對象。
當然,實現這個效果的方法有很多種,這里主要講如何在CXF Interceptor中獲取。
順便一提,我是在web應用里配置SPRing+CXF,攔截器只是簡單繼承了JAXRSIn/OutInterceptor。
比如,我有一個這樣的方法:
@GET@Path("/hello")@Consumes({"*/*"})public String Hello(){ return "Hello Alvez!";}我需要在調用結束后記錄這個方法的名字 ,但不能是"Hello",而是"哈羅"。
那就定義一個注解并給方法加上:
@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface Description { public String value(); }@GET@Path("/hello")@Consumes({"*/*"})@Description("哈羅")public String Hello(){ return "Hello Alvez!";}好了,接下來就是從攔截器獲得調用信息了。
InInterceptor還是OutInterceptor?
無論是哪一個,當我們重寫了handleMessage時就自然地想到從Message對象中獲取。
當然,如果你發現正在使用的方法參數列表中沒有Message類型,也許你可以這樣做。
Message message = JAXRSUtils.getCurrentMessage();因為這個例子中使用到的JAXIn/OutInterceptor繼承的是AbstractPhaseInterceptor<Message>,我們就可以理所當然地得到message對象。
public class JAXRSInInterceptor extends AbstractPhaseInterceptor { //.. }但一個Message里面卻有不少內容,Exchange、Destination、Attachment、InterceptorChain,繼續遞歸下去,如果不明白他們分別代表什么就無從找起。
也許我想用一個org.apache.cxf.service.invoker.MethodDispatcher(2.6.x中是org.apache.cxf.frontend.MethodDispatcher)
而理由僅僅是因為他有一個通過BindingOperationInfo對象獲取java.lang.reflect.Method對象的方法:
public class JAXRSInInterceptor extends AbstractPhaseInterceptor { //.. }這樣我就可以在攔截器中這樣使用:
Exchange exchange = message.getExchange();BindingOperationInfo bindingOperationInfo = exchange.getBindingOperationInfo();SimpleMethodDispatcher methodDispatcher = new SimpleMethodDispatcher();Method method = methodDispatcher.getMethod(bindingOperationInfo);但很遺憾,exchange里哪來的bindingOperationInfo?
那exchange里有什么? 既然他是Map的子類,我可以看看他的keyset,發現outInterceptor中的message.getExchange().keySet()如下:
org.apache.cxf.rest.messageorg.apache.cxf.resource.operation.nameorg.apache.cxf.interceptor.LoggingMessage.IDorg.apache.cxf.endpoint.ConduitSelectororg.apache.cxf.jaxrs.model.OperationResourceInfoorg.apache.cxf.service.object.lastorg.apache.cxf.endpoint.Endpointorg.apache.cxf.service.Serviceroot.resource.classservice.root.providerservice.root.instanceorg.apache.cxf.Busorg.apache.cxf.binding.BindingAcceptContent-Type
看到可以獲取OperationResourceInfo,Request/ResponseHandler接口的默認方法中也包括這個參數,只是這兩個接口已經在新版本中不能用了。(http://cxf.apache.org/docs/30-migration-guide.html)
但也提供了替代的方法(http://cxf.apache.org/docs/jax-rs.html)
e.g.我們可以從message中獲得一切想要的信息,比如被調用過的方法;
OperationResourceInfo resourceInfo = (OperationResourceInfo) ex.get("org.apache.cxf.jaxrs.model.OperationResourceInfo");ClassResourceInfo classResourceInfo = resourceInfo.getClassResourceInfo();Path path = classResourceInfo.getPath();Class<?> resourceClass = classResourceInfo.getResourceClass();Method annotatedMethod = resourceInfo.getAnnotatedMethod();Annotation[] declaredAnnotations = annotatedMethod.getDeclaredAnnotations();Description annotation = annotatedMethod.getAnnotation(Description.class);上面的Description就是文章開始時定義的注解,這樣小問題就解決了。
新聞熱點
疑難解答