A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小鲁哥哥 于 2016-11-21 13:29 编辑

【济南中心】Android课程同步笔记day05:Android应用开发基础

Get和Post请求:

在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。

优缺点:

* GET请求
> 优点:使用非常方便,只需要在url后面组拼数据.
> 缺点:数据在url的后面组拼,不安全. 有数据长度限制.
* POST请求
> 优点: 安全,数据不是在url后面组拼而是通过流的方式写给服务器.数据长度不受限制
> 缺点: 编写麻烦.

关于数据提交:

get请求:需要在url后面组拼提交的数据。

post请求:

1. 不需要组拼任何的数据  
2. 必须指定请求的数据类型,是一个经过url编码的表单数据。Content-Type  
3. 以流的方式把数据写给服务器,所以必须指定提交数据的长度。Content-Length


GET方式提交数据:

[Java] 纯文本查看 复制代码
new Thread(){
                public void run() {
                        try {
                                //GET请求方式的特点:在url后面组拼数据
                                String path = "http://192.168.1.103:8080/web/LoginServlet?qq="+qq+"&pwd="+pwd);
                                URL url = new URL(path);
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                conn.setRequestMethod("GET");
                                conn.setConnectTimeout(5000);
                                int code = conn.getResponseCode();
                                if(code == 200){
                                        InputStream is = conn.getInputStream();
                                        String result = StreamTools.readStream(is);
                                        Message msg = Message.obtain();
                                        msg.what = SUCCESS;
                                        msg.obj = result;
                                        handler.sendMessage(msg);
                                }else{
                                        Message msg = Message.obtain();
                                        msg.what = ERROR;
                                        handler.sendMessage(msg);
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
                                Message msg = Message.obtain();
                                msg.what = ERROR;
                                handler.sendMessage(msg);
                        }
                };
        }.start();

POST提交数据:

[Java] 纯文本查看 复制代码
new Thread(){
                public void run() {
                        //路径不需要组拼
                        String path = "http://192.168.1.103:8080/web/LoginServlet";
                        try {
                                URL url = new URL(path);
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                //1.设置请求方式为POST
                                conn.setRequestMethod("POST"); //注意单词必须大写.
                                conn.setConnectTimeout(5000);
                                //2.设置http请求数据的类型为表单类型
                                conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                                //3.设置给服务器写的数据的长度
                                //qq=10000&pwd=abcde
                                String data = "qq="+qq+"&pwd="+pwd;
                                conn.setRequestProperty("Content-Length", String.valueOf(data.length()));
                                //4.记得指定要给服务器写数据
                                conn.setDoOutput(true);
                                //5.开始向服务器写数据
                                conn.getOutputStream().write(data.getBytes());
                                int code = conn.getResponseCode();
                                if(code == 200){
                                        InputStream is = conn.getInputStream();
                                        String result = StreamTools.readStream(is);
                                        Message msg = Message.obtain();
                                        msg.what = SUCCESS;
                                        msg.obj = result;
                                        handler.sendMessage(msg);
                                }else{
                                        Message msg = Message.obtain();
                                        msg.what = ERROR;
                                        handler.sendMessage(msg);
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
                                Message msg = Message.obtain();
                                msg.what = ERROR;
                                handler.sendMessage(msg);
                        }
                };
        }.start();

Tomcat默认码表
1. Tomcat默认码表iso-8859-1
2. Tomcat如果发现字符串不识别,就默认采用本地码表

GB2312和GBK(了解)
GB2312
1980年发布,标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时,GB2312收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。  
GB 2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。  
对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这导致了后来GBK及GB18030汉字字符集的出现。  
GBK
1995年发布,是在GB2312-80标准基础上的内码扩展规范,共收录了21003个汉字,完全兼容GB2312-80标准。

string.getBytes(String charsetName)和new String(byte[] bytes, String charsetName)(重要)
1. byte[] bytes = string.getBytes(String charsetName)  
将字符串按指定的编码转化为byte数组,默认采用本地码表
2. new String(byte[] bytes, String charsetName)  
将byte数组按指定的编码转化为字符串
**注意:**出现乱码时不要修改文件,修改后无论怎么切换编码都是错的了

提交数据中含有中文的注意事项
客户端:
    //提交的数据中含有中文时,将字符串qq按照编码UTF-8进行编码
    URLEncoder.encode(qq, "UTF-8");

服务端:
    String qq = request.getParameter("qq");//tomcat采用的编码是iso-8859-1
    System.out.println("qq:"+new String(qq.getBytes("iso-8859-1"),"utf-8"));

HttpClient
轻量级的浏览器,将请求和响应都封装成了对象
1. 打开浏览器
2. 输入地址(数据)
3. 敲回车

HttpClient的GET和POST请求:

GET请求:

[Java] 纯文本查看 复制代码
new Thread(){
                public void run() {
                        try {
                                String path = "http://192.168.1.103:8080/web/LoginServlet?qq="+URLEncoder.encode(qq, "utf-8")+"&pwd="+URLEncoder.encode(pwd, "utf-8");
                                //1.打开浏览器
                                HttpClient client = new DefaultHttpClient();
                                //2.输入地址或者数据
                                HttpGet httpGet = new HttpGet(path);
                                //3.敲回车
                                HttpResponse response = client.execute(httpGet);
                                //获取状态码
                                int code = response.getStatusLine().getStatusCode();
                                if(code == 200){
                                        InputStream is = response.getEntity().getContent();
                                        String result = StreamTools.readStream(is);
                                        Message msg = Message.obtain();
                                        msg.what = SUCCESS;
                                        msg.obj = result;
                                        handler.sendMessage(msg);
                                }else{
                                        Message msg = Message.obtain();
                                        msg.what = ERROR;
                                        handler.sendMessage(msg);
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
                                Message msg = Message.obtain();
                                msg.what = ERROR;
                                handler.sendMessage(msg);
                        }
                };
        }.start();

POST请求:

[Java] 纯文本查看 复制代码
new Thread(){
                public void run() {
                        try {
                                String path = "http://192.168.1.103:8080/web/LoginServlet";
                                //1.打开浏览器
                                HttpClient client = new DefaultHttpClient();
                                //2.输入地址或者数据
                                HttpPost httpPost = new HttpPost(path);
                                List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                                parameters.add(new BasicNameValuePair("qq", qq));
                                parameters.add(new BasicNameValuePair("pwd", pwd));
                                httpPost.setEntity(new UrlEncodedFormEntity(parameters, "utf-8"));
                                //3.敲回车
                                HttpResponse response = client.execute(httpPost);
                                //获取状态码
                                int code = response.getStatusLine().getStatusCode();
                                if(code == 200){
                                        InputStream is = response.getEntity().getContent();
                                        String result = StreamTools.readStream(is);
                                        Message msg = Message.obtain();
                                        msg.what = SUCCESS;
                                        msg.obj = result;
                                        handler.sendMessage(msg);
                                }else{
                                        Message msg = Message.obtain();
                                        msg.what = ERROR;
                                        handler.sendMessage(msg);
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
                                Message msg = Message.obtain();
                                msg.what = ERROR;
                                handler.sendMessage(msg);
                        }
                };
        }.start();

async-http开源框架的GET请求:

[Java] 纯文本查看 复制代码
        String path = "http://192.168.1.103:8080/web/LoginServlet?qq="+URLEncoder.encode(qq)+"&pwd="+URLEncoder.encode(pwd);
        AsyncHttpClient client = new AsyncHttpClient();
        client.get(path, new AsyncHttpResponseHandler() {

                //请求成功的回调
                @Override
                public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                        tv_status.setText(new String(responseBody));
                }

                //请求失败的回调
                @Override
                public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                        tv_status.setText("http请求失败"+new String(responseBody));
                }

        });

async-http开源框架的POST请求:

[Java] 纯文本查看 复制代码
        String path = "http://192.168.1.103:8080/web/LoginServlet";
        AsyncHttpClient client = new AsyncHttpClient();
        RequestParams params = new RequestParams();
        params.put("qq", qq);
        params.put("pwd", pwd);
        client.post(path, params, new AsyncHttpResponseHandler(){

                //请求成功的回调
                @Override
                public void onSuccess(int statusCode, Header[] headers,
                                byte[] responseBody) {
                        tv_status.setText("登陆结果:"+new String(responseBody));
                }

                //请求失败的回调
                @Override
                public void onFailure(int statusCode, Header[] headers,
                                byte[] responseBody, Throwable error) {
                        tv_status.setText("请求失败请检查网络");
                }

        });

async-http开源框架的文件上传:

1. 文件上传的原理
    * 文件上传其实就是一个POST请求
    * Content-Type为multipart/form-data

具体实现代码:

[Java] 纯文本查看 复制代码
AsyncHttpClient client = new AsyncHttpClient();
                RequestParams params = new RequestParams();
                try {
                        params.put("file", file);
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                }
                client.post("http://192.168.1.103:8080/web/UploadServlet", params, new AsyncHttpResponseHandler() {
        
                        @Override
                        public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                                Toast.makeText(MainActivity.this, "上传成功", 0).show();
                        }
                        
                        @Override
                        public void onFailure(int statusCode, Header[] headers,
                                        byte[] responseBody, Throwable error) {
                                Toast.makeText(MainActivity.this, "上传失败", 0).show();
                        }
        
                });

多线程下载
* 多线程并发操作
* 网络请求

实现原理:

(1)首先获得下载文件的长度,然后设置本地文件的长度。

(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。

为什么多线程可以提高下载的速度
* 从服务器上获取的资源变多了,单位时间内下载的速度就变快.
* 下载速度还受到服务器上传带宽和用户的下载带宽限制
多线程下载的步骤
1. 在客户端本地创建一个空白文件,文件的大小跟服务器的一模一样。RandomAccessFile
2. 开启若干个线程去下载服务器的资源
3. 当所有线程都下载完毕,多线程下载就结束了


如何划分服务器的资源给不同的线程:

[Java] 纯文本查看 复制代码
        int length = conn.getContentLength(); //总长度
        int blocksize = length / threadCount; //前(n-1)个线程下载的数据量
        for (int threadId = 0; threadId < threadCount; threadId++) {
                int startIndex = threadId * blocksize;
                int endIndex = (threadId + 1) * blocksize - 1;
                if (threadId == (threadCount - 1)) {
                        endIndex = length - 1;
                }
        }

多线程下载文件:

[Java] 纯文本查看 复制代码
        //1.在客户端本地创建一个空白文件,文件的大小跟服务器的一模一样
        RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
        raf.setLength(length);
        raf.close();
        
        //2.确定每个线程获取数据的“开始位置”和“结束位置”
        int length = conn.getContentLength(); //总长度
        int blocksize = length / threadCount; //前(n-1)个线程下载的数据量
        for (int threadId = 0; threadId < threadCount; threadId++) {
                int startIndex = threadId * blocksize;
                int endIndex = (threadId + 1) * blocksize - 1;
                if (threadId == (threadCount - 1)) {
                        endIndex = length - 1;
                }
                new DownloadThread(threadId, startIndex, endIndex).start();
        }

        //3.第i个线程只取服务器中的某一段数据
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
        InputStream is = conn.getInputStream();

        //4.第i个线程取回数据后,从某个位置开始写入数据
        RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
        raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.

断点续传的原理
记录每个线程的下载进度,下次再下载的时候从该位置开始下载

多线程断点下载的小细节
1. 每个下载任务都需要自己的记录进度的文件
2. 都下载完后删除记录文件
3. 保证同步使用synchronize代码块
4. 使用FileOutputStream数据不一定每一次都写到存储设备里,有可能写到硬盘的缓存里,使用RandomAccessFile将模式设置为rwd,可以保证每次都将数据写到磁盘里

使用xUtils完成多线程断点下载

[Java] 纯文本查看 复制代码
        HttpUtils http = new HttpUtils();
        //第一个参数:服务器地址
        //第二个参数:要下载到哪里
        //是否断点续传
        //下载的一些回调函数
        http.download(path, "/mnt/sdcard/xxx.exe", true, new RequestCallBack<File>() {
                
                //下载成功的回调
                @Override
                public void onSuccess(ResponseInfo<File> arg0) {
                        Toast.makeText(MainActivity.this, "下载成功", 0).show();
                }
                
                //进度更新的回调
                @Override
                public void onLoading(long total, long current, boolean isUploading) {
                        pb0.setMax((int) total);
                        pb0.setProgress((int) current);
                        super.onLoading(total, current, isUploading);
                }

                //下载失败的回调
                @Override
                public void onFailure(HttpException arg0, String arg1) {
                        Toast.makeText(MainActivity.this, "下载失败"+arg1, 0).show();
                }

        });





39 个回复

倒序浏览

回帖奖励 +1

总结的很不错,学习下!!!
回复 使用道具 举报
总结的都是精华!
回复 使用道具 举报
我想问下我看到的只有5,以前的1234那?感谢分享
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
sigod 中级黑马 2016-12-11 21:12:37
7#
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
唉呀,走错了,想学ee的。

来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
看着技术含量很高的样子了
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
回复 使用道具 举报
谢谢分享,好好学习。
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
回复 使用道具 举报
谢谢分享 赞赞赞!!!!!
回复 使用道具 举报
谢谢分享,一定好好学
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
楼主好人,一生平安。
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马