溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用webservice自定義注解處理參數(shù)加解密問題

發(fā)布時間:2021-12-18 17:03:37 來源:億速云 閱讀:169 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下如何使用webservice自定義注解處理參數(shù)加解密問題,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

webservice自定義注解處理參數(shù)加解密

前一段項目中用到了webservice,正好自己之前也了解過一點apache的cxf框架,所以就采用了cxf來實現(xiàn)webservice服務(wù)端,本身實現(xiàn)并沒技術(shù)難點,但是項目為了保證安全性,采用了傳輸加密的過程,所以大部分請求參數(shù)需要加密,返回參數(shù)也需要加密,大致流程是:

  • 請求參數(shù)對稱加密+對稱秘鑰非對稱加密

  • 返回參數(shù)堆成加密+對稱秘鑰非對稱加密

參數(shù)加密本身并不復(fù)雜,但是有些服務(wù)并不需要加密,有些則需要,加密工具類并不通用

string,datahandler等不能重用,雖然本質(zhì)都是對字節(jié)數(shù)據(jù)加密,但是要寫許多方法,還要方法參數(shù),檢查需要加解密處理的參數(shù),然后尋找對應(yīng)的類型處理方法調(diào)用.

邏輯很清晰,但是過程實現(xiàn)很惡心,最終這樣實現(xiàn)了一版,但是并不合我的意.

如果能在攔截器中獲取到參數(shù)列表,然后尋找對應(yīng)的解碼器解碼,這樣就比較簡單了.但是難點是,如果標(biāo)記參數(shù),并指定被標(biāo)記參數(shù)的解碼器尼?

我想到了注解,注解就可以標(biāo)記,參數(shù),然后通過反射獲取到注解,解析出內(nèi)容.

本來想標(biāo)記到參數(shù)上,但是一個個標(biāo)記太麻煩,而且獲取也不太方便,索性就放在方法上,用數(shù)組來接收.

問題解決.

代碼實現(xiàn)

自定義注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author webservice請求參數(shù)自定義注解
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestHanleAnnotation {
    Class[] handler() default {};
    int[] index() default {};
}

參數(shù)解碼器接口

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * @author taoyuan
 *參數(shù)處理器
 * @param <T>
 */
public abstract class  ParamHandler<T> {
//解碼器實例緩存
public static final Map<Class,ParamHandler> hanlers=new ConcurrentHashMap<>();
//處理方法
     abstract T handle(T t);
}

解碼器實現(xiàn),這里并沒有真正解碼,只是在參數(shù)后面加了123

public class StringHandler extends ParamHandler<String> {
    @Override
    public String handle(String t) {
        return t+"123";
    }
}

服務(wù)方法注解使用

//表示第一個參數(shù)需要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";
    }

攔截器實現(xiàn)

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(){
            // 在調(diào)用方法之前調(diào)用攔截器
            super(Phase.PRE_INVOKE);
        }
    @Override
    public void handleMessage(SoapMessage msg) throws Fault {
    /*獲取請求ip,攔截器中可以做下統(tǒng)一日志處理 
    HttpServletRequest httprequest = (HttpServletRequest)msg.get(AbstractHTTPDestination.HTTP_REQUEST);
        *
        */
        //獲取正在執(zhí)行的方法
         Method method = MsgUtil.getSoapMethod(msg);
         //解析注解,并處理參數(shù)
         MessageContentsList contentsList = MessageContentsList.getContentsList(msg);
         MsgUtil.handle(method,contentsList);
    }
    @Override
    public void handleFault(SoapMessage message) {
    super.handleFault(message);
    }

注解解析工具類實現(xiàn)

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 {
    /**根據(jù)消息獲取調(diào)用方法
     * @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++){
                //獲取需要處理的參數(shù)
                Object obj = contentsList.get(indexs[i]);
                //從緩存中獲取處理器實例
                handler=ParamHandler.hanlers.get(handlers[i]);
                if(handler==null){
                    //創(chuàng)建處理器實例
                    handler=(ParamHandler) handlers[i].newInstance();
                    //緩存處理器實例
                    ParamHandler.hanlers.put(handlers[i], handler);
                }
                 contentsList.set(indexs[i], handler.handle(obj));
        }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

返回參數(shù)同樣也可以注解實現(xiàn),這里就不在贅述了,實現(xiàn)也比較簡單.

**需要注意的是,攔截器攔截順序不一樣
攔截器統(tǒng)一繼承
AbstractPhaseInterceptor類,
請求攔截 :super(Phase.PRE_INVOKE);
返回攔截: super(Phase.PRE_STREAM);**

webservice注解匯總

@WebService

  • serviceName:對外發(fā)布的服務(wù)名,指定 Web Service 的服務(wù)名稱:wsdl:service。缺省值為 Java 類的簡單名稱 + Service。(字符串)

  • endpointInterface:服務(wù)接口全路徑, 指定做SEI(Service EndPoint Interface)服務(wù)端點接口

  • name:此屬性的值包含XML Web Service的名稱。在默認(rèn)情況下,該值是實現(xiàn)XML Web Service的類的名稱,wsdl:portType 的名稱。缺省值為 Java 類或接口的非限定名稱。(字符串

  • portName:wsdl:portName。缺省值為 WebService.name+Port。

  • targetNamespace:指定你想要的名稱空間,默認(rèn)是使用接口實現(xiàn)類的包名的反序

  • wsdlLocation:指定用于定義 Web Service 的 WSDL 文檔的 Web 地址。Web 地址可以是相對路徑或絕對路徑。(字符串)注意:實現(xiàn)類上可以不添加Webservice注解

@WebMethod

注釋表示作為一項 Web Service 操作的方法,將此注釋應(yīng)用于客戶機(jī)或服務(wù)器服務(wù)端點接口(SEI)上的方法,或者應(yīng)用于 JavaBeans 端點的服務(wù)器端點實現(xiàn)類。

要點:

僅支持在使用 @WebService 注釋來注釋的類上使用 @WebMethod 注釋

  • operationName:指定與此方法相匹配的wsdl:operation 的名稱。缺省值為 Java 方法的名稱。(字符串)

  • action:定義此操作的行為。對于 SOAP 綁定,此值將確定 SOAPAction 頭的值。缺省值為 Java 方法的名稱。(字符串)

  • exclude:指定是否從 Web Service 中排除某一方法。缺省值為 false。(布爾值)

@Oneway

注釋將一個方法表示為只有輸入消息而沒有輸出消息的 Web Service 單向操作。

將此注釋應(yīng)用于客戶機(jī)或服務(wù)器服務(wù)端點接口(SEI)上的方法,或者應(yīng)用于 JavaBeans 端點的服務(wù)器端點實現(xiàn)類

@WebParam

注釋用于定制從單個參數(shù)至 Web Service 消息部件和 XML 元素的映射。

將此注釋應(yīng)用于客戶機(jī)或服務(wù)器服務(wù)端點接口(SEI)上的方法,或者應(yīng)用于 JavaBeans 端點的服務(wù)器端點實現(xiàn)類。

  • name:參數(shù)的名稱。如果操作是遠(yuǎn)程過程調(diào)用(RPC)類型并且未指定partName 屬性,那么這是用于表示參數(shù)的 wsdl:part 屬性的名稱。如果操作是文檔類型或者參數(shù)映射至某個頭,那么 -name 是用于表示該參數(shù)的 XML 元素的局部名稱。如果操作是文檔類型、參數(shù)類型為 BARE 并且方式為 OUT 或 INOUT,那么必須指定此屬性。(字符串)

  • partName:定義用于表示此參數(shù)的 wsdl:part屬性的名稱。僅當(dāng)操作類型為 RPC 或者操作是文檔類型并且參數(shù)類型為BARE 時才使用此參數(shù)。(字符串)

  • targetNamespace:指定參數(shù)的 XML 元素的 XML 名稱空間。當(dāng)屬性映射至 XML 元素時,僅應(yīng)用于文檔綁定。缺省值為 Web Service的targetNamespace。(字符串)

  • mode:此值表示此方法的參數(shù)流的方向。有效值為 IN、INOUT 和 OUT。(字符串)

  • header:指定參數(shù)是在消息頭還是消息體中。缺省值為 false。(布爾值)

@WebResult

注釋用于定制從返回值至 WSDL 部件或 XML 元素的映射。將此注釋應(yīng)用于客戶機(jī)或服務(wù)器服務(wù)端點接口(SEI)上的方法,或者應(yīng)用于 JavaBeans 端點的服務(wù)器端點實現(xiàn)類。

  • name:當(dāng)返回值列示在 WSDL 文件中并且在連接上的消息中找到該返回值時,指定該返回值的名稱。對于 RPC 綁定,這是用于表示返回值的 wsdl:part屬性的名稱。對于文檔綁定,-name參數(shù)是用于表示返回值的 XML 元素的局部名。對于 RPC 和 DOCUMENT/WRAPPED 綁定,缺省值為 return。對于 DOCUMENT/BARE 綁定,缺省值為方法名 + Response。(字符串)

  • targetNamespace:指定返回值的 XML 名稱空間。僅當(dāng)操作類型為 RPC 或者操作是文檔類型并且參數(shù)類型為 BARE 時才使用此參數(shù)。(字符串)

  • header:指定頭中是否附帶結(jié)果。缺省值為false。(布爾值)

  • partName:指定 RPC 或 DOCUMENT/BARE 操作的結(jié)果的部件名稱。缺省值為@WebResult.name。(字符串)

@HandlerChain

注釋用于使 Web Service 與外部定義的處理程序鏈相關(guān)聯(lián)。只能通過對 SEI 或?qū)崿F(xiàn)類使用 @HandlerChain 注釋來配置服務(wù)器端的處理程序。但是可以使用多種方法來配置客戶端的處理程序??梢酝ㄟ^對生成的服務(wù)類或者 SEI 使用 @HandlerChain 注釋來配置客戶端的處理程序。此外,可以按程序在服務(wù)上注冊您自己的 HandlerResolver 接口實現(xiàn),或者按程序在綁定對象上設(shè)置處理程序鏈。

  • file:指定處理程序鏈文件所在的位置。文件位置可以是采用外部格式的絕對 java.net.URL,也可以是類文件中的相對路徑。(字符串)

  • name:指定配置文件中處理程序鏈的名稱。

以上是“如何使用webservice自定義注解處理參數(shù)加解密問題”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI