首页 > 代码库 > 【网络】app(retorfit2+RxJava)+javaweb(服务器) retrofit2官方文档实践

【网络】app(retorfit2+RxJava)+javaweb(服务器) retrofit2官方文档实践

官方文档:http://square.github.io/retrofit/
下列操作,是在Retrofit环境配置好的情况下进行的。

tjstudy:写在前面,开发环境

app环境:
android studio 2.1.1
minSdkVersion 14
targetSdkVersion 23

javaweb server 环境:
MyEclipse 10
jdk 1.6

一 、最基本的标记

@GET @POST 标记:网络访问方式的最基本标记
指定访问方式,一般会写入访问地址,如果是获取的数据,还可以进行排序。
建议:base_url,最好以/结尾 @GET @POST里面的地址不以/开头。

@GET("users/list ")
@POST("users/list?dort=asc")

二 、POST 和GET方式,通用retorfit 标记

POST GET 通用:@Path @Query @QueryMap @Header
两者通用的标记:主要是指使用使用@POST 和@GET方式都能够接收到数据信息,显示效果差不多,实际开发中,根据要求使用的网络方式来进行选择
下面演示的效果大多为@GET,POST方式直接将GET 换成POST 查看了即可。

1 、 @Path:指定访问路径

@GET("{name}/UploadParam")
Observable<ResponseBody> test(@Path("name")String name);

动态传入的String 会取代{name}作为新的访问地址
这个时候访问的地址就是,base_url+name+/UploadParam

技术分享

2 、@Query :提交参数—-不是表单提交,只是普通提交

@GET("servlet/UploadParam")
Observable<ResponseBody> testQuery(@Query("name") String name);

服务器结果:

技术分享

3 、@QueryMap:是@Query的集合形式,能够携带更多的参数

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

只需要将要携带的参数都put到Map集合里面,传进来就可以了。

4 、@Header :在网络访问中添加Header信息

@Headers({
        "appkey:tjstudy _ 2016 10 23"
})
@GET("servlet/HeaderTest")
Observable<ResponseBody> testHeader(@Query("name") String name);

服务器结果:

技术分享

@Header 也可以直接放到实际请求参数中,效果和上面一致

@GET("servlet/HeaderTest")
Observable<ResponseBody> testHeader(@Header(“appkey”) 
String appkey,@Query("name") String name);

三、必须POST方式(@body @FormUrlEncoded @Multipart)

使用GET方式 + 上面的任意标记 都会报错。并且这三个标记不能混合使用,否则会报错。

1、@Body:上传一个对象

@POST("servlet/TestBody")
Observable<ResponseBody> testBody(
       @Body User user
);

服务器结果:

技术分享

是否可以上传两个对象?
在上述代码中添加了另一个User,直接报错…..貌似只能上传一个对象

2、@FormUrlEncoded:表单提交 和@Field 配对,访问过程中,参数中至少有一个@Field

@FormUrlEncoded
@POST("servlet/TestFormUrlEncodes")
Observable<ResponseBody> testFormUrlEncoded(
        @Field("param1") String first,
        @Field("param2") String last
);

服务器结果:

技术分享

@FormUrlEncoded 标记的方法中,至少要有一个参数是@Field 标记的参数,否则会报错。人家是配对的,别拆散他们。其他的参数可以是其他的标记,例如:@Query (虽然没必要,但是至少这种情况不会报错)。

3、@Multipart:文件等上传 和@Part 配对 访问过程中,参数中至少有一个@Part

RequestBody 可以封装什么样的类型,@Multipart就能将这样类型的数据上传到服务器。RequestBody可以封装文本,图片文件,音频文件等。

这里列举的是图片文件
服务器怎么接收文件,这里使用fileupload 来接收(需要引入fileupload相关包commons-fileupload-1.3和commons-io-1.2 可在代码中找到)。主要代码:

PrintWriter pw = response.getWriter();
        // 创建文件项目工厂对象
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置文件上传路径
        File uploadDir = new File(this.getServletContext().getRealPath(
                "/upload/"));// 设置文件上传的路径为项目名/upload/
        System.out.println("文件上传的路径=" + uploadDir);
        if (!uploadDir.exists()) {// 如果改文件夹不存在就创建
            uploadDir.mkdirs();
        }
        // 获取系统默认的临时文件保存路径,该路径为Tomcat根目录下的temp文件夹
        String temp = System.getProperty("java.io.tmpdir");
        // 设置缓冲区大小为 5M
        factory.setSizeThreshold(1024 * 1024 * 5);
        // 设置临时文件夹为temp
        factory.setRepository(new File(temp));
        // 用工厂实例化上传组件,ServletFileUpload 用来解析文件上传请求
        ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
        try {
            List<FileItem> list = servletFileUpload.parseRequest(request);
            System.out.println("文件的个数=" + list);
            for (FileItem fileItem : list) {
                if(fileItem==null){
                    System.out.println("获取到的文件是空的");
                    break;
                }
                File file = new File(uploadDir, fileItem.getFieldName()+".png");
                if (!file.exists()) {// 文件不存在才创建
                    fileItem.write(file);// 保存文件
                    System.out.println("文件名:" + file.getName());
                }
            }
            pw.write("{\"message\":\"上传成功\"}");
            System.out.println("{\"message\":\"上传成功\"}");
        } catch (Exception e) {
            pw.write("{\"message\":\"上传失败\"}");
            System.out.println("{\"message\":\"上传失败\"}");
        }
1)、@Mutipart + RequestBody上传单文件
File imageFile = new File(Environment.getExternalStorageDirectory().getPath(),"123.png");
RequestBody imageRequestBody = RequestBody.create(MediaType.parse("image/png"), imageFile);
@Multipart
@POST("servlet/TestMultipart")
Observable<ResponseBody> testSingleMultipart(
        @Part("photo") RequestBody image
);

服务器结果:

技术分享

2)、@Mutipart + RequestBody上传单文件 和参数

由于这里上传的文件和接收的路径都是一样的,在新操作之前,需要先把已经上传的文件删除。

@Multipart
@POST("servlet/TestSingleMultipartParam")
Observable<ResponseBody> testSingleMultipartParam(
        @Part("photo") RequestBody image,
        @Query("des") String des
);

不能使用@FormUrlEncoded提交参数,使用会报错
服务器结果:

技术分享

3)、@Mutipart + RequestBody上传多文件和参数
@Multipart
@POST("servlet/TestMultipartMoreFile")
Observable<ResponseBody> testMoreMultipartParam(
        @Part("photo1") RequestBody image1,
        @Part("photo2") RequestBody image2,
        @Query("des") String des
);

源文件只是一张图片
服务器结果:

技术分享

4)、@PartMap 上传文件和参数
@Multipart
@POST("servlet/TestPostMultipartBodyPart")
Observable<ResponseBody> testMultipartBodyMap(
        @Query("des") String des,
        @PartMap Map<String, RequestBody> images
);

服务器结果:

技术分享

5)、@Multipart 文件上传的另外一种方式——MultipartBody.Part

注意MultipartBody是okhttp3的一个方法,在okhttp2里面不存在。这里使用的是Retrofit2 所以自带的是Okhttp3
它和RequestBody的关系:

File file = new File(Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "123.png");
RequestBody requestBody =
            RequestBody.create(MediaType.parse("image/png"), file);
//参数1 数组名,参数2 文件名。
MultipartBody.Part photo1part = 
            MultipartBody.Part.createFormData("pic1", "pic2", requestBody1);

MultipartBody.part 其实就是对RequestBody的封装

@Multipart
@POST("servlet/TestPostMultipartBodyPart")
Observable<ResponseBody> testMultipartBody(
        @Part("photo1") RequestBody image1,
        @Part MultipartBody.Part image2,
        @Query("des")String des

);

这里使用的是两种上传方式
服务器结果:

技术分享

疑惑:明明直接使用ResponseBody 就能完成文件上传,为什么还要使用MultipartBody.part? 根据目前接触的网络访问操作,疑惑未解决。
//todo 为什么呢?

另外:怎么下载文件?操作比较简单
下载文件主要是对流的操作,服务器将流写入到ResponseBody里面返回到客户端就好了。客户端获取到流,然后进行操作。

四、完整demo

app效果图

技术分享

demo下载地址:
http://download.csdn.net/detail/u012391876/9662557

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    【网络】app(retorfit2+RxJava)+javaweb(服务器) retrofit2官方文档实践