您好,登錄后才能下訂單哦!
小編給大家分享一下如何使用webservice自定義注解處理參數加解密問題,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
前一段項目中用到了webservice,正好自己之前也了解過一點apache的cxf框架,所以就采用了cxf來實現webservice服務端,本身實現并沒技術難點,但是項目為了保證安全性,采用了傳輸加密的過程,所以大部分請求參數需要加密,返回參數也需要加密,大致流程是:
請求參數對稱加密+對稱秘鑰非對稱加密
返回參數堆成加密+對稱秘鑰非對稱加密
參數加密本身并不復雜,但是有些服務并不需要加密,有些則需要,加密工具類并不通用
string,datahandler等不能重用,雖然本質都是對字節數據加密,但是要寫許多方法,還要方法參數,檢查需要加解密處理的參數,然后尋找對應的類型處理方法調用.
邏輯很清晰,但是過程實現很惡心,最終這樣實現了一版,但是并不合我的意.
如果能在攔截器中獲取到參數列表,然后尋找對應的解碼器解碼,這樣就比較簡單了.但是難點是,如果標記參數,并指定被標記參數的解碼器尼?
我想到了注解,注解就可以標記,參數,然后通過反射獲取到注解,解析出內容.
本來想標記到參數上,但是一個個標記太麻煩,而且獲取也不太方便,索性就放在方法上,用數組來接收.
問題解決.
自定義注解:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author webservice請求參數自定義注解 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RequestHanleAnnotation { Class[] handler() default {}; int[] index() default {}; }
參數解碼器接口
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @author taoyuan *參數處理器 * @param <T> */ public abstract class ParamHandler<T> { //解碼器實例緩存 public static final Map<Class,ParamHandler> hanlers=new ConcurrentHashMap<>(); //處理方法 abstract T handle(T t); }
解碼器實現,這里并沒有真正解碼,只是在參數后面加了123
public class StringHandler extends ParamHandler<String> { @Override public String handle(String t) { return t+"123"; } }
服務方法注解使用
//表示第一個參數需要StringHandler處理 @RequestHanleAnnotation(index=0,handler=StringHandler.class) public String test(String test, String test2) throws Exception { System.out.println(test); System.out.println(test2); return "cesshi"; }
攔截器實現
import java.io.File; import java.lang.reflect.Method; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.MessageContentsList; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; /** * @author 都市桃源 */ public class EcrInInterceptor extends AbstractPhaseInterceptor<SoapMessage>{ private Logger log = Logger.getLogger(ContractLogicImpl.class); public EcrInInterceptor(){ // 在調用方法之前調用攔截器 super(Phase.PRE_INVOKE); } @Override public void handleMessage(SoapMessage msg) throws Fault { /*獲取請求ip,攔截器中可以做下統一日志處理 HttpServletRequest httprequest = (HttpServletRequest)msg.get(AbstractHTTPDestination.HTTP_REQUEST); * */ //獲取正在執行的方法 Method method = MsgUtil.getSoapMethod(msg); //解析注解,并處理參數 MessageContentsList contentsList = MessageContentsList.getContentsList(msg); MsgUtil.handle(method,contentsList); } @Override public void handleFault(SoapMessage message) { super.handleFault(message); }
注解解析工具類實現
import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.MessageContentsList; import org.apache.cxf.service.Service; import org.apache.cxf.service.invoker.MethodDispatcher; import org.apache.cxf.service.model.BindingOperationInfo; /** * @author ll * 獲取方法名稱 * */ public class MsgUtil { /**根據消息獲取調用方法 * @param msg * @return */ public static Method getSoapMethod(SoapMessage msg){ Exchange exchange = msg.getExchange(); BindingOperationInfo bop = exchange.get(BindingOperationInfo.class); MethodDispatcher md = (MethodDispatcher) exchange.get(Service.class) .get(MethodDispatcher.class.getName()); Method method = md.getMethod(bop); return method; } public static void handle(Method method, MessageContentsList contentsList) { if(method==null)return; RequestHanleAnnotation reqAnno= method.getAnnotation(RequestHanleAnnotation.class); int[] indexs = reqAnno.index(); if(indexs==null||indexs.length==0)return; Class[] handlers = reqAnno.handler(); try { //處理器實例 ParamHandler handler=null; for(int i=0,len=indexs.length;i<len;i++){ //獲取需要處理的參數 Object obj = contentsList.get(indexs[i]); //從緩存中獲取處理器實例 handler=ParamHandler.hanlers.get(handlers[i]); if(handler==null){ //創建處理器實例 handler=(ParamHandler) handlers[i].newInstance(); //緩存處理器實例 ParamHandler.hanlers.put(handlers[i], handler); } contentsList.set(indexs[i], handler.handle(obj)); } }catch (Exception e) { e.printStackTrace(); } } }
返回參數同樣也可以注解實現,這里就不在贅述了,實現也比較簡單.
**需要注意的是,攔截器攔截順序不一樣 攔截器統一繼承 AbstractPhaseInterceptor類, 請求攔截 :super(Phase.PRE_INVOKE); 返回攔截: super(Phase.PRE_STREAM);**
serviceName
:對外發布的服務名,指定 Web Service 的服務名稱:wsdl:service。缺省值為 Java 類的簡單名稱 + Service。(字符串)
endpointInterface
:服務接口全路徑, 指定做SEI(Service EndPoint Interface)服務端點接口
name
:此屬性的值包含XML Web Service的名稱。在默認情況下,該值是實現XML Web Service的類的名稱,wsdl:portType 的名稱。缺省值為 Java 類或接口的非限定名稱。(字符串
portName
:wsdl:portName。缺省值為 WebService.name+Port。
targetNamespace
:指定你想要的名稱空間,默認是使用接口實現類的包名的反序
wsdlLocation
:指定用于定義 Web Service 的 WSDL 文檔的 Web 地址。Web 地址可以是相對路徑或絕對路徑。(字符串)注意:實現類上可以不添加Webservice注解
注釋表示作為一項 Web Service 操作的方法,將此注釋應用于客戶機或服務器服務端點接口(SEI)上的方法,或者應用于 JavaBeans 端點的服務器端點實現類。
要點:
僅支持在使用 @WebService 注釋來注釋的類上使用 @WebMethod 注釋
operationName
:指定與此方法相匹配的wsdl:operation 的名稱。缺省值為 Java 方法的名稱。(字符串)
action
:定義此操作的行為。對于 SOAP 綁定,此值將確定 SOAPAction 頭的值。缺省值為 Java 方法的名稱。(字符串)
exclude
:指定是否從 Web Service 中排除某一方法。缺省值為 false。(布爾值)
注釋將一個方法表示為只有輸入消息而沒有輸出消息的 Web Service 單向操作。
將此注釋應用于客戶機或服務器服務端點接口(SEI)上的方法,或者應用于 JavaBeans 端點的服務器端點實現類
注釋用于定制從單個參數至 Web Service 消息部件和 XML 元素的映射。
將此注釋應用于客戶機或服務器服務端點接口(SEI)上的方法,或者應用于 JavaBeans 端點的服務器端點實現類。
name
:參數的名稱。如果操作是遠程過程調用(RPC)類型并且未指定partName 屬性,那么這是用于表示參數的 wsdl:part 屬性的名稱。如果操作是文檔類型或者參數映射至某個頭,那么 -name 是用于表示該參數的 XML 元素的局部名稱。如果操作是文檔類型、參數類型為 BARE 并且方式為 OUT 或 INOUT,那么必須指定此屬性。(字符串)
partName
:定義用于表示此參數的 wsdl:part屬性的名稱。僅當操作類型為 RPC 或者操作是文檔類型并且參數類型為BARE 時才使用此參數。(字符串)
targetNamespace
:指定參數的 XML 元素的 XML 名稱空間。當屬性映射至 XML 元素時,僅應用于文檔綁定。缺省值為 Web Service的targetNamespace。(字符串)
mode
:此值表示此方法的參數流的方向。有效值為 IN、INOUT 和 OUT。(字符串)
header
:指定參數是在消息頭還是消息體中。缺省值為 false。(布爾值)
注釋用于定制從返回值至 WSDL 部件或 XML 元素的映射。將此注釋應用于客戶機或服務器服務端點接口(SEI)上的方法,或者應用于 JavaBeans 端點的服務器端點實現類。
name
:當返回值列示在 WSDL 文件中并且在連接上的消息中找到該返回值時,指定該返回值的名稱。對于 RPC 綁定,這是用于表示返回值的 wsdl:part屬性的名稱。對于文檔綁定,-name參數是用于表示返回值的 XML 元素的局部名。對于 RPC 和 DOCUMENT/WRAPPED 綁定,缺省值為 return。對于 DOCUMENT/BARE 綁定,缺省值為方法名 + Response。(字符串)
targetNamespace
:指定返回值的 XML 名稱空間。僅當操作類型為 RPC 或者操作是文檔類型并且參數類型為 BARE 時才使用此參數。(字符串)
header
:指定頭中是否附帶結果。缺省值為false。(布爾值)
partName
:指定 RPC 或 DOCUMENT/BARE 操作的結果的部件名稱。缺省值為@WebResult.name。(字符串)
注釋用于使 Web Service 與外部定義的處理程序鏈相關聯。只能通過對 SEI 或實現類使用 @HandlerChain 注釋來配置服務器端的處理程序。但是可以使用多種方法來配置客戶端的處理程序。可以通過對生成的服務類或者 SEI 使用 @HandlerChain 注釋來配置客戶端的處理程序。此外,可以按程序在服務上注冊您自己的 HandlerResolver 接口實現,或者按程序在綁定對象上設置處理程序鏈。
file
:指定處理程序鏈文件所在的位置。文件位置可以是采用外部格式的絕對 java.net.URL,也可以是類文件中的相對路徑。(字符串)
name
:指定配置文件中處理程序鏈的名稱。
以上是“如何使用webservice自定義注解處理參數加解密問題”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。