前言 Retrofit 这个东西是简化我们在 java 代码里面书写 http 请求的工具,支持 restful 风格的请求,我们通常发送请求,要用到 hutools 和 httpUtil 这些东西,要写好多行,现在用 Retrofit 只需要两三行。
源码先给你们:retrofit-demo
一、引入依赖 MAVEN 1 2 3 4 5 <dependency > <groupId > com.github.lianjiatech</groupId > <artifactId > retrofit-spring-boot-starter</artifactId > <version > 2.3.8</version > </dependency >
Gradle 1 compile group : 'com.github.lianjiatech' , name: 'retrofit-spring-boot-starter' , version: '2.3.8'
这个工具尚不成熟,最好紧跟版本,使用最新版
二、使用步骤 1.在启动类上添加注解 这个路径是用书写 retrofit 请求方法的文件的包路径,下面我有介绍
1 @RetrofitScan("com.example.retrofitdemo.retrofitinterface")
2.项目解析 结构 entity、controller 和 service 都是普通的 entity、controller和service,retrofit
要创建的东西只有 interceptor
和 retrofitInterceptor
各种请求方法的书写方式 retrofit 的请求方法有很多,除了普通请求,还支持 Restful 风格,我在 RetrofitTest 里面几乎把所有请求方式的demo都写了,并且有详细的注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 package com.example.retrofitdemo.retrofitinterface;import com.example.retrofitdemo.entity.TestEntity;import com.example.retrofitdemo.interceptor.TokenInterceptor;import com.github.lianjiatech.retrofit.spring.boot.annotation.Intercept;import com.github.lianjiatech.retrofit.spring.boot.annotation.RetrofitClient;import okhttp3.MultipartBody;import okhttp3.Response;import org.springframework.stereotype.Component;import retrofit2.http.*;import java.util.List;import java.util.Map;@Component @RetrofitClient(baseUrl = "http://localhost:8081/") @Intercept(handler = TokenInterceptor.class, include = "test/**") public interface RetrofitTest { @POST("test/postList") List<TestEntity> postList (@Body TestEntity testEntity) ; @GET("test/getList") List<TestEntity> getList (@Query("pageNum") Integer pageNum, @Query("pageSize") Integer pageSize) ; @GET("test/{id}") List<TestEntity> getList2 (@Path("id") Long id) ; @GET("test/delete/{id}") Void delete (@Path("id") Long id) ; @POST("test/add") Void add (@Body TestEntity testEntity) ; @POST("test/update/{id}") Void update (@Path("id") Long id, @Body TestEntity testEntity) ; @FormUrlEncoded @POST("test") Void postFrom (@Field("name") String name,@Field("occupation") String age) ; @FormUrlEncoded @POST("test") Void postMap (@FieldMap Map<String, String> fields) ; @GET("test") Void header (@Header("Accept-Language") String head) ; @GET("test") Void headers (@HeaderMap Map<String, String> headers) ; @Headers("Accept: text/plain") @GET("/") Void headers2 () ; @HTTP(method = "DELETE", path = "test/delete", hasBody = true) Void delete2 (@Body TestEntity testEntity) ; @HTTP(method = "CUSTOM", path = "test/") Void custom () ; @Multipart @POST("/") Void multipartExample (@Part("description") String description, @Part(value = "image", encoding = "8-bit") TestEntity image, @PartMap Map<String, String> params) ; @POST("test/upload") @Multipart Void upload (@Part MultipartBody.Part file) ; @GET("test/{fileKey}") Response download (@Path("fileKey") String fileKey) ; }
在 ServiceImpl 中调用 在 service
中注入上面的类,然后调用里面的方法,就可以发送请求了
使用 retrofit 发送上传和下载请求时,serviceImpl 要做一些处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 package com.example.retrofitdemo.service.impl;import com.example.retrofitdemo.entity.TestEntity;import com.example.retrofitdemo.retrofitinterface.RetrofitTest;import com.example.retrofitdemo.service.TestService;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.Response;import okhttp3.ResponseBody;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.URLEncoder;import java.util.Objects;import java.util.UUID;@Service public class TestServiceImpl implements TestService { @Autowired private RetrofitTest retrofitTest; @Override public void Test () { TestEntity testEntity = new TestEntity (); testEntity.setPageNum(1 ); testEntity.setPageQuantity(5 ); System.out.println(retrofitTest.postList(testEntity)); } public void upload (MultipartFile file) throws IOException { String fileName = URLEncoder.encode(Objects.requireNonNull(file.getOriginalFilename()),"utf-8" ); okhttp3.RequestBody requestBody=okhttp3.RequestBody.create(MediaType.parse("multipart/form-data" ),file.getBytes()); MultipartBody.Part part = MultipartBody.Part.createFormData("file" ,fileName,requestBody); retrofitTest.upload(part); } public void download () throws Exception { String fileKey = "6302d742-ebc8-4649-95cf-62ccf57a1add" ; Response response = retrofitTest.download(fileKey); ResponseBody responseBody = response.body(); InputStream is = responseBody.byteStream(); File tempDirectory = new File ("temp" ); if (!tempDirectory.exists()) { tempDirectory.mkdir(); } File file = new File (tempDirectory, UUID.randomUUID().toString()); if (!file.exists()) { file.createNewFile(); } FileOutputStream fos = new FileOutputStream (file); byte [] b = new byte [1024 ]; int length; while ((length = is.read(b)) > 0 ) { fos.write(b, 0 , length); } is.close(); fos.close(); } }
按需配置拦截器 这个拦截器的功能是请求前在请求中加入 token 的功能,可以按需创建,也可以不创建,拦截器分为局部拦截器和全局拦截器,我在TokenInterceptor 里写了很详细的注释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.example.retrofitdemo.interceptor;import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor;import okhttp3.Request;import okhttp3.Response;import org.springframework.stereotype.Component;import java.io.IOException;@Component public class TokenInterceptor extends BasePathMatchInterceptor { @Override protected Response doIntercept (Chain chain) throws IOException { String token = "加入这是一个token" ; Request request = chain.request(); if (!"" .equals(token)) { request = request.newBuilder() .header("Authorization" , token) .build(); } return chain.proceed(request); } }
进阶配置文件 retrofit 下面的配置可选,不配置也不影响使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 server: port: 8080 retrofit: pool: test1: max-idle-connections: 3 keep-alive-second: 100 disable-void-return-type: false global-converter-factories: - com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory - retrofit2.converter.jackson.JacksonConverterFactory global-call-adapter-factories: - com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory - com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory log: enable: true logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor global-log-level: info global-log-strategy: body retry: enable-global-retry: true global-interval-ms: 1 global-max-retries: 1 global-retry-rules: - response_status_not_2xx - occur_io_exception retry-interceptor: com.github.lianjiatech.retrofit.spring.boot.retry.DefaultRetryInterceptor degrade: enable: true degrade-type: sentinel resource-name-parser: com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser global-connect-timeout-ms: 5000 global-read-timeout-ms: 5000 global-write-timeout-ms: 5000 global-call-timeout-ms: 0
总结 还可以请求微服务,不过我不懂,更多详细的用法可以看 gitee 的详解 https://gitee.com/lianjiatech/retrofit-spring-boot-starter