Java网络编程总结
java网络编程
http协议原理
协议
网络协议的简称,计算机遵守这个协议才能交流,主要有http和https两种
- 区别
url
地址栏输入的地址就叫做url,英文全称Uniform Resource Locator
- 格式规范
协议类型://域名/路径/?参数
多个参数之间用&分隔,参数用键值对表示key=value
和Windows文件路径\分割符不一样
- 端口号
域名后的:443表示端口号
因为http默认端口号为80,https默认端口号443,默认的端口号可以省略,其他的要写
- 路径
相对路径
不是以/开头的路径表示相对路径,以/开头的为绝对路径
不输入路径打开的是默认路径
简单api调用
get请求无参数
安装依赖库okhttp3
-
安装方式,在pom.xml增加依赖
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.1.0</version> </dependency>
使用okhttp3完成页面请求
-
实例化
OkHttpClient okHttpClient = new OkHttpClient();
-
执行调用
调用之前先实例化一个requestRequest request = new Request.Builder().url(url).build();
构建调用对象
Call call = okHttpClient.newCall(request);
最后执行调用
call.execute()返回的是一个执行的结果的对象,需要转换成字符串
call.execute().body().string();
api
api是应用程序接口,是预先定义的函数
url本质上就是api
get请求有参数
只需把有参数的url直接传入方法中即可
post表单
提交数据至服务器进行增加,删除,修改操作都是post
post操作数据放在表单中,不是url
-
创建表单对象FormBody
Builder builder = new FormBody.Builder(); // 设置数据,第一个参数是数据名,第二个参数是数据值 builder.add("", ""); FormBody formBody = builder.build(); Request request = new Request.Builder().url(url).post(formBody).build();
构建Request对象时用.post(formbody),与api不同
用for循环添加表单数据
for(String key:formData.keySet())
{builder.add(key,formDate.get(key));}
post json数据
post的参数不是formbody,改为requestbody
FastJson依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
-
先定义一个最终提交的常量数据
pravite static final MediaType JSON_TYPE = MediaType.parse("application/json;charset=utf-8");
utf-8是码表,查询
response 网页
除了返回值,还经常关注http状态码
常见状态码200表示成功,404表示出错
取得状态码的代码
call.execute().code()
但是即要读取相应内容,又要读取状态,而且不是再次请求,那么代码应该优化为
import okhttp3.Response;
// 执行请求
Response rep = call.execute();
// 获取响应状态码
int code = rep.code();
// 获取响应内容
String content = rep.body().string();
就是将原本的call.excute()保存为一次结果,再获取其中的内容
response 非文本文件
非文本文件获取不是用string()方法,而是用
response.body().bytes();
返回二进制编码,再用软件解析
response json
json是一段文本,也就是java的字符串,要解析内容需转换为java对象
JSON.parseObject()
解析json对象
普通的直接转换,遇到多次嵌套的
{
"code": 0,
"data": {
"ip": "117.89.35.58",
"country": "中国",
"area": "",
"region": "江苏",
"city": "南京",
"county": "XX",
"isp": "电信",
"country_id": "CN",
"area_id": "",
"region_id": "320000",
"city_id": "320100",
"county_id": "xx",
"isp_id": "100017"
}
}
就转换后取出内部的再转换
Map contentObj = JSON.parseObject(content, Map.class);
Map dataObj = (Map)contentObj.get("data");
String city = (String)dataObj.get("city");
user-agent
有时网站的会未成功,因为网站会校验是否是真实的浏览器发出的请求,api服务器认为不是真实的浏览器
-
判断是否是真实的浏览器,需要从HTTP消息头(Headers)中取得(User-Agent)
HTTP Headers文档代码中加上User-Agent信息来模拟真实浏览器发出的请求
-
模拟win7 + chrome:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1 -
加入header信息
Request request = new Request.Builder() .url(url) .addHeader("User-Agent", "") .build();
addheader第一个参数是名称,第二个参数是值
referer
图片防盗链
在headers中加入referer信息
在浏览器能访问是因为没有了“来源”
-
加入referer
Request request = new Request.Builder() .url(url) .addHeader("Referer", "https://ham.youkeda.com/course/j14/0") .build();
可把referer的信息设置为本站的信息(相同的域名)
有时图片请求的相应码为200,表示请求成功,但是最终相应地址却不一样,是因为服务器判断没有权限访问,做了特殊处理
host
host也是headers的信息之一
host表示当前请求的域名,虽然域名有时已经存在于url中,但是使用代理服务器或者url中不写域名而是写ip地址请求时,设置host就很有用
具体的host文档
-
设置Host
Request request = new Request.Builder() .url(url) .addHeader("Host", "www.douban.com") .build();
host的值是不带协议的域名
下载文件
写入文本文件
import java.io.File;
import java.io.FileWriter;
// 文件对象
File file = new File("foo.txt");
// 写入内容
FileWriter fileWritter = new FileWriter(file.getName());
fileWritter.write(content);
// 关闭
fileWritter.close();
写入二进制文件
import java.io.File;
import java.io.FileOutputStream;
// 文件对象
File file = new File("china-city-list.xlsx");
// 写文件
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
// 必须刷新并关闭
fos.flush();
fos.close();
需要用FileOutputStream类,必须执行刷新,关闭
data 是byte[]类型
解析excel
-
easyexecl是能快速操作excel文件的库
要先添加依赖<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version> </dependency>
excel是多sheet的模式,所以数据的位置是sheet->行->列
电脑中第一个sheet第一行第一列的位置是(0,0,0)
解析代码
import com.alibaba.excel.EasyExcel;
import java.util.Map;
import java.util.List;
// 读取第一个sheet
List<Map<Integer, String>> sheetDatas = EasyExcel.read("xzq_201907.xlsx").sheet(0).doReadSync();
// List 中每个元素表示一行
for (Map<Integer, String> rowData : sheetDatas) {
// Map 中用序号指代每一列
for (Integer index : rowData.keySet()) {
// 列值
String columnValue = rowData.get(index);
}
}
- 自动转换为类
如果每一行的含义不清楚,或其他情况,或其类型经常变化的的话,用Map类型表示每一行
但是如果知道每一行的含义,用自定义类比较好
import com.alibaba.excel.EasyExcel;
import java.util.List;
// 读取第一个sheet
List<DemoData> sheetDatas = EasyExcel.read("xzq_201907.xlsx").head(DemoData.class).sheet(0).doReadSync();
// 属性定义的顺序必须与列顺序保持一致
public class DemoData {
private String code1;
private String city1;
private String code2;
private String city2;
private String code3;
private String city3;
}
EasyExcel.XXXXXX.doReadSync()无论是什么类型,返回的都是list类型
cookie
如果文件或者网站要求登录才能访问,就要学习cookie的知识
cookie是储存在浏览器网站的一段文本文件,以key=value形式存放,多条数据之间用;隔开
准备 先找到登录后的cookie
复制cookie的值,然后用addHeader赋值给cookie
如果返回值404,是因为cookie是有有效期的
session
cookie的弊端是cookie是临时的,要登录再获取相关信息,可以用session来解决这个问题
// 用 CookieJar 实现 cookie 的存储,便于登录后请求其它 URL 可以复用
private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put("mtime.com", cookies);
System.out.println("[saveFromResponse]url.host()=" + url.host());
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
System.out.println("[loadForRequest]url.host()=" + url.host());
List<Cookie> cookies = cookieStore.get("mtime.com");
return cookies != null ? cookies : new ArrayList<>();
}
})
.build();
在login.api中找信息,有name和password
复用session
讲okHttpClient进行重构,不再定义为变量,改为类变量
private static final OkHttpClient okHttpClient
SMTP
SMPT是一个简单的基于文本的文件传输协议,在这个协议可以指定一条消息和一个或多个邮件接收者,然后进行邮件传输。
和HTTP协议类似,
协议+服务器地址 就组成一个邮件访问方式,比如:
qq邮箱: smtp.qq.com
163邮箱: smtp.163.com
JavaMail依赖
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
邮箱发送代码
import java.security.Security;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class MailClient {
public static void main(String[] args) {
try {
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
//配置邮箱信息
Properties props = System.getProperties();
//邮件服务器
props.setProperty("mail.smtp.host", "smtp.qq.com");
props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.smtp.socketFactory.fallback", "false");
//邮件服务器端口
props.setProperty("mail.smtp.port", "465");
props.setProperty("mail.smtp.socketFactory.port", "465");
//鉴权信息
props.setProperty("mail.smtp.auth", "true");
//建立邮件会话
Session session = Session.getDefaultInstance(props, new Authenticator() {
//身份认证
protected PasswordAuthentication getPasswordAuthentication() {
//1.账户 授权码
return new PasswordAuthentication("xxxxxxx@qq.com", "xxxx");
}
});
//建立邮件对象
MimeMessage message = new MimeMessage(session);
//设置邮件的发件人
message.setFrom(new InternetAddress("xxxxxxx@qq.com"));
//2.设置邮件的收件人,可多个,用逗号隔开
message.setRecipients(Message.RecipientType.TO, "xxxxxxx@qq.com");
//设置邮件的主题
message.setSubject("通过javamail发出!!!");
//文本部分
message.setContent("文本邮件测试", "text/html;charset=UTF-8");
message.saveChanges();
//发送邮件
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
固定用法,只需修改邮箱配置
posted on 2022-04-27 20:54 RicardoSimple 阅读(41) 评论(0) 编辑 收藏 举报