0.前言
上面两篇文章,
讲解了网络中,底层的数据传输的原理(Socket)本文则着重讲解实际情况中,我们如何使用Java进行数据的传输(上传、下载等)
若想要了解“类”等其他主要知识,可以去看前面的文章
由于最终目的是要开发安卓app,
因此这里使用的IDE是AS(Android Studio)
(不会使用的可以参考下面这篇文章中的例子)
《[Java]开发安卓,你得掌握的Java知识2》
1.准备工作
在读本文前,你需要做好以下准备:
- (1)要配置好apache服务器
- (2)电脑中配置了php,可以写php代码
- (3)大致了解前后端交互
- (4)可以的话,最好去了解一下html的表单<form>
- 推荐新手使用wampserver 64,
它集成了php、apache、MYSQL数据库- 直接安装、运行wampserver 64,就可以免去配置php、apache的复杂操作。
![](https://img.haomeiwen.com/i18958864/76930afd736c0ab4.png)
2.基础知识讲解
![](https://img.haomeiwen.com/i18958864/f16b4b77bf5c62ed.jpg)
![](https://img.haomeiwen.com/i18958864/2c5dd2d66bd12fe4.png)
URL的一些奥秘
- url就是我们在地址栏输入的网址
一般我们可能只会注意到www.xxx.com这部分,
后面的内容,外行人可能以为是乱码- 其实,url的每一个部分都有它对应的意思,只是我们未必能知道而已
![](https://img.haomeiwen.com/i18958864/269830ffbd501c6e.png)
www.xxx.com这部分叫域名,其实是与ip地址有映射关系的字符串,我们>访问的所有网页,其实都是接入网络中的某台计算机中的内容(这些计算机一般叫做服务器)
域名后面的那些用斜杠隔开的,其实是对应的文件夹,我们访问的网页,就是ip地址所指向的计算机中,某个指定文件夹下面的某个html文件(当然可能是jsp什么的)
如果看到有?name=jack&age=12之类的格式,其实就是向对应的文件传参数,实际上就是在说:
name = jack , age = 12
把这两个参数传过去
![](https://img.haomeiwen.com/i18958864/269830ffbd501c6e.png)
比如这一点可以在微博中有一定作用
![]()
- is_hot=1表示按照微博的火热程度来排序
如果改成is_all=1,那么就会按照时间排序,这一点十分有用
![](https://img.haomeiwen.com/i18958864/269830ffbd501c6e.png)
Get与Post
- get与post是两种传递数据的方式,他们最主要的区别在于:
get:
①传递的数据会出现在地址栏中(就是上面所说的?name=jack&age=12)
②传递的数据不能太多
③由于数据会出现在地址栏,因此不安全
④虽然不安全,但是我们可以通过修改地址栏的参数传递,来改变一些东西(比如上面微博的那个例子is_all与is_hot)post:
①传递的数据不会出现在地址栏中
②由于数据不会出现在地址栏,因此安全
③可以一次传递大量数据
④代码编写比get方法略微复杂一点
![](https://img.haomeiwen.com/i18958864/269830ffbd501c6e.png)
PHP简单语法:
变量的定义:
$name = "jack"
输出/返回内容:
echo $name;
或者echo "jack"
等变量的获取:
$age = $_GET["age"];
注意:
-
这里的GET表示是用GET方法传递数据,因此要用$_GET来获取穿过来的数据
-
"age"是传递数据的时候指定的名字,如果是用html传递的话,就是写在标签中的name(这个name是标签的一个参数)
<input type="text" name="age">
![](https://img.haomeiwen.com/i18958864/f78a4cf07f3619f7.png)
3.具体实现方法
本文会wampserver64来使用php、apache服务器
第一步
先写一个php文件,来作为接受、返回数据
<?php
$name = $_POST["fname"];
$age = $_POST["age"];
echo $name." ".$age."岁";
?>
- 简单来说就是定义了两个变量
age
然后返回
$name $age岁
第二步
把这个php文件放在wamp64\www下面
www是wampserver这个集成软件的根目录
默认的apache服务器的根目录在htdocs
![]()
![](https://img.haomeiwen.com/i18958864/3a43e57769dc70ab.png)
第三步
在java程序中书写传递数据的函数
(我知道代码很长很吓人,代码后面会有逐句分析)
public static void post() throws IOException {
//1.创建URL对象
URL url = new URL("http://127.0.0.1/AndroidTest/test1.5.php");
//2.创建HttpURLConnection对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//3.设置请求方式为post
connection.setRequestMethod("POST");
//设置有输出流(说明需要上传,默认值为false)
connection.setDoOutput(true);
//设置输入流,默认为true(服务器肯定会返回数据
connection.setDoInput(true);
//4.准备上传的数据
String data = "fname=jack&age=12";
//5.开始上传 要得到输出流对象(不断向服务器输出)
OutputStream os = connection.getOutputStream();
//data是字符串,要转换为字节
os.write(data.getBytes());
os.flush();//写完了
//6,接收服务器端返回的数据
InputStream is = connection.getInputStream();
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) != -1) {
System.out.println(new String(buf,0,len));
}
}
POST请求方式
首先,我们实际用java在网络中传递数据,不会像之前那样直接用Socket,原因是:
Socket有局限性,我们只能在Socket中放ip地址和端口,但是
无法让socket知道访问该ip地址中的哪个文件所以我们用的是封装了Socket的URL类来实现数据传递,
URL的构造参数中放的是欲访问的网址使用HTTPURLConnection的原因是要设置请求方式和输出流
因为请求方式默认为GET,所以post才需要设置请求方式String data就是想要发送给指定文件的内容,虽然是post方式,但是也是要按照类似get方式来写(只是开头没有?)
输出流用的是字节流OutputStream,
getBytes()可以将字符串变为字节数组读取返回的内容用的是InputStream,InputStream后面几行都是常规操作,如果不熟悉的可以去看之前的文章:
《[Java]开发安卓,你得掌握的Java知识9》
执行结果:(要找一个main函数调用post())
![](https://img.haomeiwen.com/i18958864/66b757ea5a5dd4ec.png)
![](https://img.haomeiwen.com/i18958864/b42454cb48e520f0.png)
GET请求方式
java代码差不多(要简单一些):
public static void getParams() throws IOException {
String path = "http://127.0.0.1/AndroidTest/test.php?fname=jack&age=12";
URL url = new URL(path);
//1.5.指明请求方式,默认为get
//2.获取连接的对象(URLConnection封装了socket,socket可以做的,URLConnection都可以做)
URLConnection connection = url.openConnection();
//接受服务器端的数据
InputStream is = connection.getInputStream();
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) != -1) {
System.out.println(new String(buf,0,len));
}
}
主要区别在于:
将要传递的数据放到了path中,不需要额外传数据
不需要去设置请求方式
php文件中的 _POST要改为_GET
![](https://img.haomeiwen.com/i18958864/b42454cb48e520f0.png)
传递文件
public static void getImage() throws IOException {
//URL
URL url = new URL("http://localhost/1.jpg");
//获取与服务器连接的对象
URLConnection connection = url.openConnection();
//读取下载的内容 - 获取输入流
InputStream is = connection.getInputStream();
//创建文件保存的位置,路径自己定义
String desPath ="D:\\AndroidStudioProjects\\AndroidCourse\\JavaCourse1Day1\\course1day1\\src\\main\\java\\course1day14\\1.jpg";
FileOutputStream fos = new FileOutputStream(desPath);
//具体的下载操作
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) != -1) {
fos.write(buf,0,len);
}
}
- URL、URLConnection的操作和上面的POST、GET一样
-下面的InputStream到最后的while那部分代码,
就是经典的文件的拷贝,先用InputStream读取文件到缓存,再用FileOutputStream将文件从缓存中读出
只不过这次是从服务器中把文件拷贝到本地
- byte[]是字节数组,新手可能没见过,它的目的就是在读取文件时,找一个地方放你要读取到的东西的一部分,然后将这次读到的内容写到硬盘中,要反复多次这样的操作,直至将整个文件拷贝完
(当然,每次读写的单位还是一个字节,只是字节数组能一次性放下1024个字节而已)
![](https://img.haomeiwen.com/i18958864/c9605d98296f3eec.png)
4.总结
(1)本文讲解了实际情况中,如何实现网络中的数据传递,比起使用底层的socket进行交互,封装好的URL更加方便
(2)虽然访问服务器可以使用URL这种封装好的类,但是数据的读写依然要使用InputStream和OutputStream这些类,因此即使看起来很复杂,也有必要多多熟悉字节、字符输入输出流的使用方法
网友评论