官方文档: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 通用:@Path @Query @QueryMap @Header
两者通用的标记:主要是指使用使用@POST 和@GET方式都能够接收到数据信息,显示效果差不多,实际开发中,根据要求使用的网络方式来进行选择。
下面演示的效果大多为@GET,POST方式直接将GET 换成POST 查看了即可。
@GET("{name}/UploadParam") Observable<ResponseBody> test(@Path("name")String name);
动态传入的String 会取代{name}作为新的访问地址
这个时候访问的地址就是,base_url+name+/UploadParam
@GET("servlet/UploadParam") Observable<ResponseBody> testQuery(@Query("name") String name);
服务器结果:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
只需要将要携带的参数都put到Map集合里面,传进来就可以了。
@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);
使用GET方式 + 上面的任意标记 都会报错。并且这三个标记不能混合使用,否则会报错。
@POST("servlet/TestBody")
Observable<ResponseBody> testBody(
@Body User user
);
服务器结果:
是否可以上传两个对象?
在上述代码中添加了另一个User,直接报错…..貌似只能上传一个对象
@FormUrlEncoded @POST("servlet/TestFormUrlEncodes") Observable<ResponseBody> testFormUrlEncoded( @Field("param1") String first, @Field("param2") String last );
服务器结果:
注:@FormUrlEncoded 标记的方法中,至少要有一个参数是@Field 标记的参数,否则会报错。人家是配对的,别拆散他们。其他的参数可以是其他的标记,例如:@Query (虽然没必要,但是至少这种情况不会报错)。
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\":\"上传失败\"}");
}
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 );
服务器结果:
由于这里上传的文件和接收的路径都是一样的,在新操作之前,需要先把已经上传的文件删除。
@Multipart @POST("servlet/TestSingleMultipartParam") Observable<ResponseBody> testSingleMultipartParam( @Part("photo") RequestBody image, @Query("des") String des );
不能使用@FormUrlEncoded提交参数,使用会报错。
服务器结果:
@Multipart @POST("servlet/TestMultipartMoreFile") Observable<ResponseBody> testMoreMultipartParam( @Part("photo1") RequestBody image1, @Part("photo2") RequestBody image2, @Query("des") String des );
源文件只是一张图片
服务器结果:
@Multipart @POST("servlet/TestPostMultipartBodyPart") Observable<ResponseBody> testMultipartBodyMap( @Query("des") String des, @PartMap Map<String, RequestBody> images );
服务器结果:
注意: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里面返回到客户端就好了。客户端获取到流,然后进行操作。
app效果图
demo下载地址:
http://download.csdn.net/detail/u012391876/9662557