Java网络编程-简单的API调用
Get请求 - 无参数
安装依赖库
首先需要安装一个库: Okhttp3
,这是一个非常流行的 HTTP
库,可以简单、快速的实现 HTTP
调用。
安装 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>
唯一的 <dependencies>
标签中,包含多个 <dependency>
标签,每一个 <dependency>
标签表示一个依赖库。书写时注意嵌套顺序哦。
pom.xml
文件的作用就是定义 Java
项目需要用到(或者说依赖到)哪些库。
使用详解
例如要抓取“中国科学技术大学”首页的内容:
使用 Okhttp3
完成页面请求,需要三大步骤:
1.实例化 OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient();
2.执行调用
在执行调用之前需要实例化一个 Request
对象,作用是定义请求的各种参数:
Request request = new Request.Builder().url(url).build();
然后构建调用对象 :
Call call = okHttpClient.newCall(request);
3.最后执行调用,调用失败可能异常,所以必须抓取异常
call.execute()
返回的是一个执行的结果对象,调用对象的方法即可获取返回的字符串内容:
result=call.execute().body().string();//添加try-catch
这个过程你可以类比打电话:
- 拿出手机,相当于实例化Request对象,
- 拨号,相当于newCall()方法,这些都是前置操作,
- 每说一句话,相当于执行 execute() 方法,
- 听到对方说的话,就相当于获取返回结果 body().string()
演示的代码基本上都属于固定写法。
举例:
public class GetPage {
public String getContent(String url){
OkHttpClient okHttpClient = new OkHttpClient();
//定义一个请求,配置,urL,
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("request" + url + "error.");
e. printStackTrace;
}
return result;
}
public static void main (String[] args) {
GetPage getPage = new GetPage();
String url = "https://www.ustc.edu.cn/";
String content = getPage.getContent (url);
System.out.println("call" + url + " ,conent=" + content);
}
把调用的步骤封装在一个 getContent()
方法中,比较容易理解,也方便复用。
注意:不要忘记 pom.xml
文件添加依赖,以及代码中使用 import
语句引入使用的类。
关于输出结果
call.execute().body().string();
可以取得服务器返回的具体内容。
在 console
中看到的大量的文本内容,这是给浏览器识别的内容,包含了很多无效的内容。所以很多时候,我们使用程序调用 API
,获取到需要的数据。
什么是 API
API 全称 Application Programming Interface,应用程序接口,API 一般是指一些预先定义的函数,目的是可以为开发人员快速访问某一程序,而无需了解和访问源码,或理解它内部工作机制的细节。
简单的讲,API 可以快速调用某个程序。
这在计算机里叫做接口,我们生活中也有很多接口,比如 U 盘可以储存信息,我们访问 U 盘,只需要把 U 盘插到电脑上就可以访问,插入的 USB 接口就是一个接口,不需要关心它是如何实现的。又比如电视机上有很多接口,有的连话筒,有的连视频,我们只需要直接插上对应的线就可以实现相应的功能,并不关心它的具体机制。
调用 API
我们看一个查询 杭州市 天气的 API
:https://api.seniverse.com/v3/weather/daily.json?key=SCYrvkytJze9qyzOh&location=杭州
把这个 URL 贴到浏览器,可以看到查询返回结果为:
{"results":[{"location":{"id":"WTMKQ069CCJ7","name":"杭州","country":"CN","path":"杭州,杭州,浙江,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2023-05-09","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"20","low":"10","rainfall":"0.00","precip":"0.00","wind_direction":"东","wind_direction_degree":"90","wind_speed":"23.4","wind_scale":"4","humidity":"69"},{"date":"2023-05-10","text_day":"阴","code_day":"9","text_night":"小雨","code_night":"13","high":"22","low":"12","rainfall":"5.40","precip":"0.88","wind_direction":"东","wind_direction_degree":"90","wind_speed":"32.8","wind_scale":"5","humidity":"75"},{"date":"2023-05-11","text_day":"小雨","code_day":"13","text_night":"阴","code_night":"9","high":"20","low":"15","rainfall":"0.43","precip":"0.41","wind_direction":"无持续风向","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"80"}],"last_update":"2023-05-09T08:00:00+08:00"}]}
这一大段的内容,跟常见的精美的网页不同,全是数据,看到有些眼花缭乱。仔细看还是能看到 2023-05-09 杭州 的天气是 晴
数据基本上不是让人直接阅读的,是给前端程序使用的
所谓 API
,本质上就是一个 URL
。开头也是 http
(或https
),与精美的网页相比,内容有明显的区别。API
返回的内容统称为数据
。
网络编程的学习方法
网络编程与程序最大的不同,是用到了新的程序开发包 。
这种程序开发包,由于不是 Java 官方出品的,而是其他公司或个人 开源 的,通常也叫 二方包 。程序开发包,是为了更加简便的完成某些特定的功能,提升开发效率。
如果不用 Okhttp3 ,而用 JDK 内置的类,也能完成相同的功能,但代码量会大很多。上一节 getContent() 方法大约有 18 行,如果不用 Okhttp3 代码量可能要再增加 3-4 倍。
不熟悉计算机网络知识就无法编程了吗?
答案是否定的: 当然可以编程 。
需要改变学习方法
学习开源技术的方法,与学习其它知识的方法,略有不同。
例如 Okhttp3 程序开发包的使用,可以从粗到细的学习,首先要知道这个技术解决了什么问题。
做什么
学过本课程,我们再看到一个新的 网址 ,必须能够想到使用 Okhttp3 获取其内容。
新网址无论是网页还是 API ,都要能举一反三,都能想到可以用 Okhttp3
怎么做
在第一节课中,已经把抓取过程的代码,封装在一个方法中:
public String getContent(String url) {
}
调用这个方法很简单,只要在参数中输入想抓取的网址,就会返回抓取的内容。
学习重点
记住:调用 getContent() 方法,即可抓取到网址的内容。首先要了解的是:知道什么代码可以解决什么问题、完成什么功能。
如果 getContent() 方法内的代码细节看不懂,也 不要纠结 。因为编程与考试不同,开发编程是允许查资料的。
我们可以把完整的 getContent() 方法代码记在电脑上,例如印象笔记等各种笔记软件,甚至手写在纸质笔记本上都可以。需要用的时候 copy 出来,即可完成功能。
当然,不要忘了两个配套步骤:添加依赖,不要遗漏 import 语句。
后面要特别注意区分,不同的代码适用于什么场景、能解决什么问题。
未来持续学习
待自己补充了计算机网络的理论知识,加上编程达到熟练程序以后,就可以回过头来研究 Okhttp3 的代码细节啦。
先预览一下 Okhttp3 的源代码:
Get请求 - 有参数
很多情况下,API
调用需要参数,例如下列查询 IP
地址信息的 API
:
http://ip-api.com/json/?lang=zh-CN
只要把包含参数的完整的 URL
直接传入到方法中就可以了。
POST表单数据
先来看一个故事:
话说灵剑派新弟子招募大会升仙大会
在灵剑山下的灵溪镇召开,王陆跃跃欲试,也来到灵溪镇。镇上只有一家如家客栈,如果住不进去,就只能露宿街头了。
王陆来到如家客栈门口,只见一群人围在客栈门口,王陆很好奇,这是怎么回事呢?
此时老板娘来到客栈门前,开口说道:欲入住咱们如家客栈,除了需要登记姓名、年龄、籍贯外,最重要的,是必须持有准入券
,请持有准入券
者入内登记吧。
王陆微微一笑,嗖的一声从怀里掏出一张长方形纸片,只见白底绿纹上三个大字:准入券
,字上鲜红大印格外醒目。老板娘接过准入券笑吟吟做个手势:客官请。
提交数据至服务端进行增加、修改、删除等操作,都是 POST
操作。与王陆登记入住客栈类似,我们在网页上提交表单进行登录的场景,就是典型的 POST
操作。
post() 方法
Okhttp3
库也支持 POST
操作。前面学习的调用 API
属于 GET
操作。不同的是,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
操作啦。
连写代码
这段代码出现了连写:
new Request.Builder().url(url).post(formBody).build();
大多数情况下 不推荐
使用连写(特别是新手不要使用连写)的方式。不用连写的方式应该写作:
Request.Builder build = new Request.Builder();
build = build.url(url);
build = build.addHeader("Referer", "http://www.taobao.com");
build = build.post(formBody);
Request request = build.build();
Request.Builder 表示 Builder 是 Request 的内部类。特殊的是需要通过 Request 类引用 Builder 类。
要完全理解 url header post 这些知识点,还需要 《计算机原理》 、 《计算机网络》 课程,这里不用纠结。可以 等学校里课程学完 后再来 复习 ,这里重点是学会 完成功能 。
不连写的代码可能对新手更友好一点。但这段代码是发送 POST 请求专用的代码,不具备通用性,所以基于很多 大神、前辈 的编码风格,给大家展示简洁的连写风格。
我们仍然把发送表单数据的过程,封装为 postContent()
方法,方便重用。这里的重点是,理解使用 FormBody
对象的实例来存放表单数据。
执行结果说明
gitee
对密码做了特殊加密,所以登录会失败,但是这也说明 gitee
已经收到了请求,只是判断登录不成功而已。
举例:
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 (I0Exception e) {
// 抓取异常
System.out.println("request" + url + " error . ");
e. printStackTrace();
}
return result;
}public static void main (String[] args) {
String url = "https://gitee.com/login";
FormPoster poster = new FormPoster();
Map<String, String> formBody = new HashMap<>();
formBody. put("user [login]", "17177456748");
String content = poster.postContent(url, formBody);
System.out.println("API调用结果");
System. out. println(content);
}
POST JSON 数据
在日常开发工作中,除了提交表单数据,也经常用到提交 JSON
数据。
跟表单数据提交方法一样,也是调用 post()
方法,只是参数不再使用 FormBody
对象,而是使用 RequestBody
示例
下列程序演示用 JSON
方法提交数据,注册一个新用户,数据包括:
数据名 | 数据值 |
---|---|
name | 张飞 |
secondName | 翼德 |
首先我们需要添加一个依赖:
<!-- JSON 操作库-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactld>fastjson</artifactld>
<version>1.2.62</version>
</dependency>
代码示例:
package com.youkeda.test.http;
import com. alibaba. fastjson.JSON;
import okhttp3.*;
import java.io. IOException;
import java.util.HashMap;
import java.util.Map;public class JsonPoster {
private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
/**
* 向指定的 UPL 提交数据
*/
public String postContent(String url, Map<String, String> formData) {
// okHttpClient 实例
OkHttpClient okHttpClient = new OkHttpClient();
// key-value
String param = JSON. toJSONString (formData);
RequestBody cequestBody = RequestBody create (JSON_TYPE, param) ;
// 指定 post 方式提交FormBody
Request request = new Request. Builder().url(url).post(requestBody).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 ="https://www.fastmock.site/mock/3d95acf3f26358ef032d8a23bfdead99/api/posts";
JsonPoster poster = new JsonPoster();
Map<String, String> datas = new HashMap<>();
datas.put("name","张飞");
datas.put ("secondName"
,"翼德");
String content = poster postContent(url, datas);
System.out.println("API调用结果") :|
System.out. println(content);
}
}
从 console 打印结果可以看到,服务器注册成功,并生了新用户的 id
号。
详解
实现 JSON
方式提交数据的步骤:
- 将数据转换成
JSON
格式的字符串,调用JSON.toJSONString()
方法即可。 - 创建
RequestBody
实例,注意需要指定提交的类型是application/json; charset=utf-8
。这里的utf-8
是API
规定的编码格式。 - 构建
Request
实例对象时,调用.post(requestBody)
即表示使用JSON
的方式提交数据。
这些基本上都是固定写法。
相关文章:

Java网络编程-简单的API调用
Get请求 - 无参数 安装依赖库 首先需要安装一个库: Okhttp3,这是一个非常流行的 HTTP 库,可以简单、快速的实现 HTTP 调用。 安装 Okhttp3 的方式是在 pom.xml 文件中增加依赖: <!-- https://mvnrepository.com/artifact/c…...

论文笔记(五十)Segmentation-driven 6D Object Pose Estimation
Segmentation-driven 6D Object Pose Estimation 文章概括摘要1. 引言2. 相关工作3. 方法3.1 网络架构3.2 分割流3.3 回归流3.4 推理策略 4. 实验4.1 评估 Occluded-LINEMOD4.1.1 与最先进技术的比较4.1.2 不同融合策略的比较4.1.3 与人体姿态方法的比较 4.2 在YCB-Video上的评…...

微服务的一些基本概念
目录 1 概述1.1 微服务架构的特征1.2 微服务架构示例 2 微服务与单体式架构2.1 什么是单体式架构?2.2 单体式架构的优点2.3 单体式架构的缺点 3 什么是微服务?3.1 微服务的优点3.2 微服务的缺点 4 如何构建微服务4.1 从单体式开始4.2 以正确的方式组织团…...

el-table修改指定列字体颜色 ,覆盖划过行的高亮显示文字颜色
修改指定列字体颜色 ,覆盖划过行的高亮显示文字颜色 代码如下: <div class"c1"><el-table:data"tableData"striperow-class-name"custom-table-row"style"width:100%"cell-mouse-enter"lightFn"cell-…...

java高频面试题汇总
Java 基础 Java 中的序列化和反序列化是什么? 序列化是将 Java 对象转换为字节流的过程,以便可以将其存储在文件中或通过网络进行传输。反序列化则是将字节流恢复为 Java 对象的过程。通过实现 Serializable 接口,Java 对象可以支持序列化。…...

Docker安装ocserv教程(效果极佳)
本章教程,介绍如何在Debain系统上安装ocserv。安装方式是使用Docker方式部署。 一、安装Docker curl -sSL https://file.ewbang.com/docker/debian/install_docker.sh -o install_docker.sh && bash install_docker.sh二、拉取镜像 docker pull tommylau/ocserv...

【数据结构与算法】第3课—数据结构之单链表
文章目录 1. 什么是链表2. 单链表2.1 单链表的初始化和打印2.2 单链表的尾插和头插2.3 单链表的尾删和头删2.4 单链表查找节点2.5 单链表在指定位置之前/之后插入数据2.6 单链表删除节点和删除pos之后的节点2.7 销毁链表 3. 单链表和顺序表对比 1. 什么是链表 链表是在逻辑结构…...

linux—基础命令及相关知识
1.0Linux的哲学思想(优势) 1、一切都是一个文件,一切硬件设备包括硬件接口都可以以文件形式显示 2、系统小型,轻量级,300个包(不装桌面的情况下) 3、避免令人困惑的用户界面(图形…...

Spring Boot 实现 WebSocket(注解方式)
本文介绍如何使用 Spring Boot 的注解方式实现一个简单的 WebSocket 服务,支持客户端与服务器之间进行实时通信。 1. 引入依赖 在 pom.xml 文件中添加 WebSocket 相关依赖。 <dependencies><!-- Spring Boot WebSocket 支持 --><dependency>&l…...

windows下Qt的安装方法
Qt Creator是个人非常喜欢的一款开发工具,喜欢用其来开发C和CPC平台项目,当然也可以用其来开发Android和Auto平台项目,但其现在采用离线安装,限于网络问题,安装速度非常慢。 现在介绍一种可以完成快速的安装方法。 下…...

嵌入式面试题 ARM常见面试题
一.ARM内核分为哪几类?他们之间有什么区别? ARM内核主要分为三类,Cortex-A,Cortex-R,Cortex-M三种,A代表Applications,向用户提供全方位解决方案,主要用于复制的应用场合,比如智能手机、移动计算平台,数字电视、机顶盒、打印机或服务器等。R代表Real-Time Embedded,…...

分布式调度器--Spring Task 的使用
目录 1、启动类(App.java)上加EnableScheduling注解: 开启基于注解的任务调度器 2、同步定时任务 3、多线程(异步)定时任务 3.1 配置线程池 3.2 开启异步支持 3.3 定义异步方法 4、Api说明 4.1 fixedDelay 4.…...

Java应用程序的测试覆盖率之设计与实现(四)-- jacoco-maven-plugin
一、什么是jacoco-maven-plugin jacoco源码jacoco文档 除了使用jacoco.cli.jar导出并生成覆盖率报告外,还可以使用jacoco-maven-plugin,它是maven集成了jacoco的一款插件。 在工程pom.xml里配置插件jacoco-maven-plugin。 <plugin><groupId&g…...

UI 提供的 progress-step 要怎么实现?
前言 这天突然收到了 UI 修改设计稿的消息通知:“xxx 已修改 xxx 项目并 了你,请及时查看变更内容”,一条、两条、三条 …,修改消息铺天盖地而来,然后就什么都看不到了(因为我选择开启消息免打扰…...

DBSwitch和Seatunel
一、DBSwitch 什么是DBSwitch?它主要用在什么场景? 通过步骤分析可以看到这个是通过配置数据源,采用一次性或定时方案,同步到数据仓库的指定表,并且指定映射关系的工具。有点类似于flinkcdc的增量同步。 参考: dbs…...

【日志】力扣刷题 -- 轮转数组
2024.10.06 【力扣刷题】 经典面试150—转轮数组—中等 189. 轮转数组 - 力扣(LeetCode) 第一次做,暴力循环 // 超出时间限制 void rotate(int* nums, int numsSize, int k) {for(int i 0; i < k; i){int right numsSize - 1;int temp…...

Java 项目 Dockerfile 示例:从基础镜像选择到环境变量配置的详细指南
Java 项目 Dockerfile 示例:从基础镜像选择到环境变量配置的详细指南 本文提供了一个 Java 项目的 Dockerfile 示例,展示了如何为 Java 应用创建高效的 Docker 镜像。Dockerfile 从 OpenJDK 8 的 Java 运行环境开始,配置了工作目录和 JVM 启…...

WebGL编程指南 - 高级变换与动画基础
学习使用一个矩阵变换库,该库封装了矩阵运算的数学细节。快速上手使用该矩阵库,对图形进行复合变换。在该矩阵库的帮助下,实现简单的动画效果。 矩阵变换库:cuon-matrix.js OpenGL中的函数: 书中 cuon-matrix.js 函数…...

银行客户贷款行为数据挖掘与分析
#1024程序员节 | 征文# 在新时代下,消费者的需求结构、内容与方式发生巨大改变,企业要想获取更多竞争优势,需要借助大数据技术持续创新。本文分析了传统商业银行面临的挑战,并基于knn、逻辑回归、人工神经网络三种算法࿰…...

制程质量管理方案设计
质量管理系统框架——QMS 涵盖产生产制造体系的全生命周期的质量管理过程 与SAP、WMS、MES、OA等业务系统进行集成,整合各业务系统中的质量信息 利用整合的全价值链质量信息,寻找质量改进点和质量创新点 系统功能模块管理 系统管理:用户管理…...

uniapp移动端优惠券! 附源码!!!!
本文为常见的移动端uniapp优惠券,共有6种优惠券样式(参考了常见的优惠券),文本内容仅为示例,您可在此基础上调整为你想要的文本 预览效果 通过模拟数据,实现点击使用优惠券让其变为灰色的效果(模…...

【分布式技术】中间件-zookeeper安装配置
文章目录 安装部署1. 安装ZooKeeper2. 配置ZooKeeper3. 启动ZooKeeper服务器4. 使用ZooKeeper命令行客户端5. 使用ZooKeeper的四个基本操作6. ZooKeeper集群模式7. 安全和权限8. 监控和日志 相关文献 安装部署 在Linux环境中操作ZooKeeper通常涉及以下几个方面: 1…...

高等数学 7.6高阶线性微分方程
文章目录 一、线性微分方程的解的结构*二、常数变易法 方程 d 2 y d x 2 P ( x ) d y d x Q ( x ) f ( x ) (1) \cfrac{\mathrm{d}^2 y}{\mathrm{d}x^2} P(x) \cfrac{\mathrm{d}y}{\mathrm{d}x} Q(x) f(x) \tag{1} dx2d2yP(x)dxdyQ(x)f(x)(1) 叫做二阶线性微分方程。…...

LSP的建立
MPLS需要为报文事先分配好标签,建立一条LSP,才能进行报文转发。LSP分为静态LSP和动态LSP两种。 静态LSP的建立 静态LSP是用户通过手工为各个转发等价类分配标签而建立的。由于静态LSP各节点上不能相互感知到整个LSP的情况,因此静态LSP是一个…...

huggingface的数据集下载(linux下clone)
1. 安装lfs sudo apt-get install git-lfs 或者 apt-get install git-lfs 2. git lfs install git lfs install 3. git clone dataset包 第2,3步骤的截图如下:...

Java使用dom4j生成kml(xml)文件遇到No such namespace prefix: xxx is in scope on:问题解决
介绍addAttribute和addNamepsace: addAttribute 方法 addAttribute 方法用于给XML元素添加属性。属性(Attributes)是元素的修饰符,提供了关于元素的额外信息,并且位于元素的开始标签中。属性通常用于指定元素的行为或样式&#…...

深入探讨Java中的LongAdder:使用技巧与避坑指南
文章目录 一、什么是LongAdder?二、LongAdder的简单使用示例代码: 三、LongAdder的工作原理四、LongAdder的常见使用场景五、使用LongAdder时的注意事项(避坑指南)1. 不要滥用LongAdder2. sum()方法与精度问题3. 避免过度使用rese…...

【本科毕业设计】基于单片机的智能家居防火防盗报警系统
基于单片机的智能家居防火防盗报警系统 相关资料链接下载摘要Abstract第1章 绪论1.1课题的背景1.2 研究的目的和意义 第2章 系统总体方案设计2.1 设计要求2.2 方案选择和论证2.2.1 单片机的选择2.2.2 显示方案的选择 第3章 系统硬件设计3.1 整体方案设计3.1.1 系统概述3.1.2 系…...

C语言 动态数据结构的C语言实现单向链表-2
建立一个单向链表 在单向链表中查找节点---查找尾节点 在单向链表中查找节点 --- 查找第 n 个节点 向单向链表中插入一个节点 向单向链表的尾部插入一个节点 向单向链表中某节点后插入一个节点 向单向链表中插入一个节点 删除单向链表中的某一节点 链表 vs 数组 动态数据结构...

Github 2024-10-23C开源项目日报 Top10
根据Github Trendings的统计,今日(2024-10-23统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目10PLpgSQL项目1Redis - 内存数据库和数据结构服务器 创建周期:5411 天开发语言:C协议类型:BSD 3-Clause “New” or “Revised” Licen…...