輕量級http請求工具forest


以下例子基於Spring Boot

第一步:添加Maven依賴

直接添加以下maven依賴即可

<dependency>  <groupId>com.dtflys.forest</groupId>  <artifactId>forest-spring-boot-starter</artifactId>  <version>1.5.0</version> </dependency>

第二步:創建一個interface

就以高德地圖API為栗子吧


package com.yoursite.client;  import com.dtflys.forest.annotation.Request; import com.dtflys.forest.annotation.DataParam;  public interface AmapClient {   /**  * 聰明的你一定看出來了@Get注解代表該方法專做GET請求  * 在url中的${0}代表引用第一個參數,${1}引用第二個參數  */  @Get("http://ditu.amap.com/service/regeo?longitude=${0}&latitude=${1}")  Map getLocation(String longitude, String latitude); } 

第三步:掃描接口

在Spring Boot的配置類或者啟動類上加上@ForestScan注解,並在basePackages屬性里填上遠程接口的所在的包名

@SpringBootApplication @Configuration @ForestScan(basePackages = "com.yoursite.client") public class MyApplication {  public static void main(String[] args) {  SpringApplication.run(MyApplication.class, args);  } }

第四步:調用接口

OK,我們可以愉快地調用接口了

// 注入接口實例 @Autowired private AmapClient amapClient; ... // 調用接口 Map result = amapClient.getLocation("121.475078", "31.223577"); System.out.println(result);

發送JSON數據

/**  * 將對象參數解析為JSON字符串,並放在請求的Body進行傳輸  */ @Post("/register") String registerUser(@JSONBody MyUser user);  /**  * 將Map類型參數解析為JSON字符串,並放在請求的Body進行傳輸  */ @Post("/test/json") String postJsonMap(@JSONBody Map mapObj);  /**  * 直接傳入一個JSON字符串,並放在請求的Body進行傳輸  */ @Post("/test/json") String postJsonText(@JSONBody String jsonText);

發送XML數據

/**  * 將一個通過JAXB注解修飾過的類型對象解析為XML字符串  * 並放在請求的Body進行傳輸  */ @Post("/message") String sendXmlMessage(@XMLBody MyMessage message);  /**  * 直接傳入一個XML字符串,並放在請求的Body進行傳輸  */ @Post("/test/xml") String postXmlBodyString(@XMLBody String xml);

文件上傳

/**  * 用@DataFile注解修飾要上傳的參數對象  * OnProgress參數為監聽上傳進度的回調函數  */ @Post("/upload") Map upload(@DataFile("file") String filePath, OnProgress onProgress);

可以用一個方法加Lambda同時解決文件上傳和上傳的進度監聽

Map result = myClient.upload("D:\\TestUpload\\xxx.jpg", progress -> {  System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已上傳百分比  if (progress.isDone()) { // 是否上傳完成  System.out.println("-------- Upload Completed! --------");  } });

多文件批量上傳

/**  * 上傳Map包裝的文件列表,其中 ${_key} 代表Map中每一次迭代中的鍵值  */ @Post("/upload") ForestRequest<Map> uploadByteArrayMap(@DataFile(value = "file", fileName = "${_key}") Map<String, byte[]> byteArrayMap);  /**  * 上傳List包裝的文件列表,其中 ${_index} 代表每次迭代List的循環計數(從零開始計)  */ @Post("/upload") ForestRequest<Map> uploadByteArrayList(@DataFile(value = "file", fileName = "test-img-${_index}.jpg") List<byte[]> byteArrayList);

文件下載

下載文件也是同樣的簡單

/**  * 在方法上加上@DownloadFile注解  * dir屬性表示文件下載到哪個目錄  * OnProgress參數為監聽上傳進度的回調函數  * ${0}代表引用第一個參數  */ @Get("http://localhost:8080/images/xxx.jpg") @DownloadFile(dir = "${0}") File downloadFile(String dir, OnProgress onProgress);

調用下載接口以及監聽下載進度的代碼如下:

File file = myClient.downloadFile("D:\\TestDownload", progress -> {  System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已下載百分比  if (progress.isDone()) { // 是否下載完成  System.out.println("-------- Download Completed! --------");  } });

基本簽名驗證

@Post("/hello/user?username=${username}") @BasicAuth(username = "${username}", password = "bar") String send(@DataVariable("username") String username);

OAuth 2.0

@OAuth2(  tokenUri = "/auth/oauth/token",  clientId = "password",  clientSecret = "xxxxx-yyyyy-zzzzz",  grantType = OAuth2.GrantType.PASSWORD,  scope = "any",  username = "root",  password = "xxxxxx" ) @Get("/test/data") String getData();

自定義注解

Forest允許您根據需要自行定義注解,不但讓您可以簡單優雅得解決各種需求,而且極大得擴展了Forest的能力。

定義一個注解

/**  * 用Forest自定義注解實現一個自定義的簽名加密注解  * 凡用此接口修飾的方法或接口,其對應的所有請求都會執行自定義的簽名加密過程  * 而自定義的簽名加密過程,由這里的@MethodLifeCycle注解指定的生命周期類進行處理  * 可以將此注解用在接口類和方法上  */ @Documented /** 重點: @MethodLifeCycle注解指定該注解的生命周期類*/ @MethodLifeCycle(MyAuthLifeCycle.class) @RequestAttributes @Retention(RetentionPolicy.RUNTIME) /** 指定該注解可用於類上或方法上 */ @Target({ElementType.TYPE, ElementType.METHOD}) public @interface MyAuth {   /**  * 自定義注解的屬性:用戶名  * 所有自定注解的屬性可以在生命周期類中被獲取到  */  String username();   /**  * 自定義注解的屬性:密碼  * 所有自定注解的屬性可以在生命周期類中被獲取到  */  String password(); }

定義注解生命周期類

/**  * MyAuthLifeCycle 為自定義的 @MyAuth 注解的生命周期類  * 因為 @MyAuth 是針對每個請求方法的,所以它實現自 MethodAnnotationLifeCycle 接口  * MethodAnnotationLifeCycle 接口帶有泛型參數  * 第一個泛型參數是該生命周期類綁定的注解類型  * 第二個泛型參數為請求方法返回的數據類型,為了盡可能適應多的不同方法的返回類型,這里使用 Object  */ public class MyAuthLifeCycle implements MethodAnnotationLifeCycle<MyAuth, Object> {    /**  * 當方法調用時調用此方法,此時還沒有執行請求發送  * 次方法可以獲得請求對應的方法調用信息,以及動態傳入的方法調用參數列表  */  @Override  public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] args) {  System.out.println("Invoke Method '" + method.getMethodName() + "' Arguments: " + args);  }   /**  * 發送請求前執行此方法,同攔截器中的一樣  */  @Override  public boolean beforeExecute(ForestRequest request) {  // 通過getAttribute方法獲取自定義注解中的屬性值  // getAttribute第一個參數為request對象,第二個參數為自定義注解中的屬性名  String username = (String) getAttribute(request, "username");  String password = (String) getAttribute(request, "password");  // 使用Base64進行加密  String basic = "MyAuth " + Base64Utils.encode("{" + username + ":" + password + "}");  // 調用addHeader方法將加密結構加到請求頭MyAuthorization中  request.addHeader("MyAuthorization", basic);  return true;  }   /**  * 此方法在請求方法初始化的時候被調用  */  @Override  public void onMethodInitialized(ForestMethod method, BasicAuth annotation) {  System.out.println("Method '" + method.getMethodName() + "' Initialized, Arguments: " + args);  } }

使用自定義的注解

/**  * 在請求接口上加上自定義的 @MyAuth 注解  * 注解的參數可以是字符串模板,通過方法調用的時候動態傳入  * 也可以是寫死的字符串  */ @Get("/hello/user?username=${username}") @MyAuth(username = "${username}", password = "bar") String send(@DataVariable("username") String username);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM