1. 程式人生 > >策略模式(註解版)實現 retrofit 的get和post請求的公共引數(二)

策略模式(註解版)實現 retrofit 的get和post請求的公共引數(二)

(想用純策略模式來完全解決 if else if switch case這種需求,是做不到的,或許策略模式根本不能這麼用,最近看到一個開源框架,作者使用策略模式+介面卡模式完美結合,前提是在使用之前要在Application中選擇自己的介面卡,如果兩個介面卡進行選一使用的時候,是不是也要進行if else if switch case的判斷了呢?)
即:
https://github.com/orhanobut/logger ,一個日誌列印框架

廢話不多說,下面升級一下我們的策略模式實現retrofit公共引數:

主要更改的是把ParamsContext類中的Switch case 去掉,換一種方式。

switch (request.method()) {
            case GET:
                iRequestParam = new GetRequestParams();
                break;
            case POST:
                iRequestParam = new PostRequestParams();
                break;

(不然新增一個新的策略,是不是又要加個case?)

為了不加case,我們來試試反射:

1、註解類:

//適用於類上面的註解
@Target(ElementType.TYPE) //執行時註解 @Retention(RetentionPolicy.RUNTIME) public @interface Method { //返回String,預設GET String value() default "GET"; }

2、具體實現類加上註解

什麼都不改,就類上面加個註解即可:@Method(“GET”)

@Method("GET")
public class GetRequestParams implements IRequestParam {
    @Override
    public
Request getRequest(Request request, Context context) { //新增公共引數 HttpUrl modifiedUrl = request.url().newBuilder() .addQueryParameter(CLIENT, AppTools.getClient(context)) .addQueryParameter(VERSION, AppTools.getAppVersion(context)) .addQueryParameter(TOKEN, AppTools.getToken(context)) .build(); return request.newBuilder().url(modifiedUrl).build(); } }

POST同上

@Method("POST")
public class PostRequestParams implements IRequestParam {
    @Override
    public Request getRequest(Request request, Context context) {

        if (request.body() instanceof FormBody) {
            FormBody.Builder bodyBuilder = new FormBody.Builder();

            FormBody formBody = (FormBody) request.body();

            for (int i = 0; i < formBody.size(); i++) {
                bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
            }

            formBody = bodyBuilder.add(CLIENT, AppTools.getClient(context))
                    .addEncoded(VERSION, AppTools.getAppVersion(context))
                    .addEncoded(TOKEN, AppTools.getToken(context))
                    .build();
            request = request.newBuilder().post(formBody).build();
        }
        return request;
    }
}

好了,這些做完之後,就改修改關鍵地方了 ParamsContext,
一句話:拿到IRequestParam的所有實現類 返回即可

具體程式碼如下:

public class ParamsContext {

    public static final String GET = "GET";
    public static final String POST = "POST";

    private Context context;
    private Request request;

    //--------------------------------註解相關-----------------------------------
    private List<Class<? extends IRequestParam>> requestParamList;


    public ParamsContext(Request request, Context context) {
        this.context = context;
        this.request = request;

        init();
    }

    public Request getInRequest() {
        //選擇策略進行處理
        IRequestParam iRequestParam = chooseRequest(request.method());
        return iRequestParam.getRequest(request, context);
    }


    //------------------------------反射獲取註解-----------------------------------

    private void init() {
        requestParamList = new ArrayList<>();

        try {
            String packageName = getClass().getPackage().getName();
            Class<?> getRequestParams = Class.forName(packageName + ".GetRequestParams");
            Class<?> postRequestParams = Class.forName(packageName + ".PostRequestParams");
            List<Class<?>> classList = new ArrayList<>();
            classList.add(getRequestParams);
            classList.add(postRequestParams);

            for (int i = 0; i < classList.size(); i++) {
                Class<?> clazz = classList.get(i);
                //判斷clazz是否是IRequestParam的實現類
                if (IRequestParam.class.isAssignableFrom(clazz)) {
                    requestParamList.add((Class<? extends IRequestParam>) clazz);
                }
            }


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


    }


    //根據返回的method產生相應的方法
    public IRequestParam chooseRequest(String requestMethod) {

        //在策略列表中查詢策略
        for (Class<? extends IRequestParam> clazz : requestParamList) {
            //獲取該策略的註解
            Method method = clazz.getAnnotation(Method.class);
            if (requestMethod.equals(method.value())) {
                try {
                    return clazz.newInstance();
                } catch (Exception e) {
                    throw new RuntimeException("策略獲得失敗");
                }
            }
        }

        throw new RuntimeException("策略獲得失敗");
    }
}

客戶端使用不變:

    public Interceptor initQuery(final Context context) {


        Interceptor addQueryParameterInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                request = new ParamsContext(request, context).getInRequest();
                return chain.proceed(request);
            }
        };
        return addQueryParameterInterceptor;
    }

至此,修改就結束了,此時如果我想新增一個新的策略(update、delete等..),只需要加一個帶有註解的策略即可
原始碼:https://github.com/MrXiong/ZxRetrofit2.0

———————————————–分割線—————————————-

這裡有個問題,設計模式學習之策略模式 這篇文章裡面獲取包下面的類是通過getClass().getClassLoader().getResource獲取的,我這裡是通過 Class.forName方法獲取的,就是事先需要知道IRequestParam介面的實現類,那麼如果新增一個新策略,這個勢必也要新增一個。

那篇文章的獲取包下面所有類是這樣寫的:

private File[] getResources() {
        try {
            File file = new File(classLoader.getResource(CAL_PRICE_PACKAGE.replace(".", "/")).toURI());
            return file.listFiles(new FileFilter() {
                public boolean accept(File pathname) {
                    if (pathname.getName().endsWith(".class")) {//我們只掃描class檔案
                        return true;
                    }
                    return false;
                }
            });
        } catch (URISyntaxException e) {
            throw new RuntimeException("未找到策略資源");
        }
    }

可是我在Android Sudio中使用怎麼獲取到的getResource始終是空的,後來我想不就是找.class檔案麼,Android Studio編譯後的.class檔案不就在/app/build/intermediates/classes 這裡麼,我就把路徑換了一下:

    private File[] getResources() {
        try {

            String classPath = "../app/build/intermediates/classes/debug/com/zx/rxjava/policy";
            URL resource = getClass().getClassLoader().getResource(classPath);
            Logs.d(resource +"");
            URI uri = resource.toURI();

            File file = new File(classPath);


            File[] files = file.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    if (pathname.getName().endsWith(".class")) {//我們只掃描class檔案
                        return true;
                    }
                    return false;
                }
            });
            return files;

        } catch (Exception e) {
            throw new RuntimeException("未找到策略資源");
        }
    }

可是仍然獲取不到值,各位大佬知道問題的請告知我哦,O(∩_∩)O謝謝

相關推薦

GETPOST請求的區別面試原理都得知道

關於GET和POST是經常用到的兩種請求介面的方式   GET和POST是HTTP請求的兩種基本方法,要說它們的區別,接觸過WEB開發的人都能說出一二。   最直觀的區別就是GET把引數包含在URL中,POST通過request body傳遞引數

PHP中使用CURL實現模擬GETPOST請求,親測完美解決

//初始化 $curl = curl_init(); //設定抓取的url curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com'); //設定標頭檔案的資訊作為資料流輸出 curl_setopt($cur

Java實現傳送GetPost請求

前言 已經有幾天沒有寫部落格了 , 原因是最近生活中有大量的事情, 儘管每天都在學習 , 但是卻沒有將知識點記錄在部落格中 , 感覺這樣非常不好 . 以後一定要堅持寫部落格 , 記錄自己

策略模式註解實現 retrofitgetpost請求公共引數

(想用純策略模式來完全解決 if else if switch case這種需求,是做不到的,或許策略模式根本不能這麼用,最近看到一個開源框架,作者使用策略模式+介面卡模式完美結合,前提是在使用之前要在Application中選擇自己的介面卡,如果兩個介面卡

策略模式實現 retrofitgetpost請求公共引數

策略模式的作用,作用是替換if,elst if ,switch case,可是為什麼我就替換不了呢? 比如: 圖書價格,初級會員9折,高階會員打8折 通常實現: private double getPrice(int grade, doubl

php 實現http getpost提交json資料請求

 介面,抓取資料經常用到 //$arr為提交的資料為json型別 預設 get function http_curl($url,$type='get',$res='json',$arr=''){ //1.初始化curl $ch = cu

angularJS 條件查詢 品優購條件查詢品牌條件查詢列表展示公用方法解決思路 及 post請求混合引數提交方式

  Brand.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"

用python傳送帶傳參的GetPost請求

上一篇文章使用了python的urllib來進行傳送帶傳參的Get和Post請求 後來請教了下組裡的前輩,發現有稍微更簡潔一點的寫法 是直接使用requests,下面附上程式碼 Get請求 # -*-coding:utf-8 -*- import request

Java使用HttpsURLConnection進行GetPost請求繞過證書驗證

public String gethttpsconnbypost(String url,Map headMap){ StringBuilder result = new StringBuilder(); try { //建立地址物件 URL u=new URL(url); //獲取

nodejs學習筆記——處理getpost請求

上一章介紹瞭如何在nodejs中構造httpserver以及在nodejs中如何構造httpclient來訪問httpserver,接下來說一下nodejs在http互動中是如何處理請求的。首先我們回顧一下上一章最後的例子: server程式碼(server把請求頭資訊處

Java程式碼發起HTTP GETPOST請求URLConnection

背景:在使用java語言寫介面自動化用例的時候,經常用到程式碼直接發起HTTP請求,從而得到響應內容,通過斷言響應內容,判斷介面返回是否正確。 方法:java實現HTTP請求主要有兩種方法,一是用JDK自帶類URLConnection、二是用第三方jar包ht

iOS開發網路篇—傳送GETPOST請求使用NSURLSession

1)該文主要介紹如何使用NSURLSession來發送GET請求和POST請求   2)本文將不再講解NSURLConnection的使用,如有需要了解NSURLConnection如何傳送請求。     詳細資訊,請參考:http://www.cnblogs.co

java封裝httpClient工具支援httphttps,包含getpost請求

網上有關方法非常多,但相對較零散,有些只支援http或https中的一種,或者只有get或post中的一種。以下對httpclient工具做了比較全面的封裝,支援http和https,包含get和post請求。 maven匯入的jar包有: <dependency&g

原生AjaxGETPOST請求jQueryAjaxGetPost請求詳解

// 原生Ajax Get Post請求 function ajGet(){ // 建立一個 XMLHttpRequest 物件。(這個東西有相容,需要做相容的可以去搜下) var xhr = new XMLHttpRequest(); // 開啟請求,三個引數,

PHP中使用CURL實現GETPOST請求

由於 protocol 對稱加密 即使 匯報 bst 接口 useragent 拷貝 一、什麽是CURL? cURL 是一個利用URL語法規定來傳輸文件和數據的工具,支持很多協議,如HTTP、FTP、TELNET等。最爽的是,PHP也支持 cURL 庫。使用php的cURL

CURL實現發送GetPost請求(PHP)

結果 基本 釋放 初始 常用 header 理解 介紹 今天 1.cURL介紹   cURL 是一個利用URL語法規定來傳輸文件和數據的工具,支持很多協議,如HTTP、FTP、TELNET等。最爽的是,PHP也支持 cURL 庫。本文將介紹 cURL 的一些高級特性,以及

利用Java實現GETPOST請求

三個類 Java建立代理連線物件 Java傳送Post請求 Java傳送Get請求 程式碼 Java建立代理連線物件 /** * 1.返回代理物件 * @param proxyIp * @param

C++:C語言實現HTTP的GETPOST請求例程參考 C++:C語言實現HTTP的GETPOST請求

C++:C語言實現HTTP的GET和POST請求   閱讀目錄   HTTP請求和IP/TCP   實現GET請求   實現POST請求:   參考: 回到頂部

PHP中使用cURL實現GetPost請求的方法

data print str close arr 設置 高級特性 post數據 decode cURL 是一個利用URL語法規定來傳輸文件和數據的工具,支持很多協議,如HTTP、FTP、TELNET等。最爽的是,PHP也支持 cURL 庫。本文將介紹 cURL 的一些高級特

用Java實現傳送http的getpost請求

import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; imp