Java网络编程(自己在学习的一些路线)

tech2022-07-31  146

Java网络编程

1. 协议与URL

这个可以参考我在python写的相关文档。

2. maven

Maven 是一个项目管理和构建自动化工具。但是对于我们程序员来说,我们最关心的是它的项目构建功能。所以这里我们介绍的就是怎样用 Maven 来满足我们项目的日常需要。

Maven 提供了一个命令行工具可以把工程打包成 Java 支持的格式(比如 jar),并且支持部署到中央仓库里,这样使用者只需要通过工具就可以很快捷的运用其他人写的代码,只需要你添加依赖即可

想要使用 Maven 这个工具,是要在命令行(终端软件)里输入指令的方式来执行的,我们需要大家了解几个常用的命令,注意命令要在工程的根目录下执行哦

mvn clean compile

编译命令,Maven 会自动扫描 src/main/java 下的代码并完成编译工作,执行完,会在根目录下生成 target/classes 目录(存放所有的 class)

mvn clean package

编译并打包命令,这个命令是 compile 和 package 的集合,也就是说会先执行 compile 命令,然后在执行 jar 打包命令,这个的结果会把所有的 java 文件和资源打包成一个jar,jar 是 java 的一个压缩格式,方便我们灵活的运用多个代码

mvn clean install

执行安装命令,这个命令是 compile 和 package、install 的集合,也就是说会先执行 compile 命令,然后在执行 jar 打包命令,然后执行 install 命令安装到本地的 Maven 仓库目录里。

这五个概念都会运用在 Maven 的配置文件中。Maven 的配置文件是一个强约定的XML格式文件。

初学者可能会记不住这么多属性,没有关系,可以随时开启编程的无敌模式:拷贝、粘贴,照葫芦画瓢即可。

我们来看一些相关:

一个 Java 项目所有的配置都放置在 POM 文件中,大概有如下的行为:

定义项目类型与名字;

管理依赖关系;

定制插件;

我们简单看看。

我们发现有这样的东西:

maven坐标

maven工程属性

maven依赖

maven插件

补充介绍一下,XML 格式可能是我们第一次接触,其实 HTML 语言也是 XML 格式,不过 XML 格式会严格遵守标记语言的要求,那就是有开始标签和结束标签,比如 <version>1.0</version>,我们在自定义 pom.xml 时候,如果没有写完整的开始、结束标签,那就会出错,这里我们就不详细展开了,大家多看几次也就了解啦。

maven坐标

<groupId>com.youkeda.course</groupId> <artifactId>app</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version>

这四个标签组成了 Maven 的坐标,所谓坐标就是一种位置信息,Maven 的坐标决定了这个 Maven 工程部署后存在 Maven 仓库的文件位置,所以这个坐标信息是必须要指定的。

这个再我们搭建maven时就已经确定了。

groupId

groupId 就像一个文件夹一样,它的命名和 Java 的包比较一致,这里一般只用小写的英文字母和字符.,比如这里的com.youkeda.course。一般来说一个公司会设置自己的 groupId,避免和其他公司重合,个人开发者也一样。

artifactId

artifactId 有点像文件名一样,在一个 groupId 内,它应该是唯一的,你不能使用中文或者特殊字符,从规范上来说只能使用小写的英文字母、.、-、_。比如:app、member.shared 这些都可以

packaging

Maven 工程执行完后会把整个工程打包成packaging指定的文件格式,默认情况下packaging的值是jar,所以如果pom.xml文件中没有声明这个标签,那就是 jar

packaging 有如下的几种格式

jar,war,ear,pom

大部分情况我们都是使用jar包

version

顾名思义,就是版本。在 Maven 的世界里,会把一个工程分为两个状态,这也是软件工程里最最常用的规范。

SNAPSHOT 这个单词翻译过来的意思是快照,实际上代表了当前程序还处于不稳定的阶段,随时可以再修改,所以在我们开发的时候我们会在版本号后面加上SNAPSHOT关键字

属性配置:

<properties> <java.version>1.8</java.version> <maven.compiler.source>${java.version}</maven.compiler.source> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>${java.version}</maven.compiler.target> </properties>

首先它的格式是在properties 标签内,这个是固定的格式。properties内的标签可以自定义,但是一般来说只能是小写英文字母+.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kUMQ5kyf-1599051627101)(D:\南京邮电大学文件\南京咪珠软件编辑部分\编程学习笔记\Java\image-20200831160330566.png)]

依赖管理:

dependency 就是用于指定当前工程依赖其他代码库的,Maven 会自动管理 jar 依赖

一旦我们在 pom.xml 里声明了 dependency 信息,会先去本地用户目录下的.m2文件夹内查找对应的文件,如果没有找到那么就会触发从中央仓库下载行为,下载完会存在本地的.m2文件夹内

请注意,一个 pom.xml 只能存在一个 dependencies 标签,可以有多个 dependency,因为我们很有可能依赖多个库

大家仔细观察这个dependency标签,你会发现dependency标签的内容其实就是 Maven 坐标,所以说只要有坐标我们就可以建立依赖

一般我们会把别人写的代码库称为三方库,自己、团队写的称为二方库,这个概念请大家记住,以后我们可能会这样描述内容的

中央仓库:我们很多jar包在中央仓库里,但是我们要通过阿里云来访问:

间接依赖:间接依赖是 mvn 成功的核心要素,简单的来说,如果一个remote工程依赖了 okhttp 库,而当前工程locale依赖了 remote工程,这个时候locale工程也会自动依赖了 okhttp

插件体系:

插件体系让 Maven 这个工具变得高度可定制,所以可以无缝的支撑工程化能力。现在只要了解插件的格式就可以啦,因为不同的插件有不同的作用。

<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> </plugin> </plugins> </build>

插件用于执行 maven compile 的,你会发现 maven 的插件其实也是存放在中央仓库的坐标,也就是一切都是 jar。

3. 网络编程相关请求

3.1 get请求

在进行写之前,我们需要进行依赖注入。

我们增加的是这样的一个库:okhttp3

我们这么添加依赖:

<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.1.0</version> </dependency>

使用 Okhttp3 完成页面请求,需要三大步骤:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fE9stgu9-1599051627104)(D:\南京邮电大学文件\南京咪珠软件编辑部分\编程学习笔记\Java\image-20200831161738833.png)]

固定写法,不用记。

输出结果:call.execute().body().string();可以取得服务器返回的具体内容。在下一章我们会详细学习,这里大家知道用法即可。

以我们学校的网络为例:

package html; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import java.io.IOException; public class GetPage { public String getContent(String url){ OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); Call call = okHttpClient.newCall(request); String result = null; try{ result = call.execute().body().string(); }catch (IOException e){ System.out.println("Error"); e.printStackTrace(); } return result; } public static void main(String[] args) { GetPage getPage = new GetPage(); String url = "http://www.njupt.edu.cn/mainm.htm"; String content = getPage.getContent(url); System.out.println(content); } }

我们解析出来了相关的页面html文档。

包含参数的话就全部复制过来就可以了。

3.2 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();

数据的写法是不是很眼熟呢?整体步骤跟请求 API 相似,不同的是,在构建 Request 对象时,使用 .post(formBody) 语句放入表单对象,就表示执行 POST 操作啦。

我们看一个例子:

package html; import java.io.IOException; import java.util.Map; import java.util.HashMap; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.FormBody; import okhttp3.FormBody.Builder; public class Phone { public String postContent(String url, Map<String, String> formData) { // okHttpClient 实例 OkHttpClient okHttpClient = new OkHttpClient(); //post方式提交的数据 Builder builder = new FormBody.Builder(); // 放入表单数据 for (String key : formData.keySet()) { builder.add(key, formData.get(key)); } // 构建 FormBody 对象 FormBody formBody = builder.build(); // 指定 post 方式提交FormBody Request request = new Request.Builder().url(url).post(formBody).build(); // 使用client去请求 Call call = okHttpClient.newCall(request); // 返回结果字符串 String result = null; try { // 获得返回结果 result = call.execute().body().string(); } catch (IOException e) { // 抓取异常 System.out.println("request " + url + " error . "); e.printStackTrace(); } return result; } public static void main(String[] args) { String url = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm"; Map<String, String> formData = new HashMap(); formData.put("tel","15850558521"); Phone poster = new Phone(); String content = poster.postContent(url, formData); System.out.println("API调用结果"); System.out.println(content); } }

3.3 post的json数据

我们仍然调用post方法,但是不是FormBody,而是RequestBody

将数据转换成 JSON 格式的字符串,调用 JSON.toJSONString() 方法即可。

创建 RequestBody 实例,注意需要指定提交的类型是 application/json; charset=utf-8 。这里的 utf-8 是 API 规定的编码格式。

构建 Request 实例对象时,调用 .post(requestBody) 即表示使用 JSON 的方式提交数据。

基本上是固定写法。

我们又要注入依赖了。

<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency>

我解析了小阿七,源码在这里:

package html; import com.alibaba.fastjson.JSON; import java.io.IOException; import java.util.HashMap; import java.util.Map; import okhttp3.Call; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; public class JsonPoster { public static final MediaType Json_type = MediaType.parse("application/json; charset=utf-8"); public String postContent(String url,Map<String,String> data){ String result = null; OkHttpClient okHttpClient = new OkHttpClient(); String param = JSON.toJSONString(data); RequestBody requestBody = RequestBody.create(Json_type,param); Request request = new Request.Builder().url(url).post(requestBody).build(); Call call = okHttpClient.newCall(request); try{ result = call.execute().body().string(); }catch(IOException e){ System.out.println(url + "Error!"); e.printStackTrace(); } return result; } public static void main(String[] args) { Map<String,String> data = new HashMap<>(); String url ="http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key=%E5%B0%8F%E9%98%BF%E4%B8%83&pn=1&rn=30&httpsStatus=1&reqId=f61e3dd1-ec4f-11ea-bbb1-e3764df2dd13"; data.put("key","小阿七"); data.put("pn","1"); data.put("httpsStatus","1"); data.put("reqId","f61e3dd1-ec4f-11ea-bbb1-e3764df2dd13"); JsonPoster poster = new JsonPoster(); String result = poster.postContent(url,data); System.out.println(result); } }

我们发现有问题,具体什么问题,我们后面慢慢说。

4. response

4.1 response解析文本文件

上一章我们学习了 Java 中使用 Okhttp3 库请求网页或调用 API 的知识,

call.execute().body().string()来返回我们所要的字符串

实际上,除了具体的返回结果,我们通常还关心的数据是:http 状态码

状态码是用一个数字直观反映了本次请求的状况,例如常见的 200 表示请求成功了,404 表示出错了,服务端没有被请求的内容。我们访问小阿七就出问题了。

为了取得响应状态码,可以使用语句:

call.execute().code()

具体操作如下:

import okhttp3.Response; // 执行请求 Response rep = call.execute(); // 获取响应状态码 int code = rep.code(); // 获取响应内容 String content = rep.body().string();

4.2 response解析非文本文件

我们只要把string改成byte就可以了

response.body().bytes();

这个可以用于图片,视频等非文本文件。

4.3 json

前两节,我们学习了 Java 中使用 Okhttp3 库获取请求返回的内容。无论是文本文件,还是二进制文件,都能够熟练使用了。

而在工作中,经常会调用 API ,而很多 API 返回的文本内容是 JSON 格式的。

json是一段文本,也就是 Java 的字符串,是难以进行解析具体内容的。必须转换成 Java 的对象。

前一节我们已经学习过使用 fastjson 库把参数对象转换为 JSON 格式字符串,当然也可以把 JSON 结果转换为对象,方便程序今后一步分析。

JSON.parseObject()

package com.youkeda.test.http; import com.alibaba.fastjson.JSON; import java.io.IOException; import java.util.HashMap; import java.util.Map; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class ApiAsker { /** * 根据输入的url,读取页面内容并返回 */ public String getContent(String url) { // okHttpClient 实例 OkHttpClient okHttpClient = new OkHttpClient(); // 定义一个request Request request = new Request.Builder().url(url).build(); // 使用client去请求 Call call = okHttpClient.newCall(request); // 返回结果字符串 String result = null; try { // 执行请求 Response response = call.execute(); // 获取响应内容 result = response.body().string(); } catch (IOException e) { // 抓取异常 System.out.println("request " + url + " error . "); e.printStackTrace(); } return result; } public static void main(String[] args) { String url = "http://ip-api.com/json/"; ApiAsker asker = new ApiAsker(); String content = asker.getContent(url); System.out.println("查询结果文本:" + content); Map contentObj = JSON.parseObject(content, Map.class); System.out.println("JSON 格式字符串转换为 Map 对象"); } }

4.4 解析json

我们上面解析了我现在的地址,在江苏南京,

{“status”:“success”,“country”:“China”,“countryCode”:“CN”,“region”:“JS”,“regionName”:“Jiangsu”,“city”:“Nanjing”,“zip”:"",“lat”:32.0617,“lon”:118.7778,“timezone”:“Asia/Shanghai”,“isp”:“China Mobile Communications Corporation”,“org”:“China Mobile Communications Corporation”,“as”:“AS56046 China Mobile communications corporation”,“query”:“36.152.115.125”} 我们怎么得到我们想要的东西呢?

我们就使用get方法,在里面输入键值就可以了

System.out.println("查询结果文本:" + content); Map contentObj = JSON.parseObject(content, Map.class); System.out.println("当前 IP 为:" + contentObj.get("query"));

如果嵌套复杂怎么办,我们一层层剥开就可以了。

Map contentObj = JSON.parseObject(content, Map.class); Map dataObj = (Map)contentObj.get("data"); String city = (String)dataObj.get("city");

5. headers

5.1 user-agent

由于有一些网站有防抓取机制,就像小阿七一样所以我们没有办法访问到,因为浏览器判断请求是否真的来自于一个真实的浏览器。如果不是来自浏览器,例如 Java 程序请求,API 服务器认为不是真实的浏览器访问,就直接拒绝掉了。

判断请求是否真的来自于一个真实的浏览器,需要从 HTTP 消息头(Headers)中取得 User-Agent 信息后,才能判断。

调取方法:进去浏览器里面查看在开发者工具里面可以看到相关的问题与操作。

headers是HTTP协议的一项比较重要的内容,作用是在发起请求的时候,除了请求参数外,可以附加更多的信息。可以参看python文档里面的内容。

这里只要记住,Headers 信息并不是写在 URL 中的,属于隐藏的数据,不能直观看到。

User-Agent:是存放在 Headers 中的一种数据信息。作用是,在指定 URL 发送请求的时候,告诉服务端当前用户的浏览器类型、版本,甚至操作系统、CPU等非隐私的技术信息。

服务器从 Headers 中的 User-Agent 信息获取到浏览器类型、版本等数据后,就认为是一个浏览器请求的环境了,就会给出响应。

我们使用这个,就可以让浏览器认为是本浏览器进行工作的,就可以进行爬取了。

所以,我们只要在程序代码中,附加上 User-Agent 信息,就能允许成功了。当然,这里的 User-Agent 是模拟的。

代码如下:

Request request = new Request.Builder() .url(url) .addHeader("User-Agent", "") .build();

addHeader的方法:第一个是参数名,第二个是参数值。

5.2 referer

有一些网页,我们加了user-agent还是打不开,因为有防盗处理机制,我们现在加一个方法:

但浏览器在请求网页中的图片(或其它任何文件)时,会自动在 HTTP 消息头 Headers 中,加一个 Referer 信息,表示请求的来源。

即浏览器自动告诉图片服务器,从当前 youkeda.com 请求此图片,这时图片服务器拒绝了访问,因为图片服务器的规则是不允许其它网站(非nlark.com)访问图片。

加referer的方法:

Request request = new Request.Builder() .url(url) .addHeader("Referer", "https://ham.youkeda.com/course/j14/0") .build();

贴到浏览器能访问是因为此图片服务器允许无 Referer 信息时访问。但也不是所有图片服务器都允许呢,况且即使同一个图片服务器,也可能修改规则,某一天突然改为必须本站内才能也未可知。

所以,为了一劳永逸的解决问题,需要把 Referer 信息设置为图片原始使用的网站。

5.3 host

前两节我们学习了如何使用 Okhttp3 库设置 HTTP 协议的 Headers,以此解决在调用网址、API 过程中可能出现的各种问题。

这节课学习 Host,也是 Headers 中非常重要的信息之一。

表示当前请求的域名。虽然这个域名已经存在于 URL 中,但遇到复杂的场景,例如使用代理服务器、或者 URL 中不写域名而是写 IP 地址进行请求等,设置 Host 就非常有用了。

Request request = new Request.Builder() .url(url) .addHeader("Host", "www.douban.com") .build();

6. 相关东西的下载

6.1 下载文件

在第3章第2节我们学习了如何请求图片、excel等文件,此类二进制文件无法把内容输出在 console 进行查看的,所以请求结果必须写入文件。

Java写文件要分为三个步骤

创建文件对象 ↓ 写入内容 ↓ 关闭写入操作

文本文件的写入:

import java.io.File; import java.io.FileWriter; // 文件对象 File file = new File("foo.txt"); String content = "Hello world" // 写入内容 FileWriter fileWritter = new FileWriter(file.getName()); fileWritter.write(content); // 关闭 fileWritter.close();

此时就生成了一个文本文件。

二进制文件的写入:

假设文件数据的变量是 byte[] data,那么写入本地文件的代码如下

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();

图片下载与二进制文件下载一模一样

6.2 解析excel

我们需要注入依赖。

大家都知道,excel 文件是多 sheet 模式的,每个 sheet 实际上是一个表格,表格又分为行和列。

解析方法:

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); } }

解析文件的第一个步骤是读取文件内容,调用 EasyExcel.read() 方法,传入文件名称。然后这里解析的 第一个 工作表,所以调用 sheet() 方法,传入参数 0 。最后的 doReadSync() 表示同步方式读取文件内容,返回一个读取到的内容集合 List 。这是一个连贯的写法。

我们知道,excel里面我们不知道类是什么,所以我们要自动转化成类来进行使用。

在不能提前确定 excel 文件每一列的含义时,或者复杂场景下 excel 文件的列经常变化,用 Map 表示每一列的数据比较好。

但是如果知道 excel 文件每一列的含义,用自定义类来表示,会更加直观。

import com.alibaba.excel.EasyExcel; import java.util.List; // 读取第一个sheet List<DemoData> sheetDatas = EasyExcel.read("xzq_201907.xlsx").head(DemoData.class).sheet(0).doReadSync();

注意这里多调用了一个方法:.head(DemoData.class),DemoData 就是自定义的类,表示一行数据,类的每个属性都表示一列的值。

返回值为 List 就表示把每一行都转换为一个 DemoData 的实例对象,放入 List 集合中。

code1 是第一个属性,映射 excel 文件第一列的值。这是为了让大家易懂,在属性名上加了数字,实际上,即使属性名是 code10000 ,只要放在最前面,就映射第一列的值。

无论转换为自定义的类还是 Map,EasyExcel.XXXXXX.doReadSync() 最终返回的都是一个集合 List 。大家一定要理解的是,集合中的每一个元素,即每一个实例对象(无论是自定义类还是 Map),都表示一行数据。

7. cookie & session

7.1 cookie

前面我们学习 Okhttp3 库可以调用API、抓取网页、下载文件。但是这些操作都是不要求登录的,如果 API、网页、文件等内容要求登录才能访问,就需要学习新的 cookie 相关的知识了。

所谓 cookie ,是存储在客户端浏览器中的一段文本内容。以 key=value (数据名称、数据值)的格式存储一条数据;多条数据之间用分号 ; (英文半角)分开。由于各种浏览器都对 cookie 大小和数量有限制,所以 cookie 目前的核心功能是存储登录数据;额外可以存储一些小数据。

cookie的寻找方法:谷歌浏览器里面的开发者模式下进行查找即可。

由于cookie比较长,我们要把它解析成map

我们使用ReadFileTool.readContent方法进行把长长的字符串解析成map键值对。

7.2 session

但 cookie 的弊端是,cookie 是存放在客户端浏览器的,而且是临时的,登录后还想以登录状态与服务器通讯,就比较麻烦。

这就需要在程序中使用 Session 对象来解决这个问题。

代码如下:

package com.youkeda.test.http; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import okhttp3.Cookie; import okhttp3.CookieJar; import okhttp3.FormBody; import okhttp3.FormBody.Builder; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; public class PageLoginer { // 用 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(); public String postContent(String url, Map<String, String> formData) { //post方式提交的数据 Builder builder = new FormBody.Builder(); // 放入表单数据 for (String key : formData.keySet()) { builder.add(key, formData.get(key)); } // 构建 FormBody 对象 FormBody formBody = builder.build(); // 指定 post 方式提交FormBody Request request = new Request.Builder() .url(url) .post(formBody) .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36") .addHeader("Referer", "https://passport.mtime.com/member/signin/?redirectUrl=http%3A%2F%2Fwww.mtime.com%2F") .addHeader("Host", "passport.mtime.com") .build(); // 返回结果字符串 String result = null; try { result = okHttpClient.newCall(request).execute().body().string(); } catch (IOException e) { System.out.println("request " + url + " error . "); e.printStackTrace(); } return result; } public static void main(String[] args) { // 登录页面 url String url = "https://passport.mtime.com/member/signinLogin"; // 登录表单数据 Map<String, String> formData = new HashMap(); formData.put("loginEmailText", "13777467803"); formData.put("loginPasswordText", "aa787bc9cc97ba5d27cc042ecffe1489"); formData.put("isvcode", "true"); formData.put("isAutoSign", "false"); PageLoginer asker = new PageLoginer(); String content = asker.postContent(url, formData); System.out.println(content); } }

这里面new CookieJar() {…}是匿名内部类

我们使用时看看就可以了

8. 发邮件

在 Java 中我们可以调用 JavaMail 调用发送和接收邮件,我们首先配置 maven 依赖,如 pom 文件中加入

<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; import com.sun.net.ssl.internal.ssl.Provider; public class MailClient { public static void main(String[] args) { try { //设置SSL连接、邮件环境 Security.addProvider(new Provider()); 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(); } } }

“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(); } } }

授权码自己看吧。
最新回复(0)