zoukankan      html  css  js  c++  java
  • Android学习笔记(十九) OkHttp

    一、概述

    根据我的理解,OkHttp是为了方便访问网络或者获取服务器的资源,而封装出来的一个工具包。通常的使用步骤是:首先初始化一个OkHttpClient对象,然后使用builder模式构造一个Request,之后使用Call来执行这个Request。其中,OkHttpClient一般只使用一个,而OkHttpClient的newCall方法则对应每次请求的执行。

    二、Get

    2.1 步骤分解

    1. 拿到OkHttpClient对象
    2. 构造Request
    3. 将Request封装为Call
    4. 执行Call(直接execute或者enqueue)

    2.2 程序

         public void doGet(View view) throws IOException{
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url("http://www.imooc.com/").build();
            Call call = client.newCall(request);
            call.enqueue(new Callback(){
    
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.e("okHttp",e.getMessage());
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Log.d("okHttp","doGet success!");
                    String string = response.body().string();
                    Log.d("okHttp Content",string);
                }
                
            });
        }

    上面的enqueue也可以换成execute,不过执行后返回一个Response对象。

    相应代码替换成:

    Response response = call.execute();
    if(response.isSuccessful){
        return response.body().string();
    }else{
        throw new IOException("Unexpected code " + response);
    }

    三、Post键值对

    3.1 步骤分解

    1. 拿到OkHttpClient对象
    2. 构造RequestBody
    3. 构造Request
    4. 将Request封装为Call
    5. 执行Call

    3.2 代码

    public void doPost(View view){
        OkHttpClient client = new OkHttpClient();
        
        RequestBody body = new FormBody.Builder().builder()
                    .add("username","admin")
                    .add("password","123")
                    .build();
        Request.Builder builder = new Request.Builder();
        Request = builder.url(mBaseUrl+"login").post(body).build();
        
        Call call = client.newCall(request);
        call.enqueue(new Callback(){
    
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("okHttp",e.getMessage());
            }
    
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d("okHttp","doGet success!");
                String string = response.body().string();
                Log.d("okHttp Content",string);
            }
            
        });
    }

    Call那个步骤在多数程序中都会用到,所以最好是抽取成为一个函数。在服务器端使用的是struts2架构,因此需要添加一个action,在所需调用的函数中将username和password打印出来就能看到post上去的数据了。

    四、Post JSON(字符串)

    和上面的步骤唯一不同的是RequestBody的构造。这里使用的是RequestBody的静态方法create()。

    RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"),"{username:admin,password:123}");

    在服务器端的函数代码为:

    public String postString(){
        HttpServletRequest request = ServletActionContext.getRequest();
        ServletInputStream is = request.getInputStream();
        
        StringBuilder sb = new StringBuilder();
        int len = 0;
        byte[] buf = new byte[1024];
        
        while((len = is.read(buf)) != -1){
            sb.append(new String(buf, 0, len));
        }
        
        System.out.println(sb.toString());
        
        return null;
    }

    五、Post File

    参考上面的代码,这里构造RequestBody也是调用它的静态方法create(),只不过参数改成了跟File相适应的。

    重复代码已省去。至于MediaType参数,参考http://www.w3school.com.cn/media/media_mimeref.asp

    File file = new File(Environment.getExternalStorageDirectory(),"test.jpg");
    if(!file.exists()){
        Log.e("file error","not exist!");
        return;
    }
    RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"),file);

    服务器端的程序也和上面的程序大同小异,只不过改成用FileOutputStream来接受InputStream里面的数据,而不是上面的StringBuilder。

    public String postFile(){
        HttpServletRequest request = ServletActionContext.getRequest();
        ServletInputStream is = request.getInputStream();
        
        String dir 
    = ServletActionContext.getServletContext().getRealPath("files"
    );
        File file = new File(dir,"test.jpg");
        FileOutputStream fos = new FileOutputStream(file);
        int len = 0;
        byte[] buf = new byte[1024];
        
        while((len = is.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        
        fos.flush();
        fos.close();
        
        return null;
    }

    这里有个需要注意的地方,getRealPath得到的路径默认是tomcat下webapps中的项目文件夹下。因为每次重启服务器里面的文件都会被删除,所以我更改了路径:

    <Context path="/VCloud" docBase="D:WorkspaceVCloudDir" debug="0" reloadable="true"/>

    我把文件test.jpg放在D:WorkspaceVCloudDirfiles下,然后在浏览器中输入localhost:8080/VCloud/files/test.jpg就能打开这个文件。

    六、上传文件以及参数

    使用MultipartBody的意义在于:传输文件的同时可以传输字段;可以指定文件名;可以一次上传多个文件。

    代码仅展示RequestBody部分,其他部分和上面基本一致。

    File file = new File(Environment.getExternalStorageDirectory(),"test.jpg");
    RequestBody fileRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"),file);
    MultipartBody.Builder multipartBuilder = new MultipartBody.Builder();
    RequestBody body = multipartBuilder
                .type(MultipartBody.FORM)
                .addFormDataPart("username","admin")
                .addFormDataPart("password","123")
                .addFormDataPart("mPhoto","test.jpg",fileRequestBody)
                .build();

    服务端部分:

    public File mPhoto;
    public String mPhotoFileName;//注意写法是固定的
    public String uploadInfo(){
        
        if(mPhoto == null){
            System.out.println(mPhotoFileName + " is null .);
        }
        
        String dir = ServletActionContext.getServletContext().getRealPath("files");
        
        File file = new File(dir, mPhotoFileName);
        FileUtils.copyFile(mPhoto, file);
        
        return null;
    }

    七、下载文件

    和get方法类似,不同之处在于对得到的Response的处理,即onResponse里面的内容。

    url就是文件地址,如localhost:8080/VCloud/files/test.jpg。

    public void onResponse(Response response){
        Log.d("onResponse","onResponse");
        
        InputStream is = response.body().byteStream();
        int len = 0;
        File file = new File(Environment.getExternalStorageDirectory(),"test.jpg");
        byte[] buf = new byte[128];
        FileOutputStream fos = new FileOutputStream(file);
        
        while((len = is.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        
        fos.flush();
        fos.close();
        is.close();
        
        Log.d("download","download success!");
    }
  • 相关阅读:
    Go语言基础之结构体练习
    多对多表操作
    一对多表操作
    单表操作
    flask中orm增删改查操作
    基于scoped_session实现线程安全
    SQLAlchemy
    wtforms 表单使用
    记一次攻防演练复盘之计中计
    【漏洞复现】CVE-2021-22205 GitLab 未授权RCE
  • 原文地址:https://www.cnblogs.com/viaduct/p/6695104.html
Copyright © 2011-2022 走看看