安卓基础(持续更新的笔记)
为什么要这样:
// 创建请求体RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),jsonObject.toString());
jsonObject
就包含了一个 JSON 数据,它其实就是:
{"name": "张三","age": 10
}
所以,jsonObject.toString()
会把我们的 JSON 数据转换成:
{"name":"张三","age":10}
什么是 client.newCall(request).enqueue()
?
client
是什么?
- 你可以把
client
想象成一个邮递员。 - 它负责接收信件(就是请求)并把信件送到目的地(比如服务器)。
request
是什么?
request
就是你要寄出的信,它包含了你想要发送的信息(比如:你想要从网站获取的数据)。- 你可以把 request 看作是装在信封里的信,信里写着你要做什么(比如:查天气,获取新闻等)。
newCall(request)
是什么意思?
- 当你说
client.newCall(request)
时,你是在告诉邮递员:“嘿!这是我的信(请求),帮我寄出去!”
enqueue(new Callback() {...})
是什么意思?
-
这部分就是你告诉邮递员,“当信送到之后,告诉我一声!”就像你期待收信一样,你也期待邮递员处理完请求之后给你一个答复。
-
enqueue
是一个 "异步" 操作,意味着邮递员把信送出去后,他不会立刻等待回信,而是继续去做其他事情。等他收到回复时,他会 通知你,就像“嘿!你的信已经回来了,我有了答案!” -
Callback
就是你给邮递员的一个回信地址,你告诉邮递员,“当有回复的时候,联系我”。当你收到答复时,邮递员就会通过Callback
告诉你 答复内容。
public void onResponse(Call call, Response response) throws IOException
为什么要加一个 Call call
参数?
-
表示当前的请求:
onResponse
是一个回调方法,它在网络请求成功后被调用。Call call
这个参数是告诉你当前的请求是什么,它是你发起的某个网络请求对象。这样,在回调中你可以通过call
来获取有关请求的信息。 -
支持多次请求: 有时候,程序可能会发起多个请求。通过在
onResponse
中传递call
,你就能知道是哪个请求返回的结果。如果没有call
,你就不知道是哪个请求触发了回调。
String responseBody = response.body().string();
response.body().string();
这行代码的意思是什么?
response
: 这是你从网络请求得到的回应,它包含了很多信息,比如服务器返回的数据、状态码、头信息等。body()
: 这个方法可以用来获取服务器返回的数据内容。可以理解为,"body" 就是回应的内容。string()
: 这个方法把回应的内容转换成字符串。因为服务器返回的数据通常是以二进制的方式存储的,我们需要把它转换成可读的文本(字符串)才能理解里面的内容。
举个简单的例子:
想象你给朋友发了一个包裹,这个包裹里有一些写着字的纸条,代表服务器给你的回应。
response.body()
就像是你打开包裹,拿到里面的纸条。string()
就是你把纸条上的内容读出来,变成可以理解的文字。
轮询获取消息是什么?
轮询获取消息,简单来说,就是定时检查是否有新消息。就像你每天都会去查看邮箱,看看是否有新的邮件。你定期检查一次,如果有新邮件,你就打开看,没有就过一会儿再看一次。
代码怎么实现?
- Looper 是顾客排队的地方(等候队列),
- Handler 就是把任务分配给助手的工具(执行任务)。
new Handler(Looper.getMainLooper())
就是告诉你:“嘿,我们要让这个任务在应用的大脑(主线程)里执行!”-
handler.post(new Runnable()):
handler.post(new Runnable())
就是把一个新的任务(Runnable)交给管家(Handler)来执行。- 它的作用是告诉管家:“嘿,我有个任务交给你,你去做吧!”
-
Looper.loop()
会启动一个无限的循环,持续检查并执行交给它的任务。
在安卓中,轮询可以通过定时任务来实现。最常见的方法是使用Handler
和Runnable
,每隔一段时间就去请求服务器看看有没有新消息。这里是一个简单的例子:
// 导入 Android 中的 Handler 类和 Looper 类
import android.os.Handler;
import android.os.Looper;public class PollingExample {// 创建一个 Handler 对象,Handler 会在主线程中处理任务private Handler handler = new Handler(Looper.getMainLooper());// 定义一个变量 interval,每隔5秒检查一次private int interval = 5000; // 每5秒钟检查一次private boolean isPolling = false; // 用来标记是否在进行轮询// 开始轮询,设置 isPolling 为 true,表示开始检查新消息public void startPolling() {isPolling = true; // 开启轮询pollMessages(); // 调用 pollMessages 方法开始检查}// 停止轮询,设置 isPolling 为 false,表示不再检查新消息public void stopPolling() {isPolling = false; // 停止轮询}// 检查是否有新消息的方法private void pollMessages() {if (isPolling) { // 如果正在进行轮询// 模拟发起网络请求,检查是否有新消息System.out.println("正在检查是否有新消息..."); // 输出提示信息,表示正在检查消息// 模拟检查到新消息boolean newMessageReceived = checkForNewMessages();// 如果检查到新消息,就输出提示信息if (newMessageReceived) {System.out.println("有新消息!"); // 输出“有新消息!”}// 每隔 interval(5秒)再去检查一次handler.postDelayed(new Runnable() {@Overridepublic void run() {pollMessages(); // 再次调用 pollMessages 方法,继续检查}}, interval); // 设置延迟时间为 interval(5秒)}}// 模拟一个方法,用来检查是否有新消息private boolean checkForNewMessages() {// 假设这里是通过网络请求来检查新消息,我们简单返回 true,表示有新消息return true;}
}
Retrofit 是一个用来简化网络请求的 Android 库。它帮助我们在 Android 应用程序中发送 HTTP 请求(比如获取网络上的数据),并把这些请求的响应数据转换成我们能理解和使用的格式。换句话说,它是一个让你与网络进行“对话”的工具。
如何使用 Retrofit?
- 创建一个接口:定义你想要请求的 API,告诉 Retrofit 你需要什么数据。
- 配置 Retrofit 实例:设置 Retrofit,告诉它请求的 URL 和如何处理数据。
- 发起请求:通过 Retrofit 请求网络数据,并处理返回的结果。
步骤 1: 安装 Retrofit
首先,我们需要在我们的项目中添加 Retrofit 这个工具。就像是我们需要下载一个游戏的安装包一样。
- 打开 Android Studio。
- 找到你项目中的
build.gradle
文件(就是一个列出我们需要用到的工具和库的清单)。 - 在这个文件里添加 Retrofit 的依赖(就像是给我们的游戏添加功能):
dependencies {implementation 'com.squareup.retrofit2:retrofit:2.9.0' // 这是 Retrofit 这个工具implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // 用来转换数据的工具
}
然后点击 Sync Now,就像是安装游戏一样,安装完成后你就可以使用 Retrofit 了。
步骤 2: 创建 Retrofit 接口
接下来我们要告诉 Retrofit,我要去哪里获取数据(就像告诉游戏你要去哪里玩)。
接口 是一个用来定义我们需要请求哪些数据的地方。我们可以把它想象成是告诉 Retrofit 我们要去哪里拿数据。
比如我们想去一个网站,看看 GitHub 上某个人的仓库(就像是我们想要知道某个游戏的排名)。我们可以定义一个接口来告诉 Retrofit 我们需要这些信息。
public interface ApiService {@GET("users/{user}/repos") // 这里是 GitHub 的地址Call<List<Repo>> listRepos(@Path("user") String user); // 这个方法去获取某个用户的所有仓库
}
这里我们用了一个 GET 请求,意思是去获取数据。
步骤 3: 创建 Retrofit 实例
接下来,我们需要让 Retrofit 开始工作,就像启动游戏一样。
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/") // 告诉 Retrofit 去哪里获取数据.addConverterFactory(GsonConverterFactory.create()) // 使用 Gson 来帮助我们理解数据.build();
步骤 4: 发起请求
现在我们需要告诉 Retrofit 去获取数据。我们只需要告诉它一个用户的名字,它就会帮我们去获取这个用户的所有仓库。
ApiService apiService = retrofit.create(ApiService.class); // 创建接口
Call<List<Repo>> call = apiService.listRepos("octocat"); // 发起请求,获取 octocat 的仓库
步骤 5: 处理结果
当我们请求数据时,Retrofit 会帮我们处理所有的事情。我们只需要准备好两件事情:
- 如果请求成功了,我们怎么处理结果(就像完成任务后获得奖励)。
- 如果请求失败了,我们怎么处理失败的情况(就像遇到障碍要重新尝试)。
call.enqueue(new Callback<List<Repo>>() {@Overridepublic void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {if (response.isSuccessful()) { // 请求成功List<Repo> repos = response.body(); // 获取到仓库数据for (Repo repo : repos) {System.out.println(repo.getName()); // 打印出每个仓库的名字}}}@Overridepublic void onFailure(Call<List<Repo>> call, Throwable t) {t.printStackTrace(); // 如果请求失败了,打印错误信息}
});
addConverterFactory(GsonConverterFactory.create())
这个代码行是 Retrofit 的一部分,它告诉 Retrofit 如何将从网络上获取到的数据(通常是 JSON 格式)转换成 Java 对象。简单来说,它就像是一个“翻译员”,帮你把网络上收到的“外文”数据(比如 JSON)翻译成你能理解的“中文”数据(比如 Java 对象)。
具体解释:
-
Gson:它是一个工具库,可以将 JSON 数据转换成 Java 对象,也可以将 Java 对象转换成 JSON 数据。Retrofit 使用 Gson 来帮你完成这种转换。
-
ConverterFactory:这就是一个工具箱,里面有很多种转换数据的“翻译员”。
GsonConverterFactory.create()
就是告诉 Retrofit 用 Gson 这个“翻译员”来做这个工作。 -
addConverterFactory():这个方法是用来告诉 Retrofit 你希望使用哪种“翻译员”,并且让它使用这个“翻译员”来处理数据。
举个例子:
假设你从网络上请求到一个用户的信息,服务器返回的结果是这样的一段 JSON:
{"name": "Tom","age": 12
}
你可能想把这段 JSON 转换成一个 Java 对象,可能是这样的:
class User {String name;int age;
}
然后,使用 addConverterFactory(GsonConverterFactory.create())
,Retrofit 就会帮你把这段 JSON 数据自动转换成 User
类的对象,这样你就能在程序里像使用普通 Java 对象一样使用这段数据。
总结:
addConverterFactory(GsonConverterFactory.create())
就是告诉 Retrofit 用 Gson 来帮你自动翻译 JSON 数据,让你可以直接使用 Java 对象,免去了你自己手动解析 JSON 的麻烦。
Gson 是怎么工作的?
Gson 可以帮助你把这段 JSON 数据“翻译”成一个 Java 对象,像这样:
class Person {String name;int age;
}
使用 Gson,你可以通过以下代码把 JSON 转换成 Java 对象:
Gson gson = new Gson();
String json = "{\"name\":\"Tom\", \"age\":12}";
Person person = gson.fromJson(json, Person.class);
这里,fromJson()
方法会把 JSON 数据转换成 Person
类型的对象。现在你就可以像使用普通 Java 对象一样,访问 person.name
或 person.age
了。
Gson 能做什么?
-
将 Java 对象转换成 JSON(序列化):
Person person = new Person(); person.name = "Tom"; person.age = 12; Gson gson = new Gson(); String json = gson.toJson(person); // 将 Java 对象转换为 JSON
-
这会得到一个 JSON 字符串:
{"name":"Tom", "age":12}
。 -
将 JSON 转换成 Java 对象(反序列化):
String json = "{\"name\":\"Tom\", \"age\":12}";
Person person = gson.fromJson(json, Person.class); // 从 JSON 创建 Java 对象
为什么要用 Gson?
- 简单易用:你只需要很少的代码就可以处理 JSON。
- 自动转换:Gson 会自动把 JSON 数据和 Java 对象的字段进行匹配。
- 高效:它处理 JSON 数据非常高效,尤其适合网络请求和响应。
总结:
Gson 就是一个用来处理 JSON 数据的工具,它让你在 Java 程序中可以轻松地和 JSON 数据打交道,把它们相互转换成 Java 对象。
使用 OkHttp3:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://api.example.com/data").build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {// 请求失败}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 请求成功,获取响应数据}
});
使用 Retrofit:
// 1. 定义接口
public interface ApiService {@GET("data")Call<Data> getData(); // 自动把响应转换成 Data 对象
}// 2. 创建 Retrofit 实例并发起请求
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()) // Gson 解析响应.build();ApiService apiService = retrofit.create(ApiService.class);
Call<Data> call = apiService.getData(); // 通过接口方法发起请求call.enqueue(new Callback<Data>() {@Overridepublic void onResponse(Call<Data> call, Response<Data> response) {// 处理响应数据,response.body() 会自动转成 Data 对象}@Overridepublic void onFailure(Call<Data> call, Throwable t) {// 请求失败}
});
总结:
- OkHttp3 是底层的工具,用来发起 HTTP 请求并处理响应。
- Retrofit 是基于 OkHttp3 的更高级工具,它让我们通过定义接口、注解和一些简化的代码来轻松发起 HTTP 请求,并且能自动解析服务器响应的数据。
HashMap 和 Gson 是两个完全不同的东西,它们有不同的用途和功能。下面我会简单地说明它们各自是什么,以及它们之间的区别。
1. HashMap:
HashMap 是一种数据结构,用于存储键值对(key-value pairs)。它将一个 键(key) 映射到一个 值(value)。你可以通过给定的 键 来快速查找、添加或删除 值。
- 用途:用于存储和查找数据。
- 操作:可以存储、查找、删除、更新键值对。
- 例子:比如你有一个字典,你可以通过查找词语(键)来获得它的解释(值)。
示例:
HashMap<String, String> map = new HashMap<>();
map.put("apple", "fruit");
map.put("dog", "animal");String value = map.get("apple"); // 获取 "apple" 对应的值 "fruit"
2. Gson:
Gson 是一个用于将 Java 对象转换为 JSON 格式(序列化)和将 JSON 格式转换回 Java 对象(反序列化)的库。JSON 是一种轻量级的数据交换格式,广泛用于网络请求和响应中。
- 用途:用于在 Java 对象和 JSON 数据之间进行转换。
- 操作:将 Java 对象转换为 JSON 格式,或者将 JSON 格式的数据转换为 Java 对象。
- 例子:当你从服务器获取 JSON 数据时,可以使用 Gson 将 JSON 转换为 Java 对象,或者将 Java 对象转换为 JSON 发送到服务器。
示例:
// 将 Java 对象转换为 JSON 字符串
Person person = new Person("John", 30);
Gson gson = new Gson();
String json = gson.toJson(person); // 转换成 JSON 字符串// 将 JSON 字符串转换为 Java 对象
String jsonString = "{\"name\":\"John\",\"age\":30}";
Person personFromJson = gson.fromJson(jsonString, Person.class);
3. HashMap 和 Gson 的区别:
-
类型和功能:
- HashMap 是一个数据结构,用来存储键值对(key-value pairs),用于高效查找、添加和删除数据。
- Gson 是一个库,用来处理 JSON 和 Java 对象之间的转换。它不直接存储数据,只是帮助将数据转换成 JSON 格式,或者从 JSON 转换回 Java 对象。
-
用途:
- HashMap 用于存储和管理键值对数据,像是字典一样。
- Gson 用于将对象和 JSON 格式之间进行转换,通常用于网络请求和响应。
-
使用场景:
- HashMap 用于程序内部存储临时数据,并根据键快速查找对应的值。
- Gson 用于与外部系统(例如服务器)交换数据,或者存储/传输数据时使用 JSON 格式。
4. 总结:
- HashMap 是一个数据结构,用于存储键值对(key-value pairs),类似字典的功能。
- Gson 是一个用于 对象和 JSON 数据 相互转换的工具库。
Interceptor
是 OKHttp 中的一个强大工具,它允许你拦截和修改 HTTP 请求和响应。你可以使用 Interceptor
来实现一些常见功能,比如记录日志、修改请求头、重试机制、缓存控制等。
使用 Interceptor
的步骤
1. 创建一个 Interceptor
Interceptor
是一个接口,有两个主要的方法:
intercept(Chain chain)
:这个方法用于拦截请求,可以在这里修改请求和响应
// 导入 OkHttp 的相关类,Interceptor 用于拦截和修改请求和响应
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;// 创建一个 LoggingInterceptor 类,它实现了 OkHttp 的 Interceptor 接口
public class LoggingInterceptor implements Interceptor {// 重写 intercept 方法,这个方法会在请求发出之前和响应返回之后执行@Overridepublic Response intercept(Chain chain) throws IOException {// 获取原始的 HTTP 请求对象Request request = chain.request();// 打印请求的 URL 地址System.out.println("Request URL: " + request.url());// 打印请求的所有头部信息,例如 User-Agent,Content-Type 等System.out.println("Request Headers: " + request.headers());// 继续发送这个请求,获取响应。这里的 `chain.proceed(request)` 就是实际执行请求的地方Response response = chain.proceed(request);// 打印响应的状态码(例如 200 表示成功)System.out.println("Response Code: " + response.code());// 打印响应的头部信息System.out.println("Response Headers: " + response.headers());// 返回响应对象,这一步很重要,必须返回响应以继续正常流程return response;}
}
流程图:
- 请求 → 拦截器 1 → 拦截器 2 → 网络请求 → 网络拦截器 → 拦截器 2 → 拦截器 1 → 响应返回应用。
拦截器的执行顺序(请求):
假设我们有以下两个拦截器:
LoggingInterceptor
(打印请求信息)HeaderInterceptor
(添加额外的 header)
假设添加顺序如下:
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new LoggingInterceptor()) // 第一个拦截器.addInterceptor(new HeaderInterceptor()) // 第二个拦截器.build();
LoggingInterceptor
会先执行,打印请求的 URL、头部等信息。- 然后,
HeaderInterceptor
会执行,向请求中添加额外的 header(比如授权信息)。
public class LoggingInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request(); // 获取原始请求System.out.println("Request URL: " + request.url());// 继续执行请求Response response = chain.proceed(request);System.out.println("Response Code: " + response.code());return response;}
}public class HeaderInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request originalRequest = chain.request();Request modifiedRequest = originalRequest.newBuilder().addHeader("Authorization", "Bearer some_token") // 添加一个header.build();// 继续请求return chain.proceed(modifiedRequest);}
}
import okhttp3.*;import java.io.IOException;public class ComplexInterceptorExample {public static void main(String[] args) throws Exception {// 创建 OkHttpClient 并添加多个拦截器OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new LoggingInterceptor()) // 第一个拦截器 - 日志.addInterceptor(new HeaderInterceptor()) // 第二个拦截器 - 添加header.addInterceptor(new CustomInterceptor()) // 第三个拦截器 - 自定义处理.build();// 创建请求Request request = new Request.Builder().url("https://jsonplaceholder.typicode.com/posts").build();// 发送请求client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {System.out.println("请求失败: " + e.getMessage());}@Overridepublic void onResponse(Call call, Response response) throws IOException {System.out.println("最终响应: " + response.body().string());}});}// 第一个拦截器:日志拦截器static class LoggingInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request(); // 获取原始请求System.out.println("日志拦截器: 请求 URL: " + request.url());// 打印请求的头信息System.out.println("日志拦截器: 请求头: " + request.headers());// 继续请求Response response = chain.proceed(request);// 打印响应的状态码System.out.println("日志拦截器: 响应码: " + response.code());// 返回响应return response;}}// 第二个拦截器:添加 Headerstatic class HeaderInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request originalRequest = chain.request();// 在请求头添加自定义的 Authorization tokenRequest modifiedRequest = originalRequest.newBuilder().addHeader("Authorization", "Bearer some_token").build();// 打印修改后的请求头System.out.println("Header拦截器: 添加了 Authorization header");// 继续请求return chain.proceed(modifiedRequest);}}// 第三个拦截器:模拟延迟处理static class CustomInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();System.out.println("Custom拦截器: 在请求前做一些处理");// 模拟延迟处理try {Thread.sleep(1000); // 假设在此做了一些长时间处理} catch (InterruptedException e) {e.printStackTrace();}// 继续发送请求Response response = chain.proceed(request);// 模拟响应后处理System.out.println("Custom拦截器: 在响应后做一些处理");// 返回响应return response;}}
}
Retrofit 拦截器的工作原理
- 拦截器的作用:拦截器可以在请求被发送到服务器之前和响应被返回给应用之前进行拦截。这使得它能够修改请求和响应,比如添加自定义的请求头、打印日志、处理缓存等。
- 拦截器的类型:OkHttp 拦截器主要分为两种:
- 应用拦截器:它可以访问整个请求和响应,并可以修改它们。应用拦截器是一次性拦截请求或响应的。
- 网络拦截器:它与应用拦截器不同,网络拦截器允许你访问底层网络响应(例如,查看重定向和缓存的响应)。
如何在 Retrofit 中使用拦截器
-
创建拦截器: 你可以创建一个自定义的拦截器类,来控制请求和响应的行为。
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;public class LoggingInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {// 获取请求Request request = chain.request();// 打印请求信息System.out.println("Request URL: " + request.url());System.out.println("Request Headers: " + request.headers());// 执行请求并获取响应Response response = chain.proceed(request);// 打印响应信息System.out.println("Response Code: " + response.code());System.out.println("Response Headers: " + response.headers());// 返回响应return response;}
}
将拦截器添加到 Retrofit: 使用 OkHttp 的拦截器机制,我们可以将这个拦截器添加到 Retrofit 实例中。拦截器会在每个请求的生命周期中起作用。
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;public class RetrofitInstance {private static Retrofit retrofit = null;public static Retrofit getRetrofitInstance() {if (retrofit == null) {// 创建 OkHttpClient 实例并添加拦截器OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new LoggingInterceptor()) // 添加自定义拦截器.build();// 创建 Retrofit 实例并返回retrofit = new Retrofit.Builder().baseUrl("https://jsonplaceholder.typicode.com/").client(client) // 将 OkHttpClient 添加到 Retrofit 中.addConverterFactory(GsonConverterFactory.create()) // 添加转换器.build();}return retrofit;}
}
使用 Retrofit 发起请求: 一旦你将拦截器添加到 Retrofit 中,它将自动应用于所有通过 Retrofit 发起的请求。
public interface ApiService {@GET("posts")Call<List<Post>> getPosts();
}// 使用 Retrofit 实例发送请求
ApiService apiService = RetrofitInstance.getRetrofitInstance().create(ApiService.class);
Call<List<Post>> call = apiService.getPosts();call.enqueue(new Callback<List<Post>>() {@Overridepublic void onResponse(Call<List<Post>> call, Response<List<Post>> response) {// 请求成功}@Overridepublic void onFailure(Call<List<Post>> call, Throwable t) {// 请求失败}
});
1. HttpURLConnection
HttpURLConnection
是 Android 中最基础的 HTTP 请求方式,用于从服务器获取数据或发送数据。它是 Java 自带的类,适用于大多数简单的 HTTP 请求。
使用示例:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;public class HttpURLConnectionExample {public static void main(String[] args) throws Exception {// 目标网址URL url = new URL("https://api.example.com/data");// 打开连接HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 设置请求方式connection.setRequestMethod("GET");// 设置连接超时和读取超时connection.setConnectTimeout(5000);connection.setReadTimeout(5000);// 添加请求头(headers)connection.setRequestProperty("User-Agent", "Mozilla/5.0");connection.setRequestProperty("Accept", "application/json");connection.setRequestProperty("Authorization", "Bearer YOUR_ACCESS_TOKEN");// 获取响应码int responseCode = connection.getResponseCode();System.out.println("Response Code: " + responseCode);// 如果响应码是200(表示成功),读取响应内容if (responseCode == HttpURLConnection.HTTP_OK) {BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String inputLine;StringBuffer response = new StringBuffer();while ((inputLine = in.readLine()) != null) {response.append(inputLine);}in.close();System.out.println("Response Content: " + response.toString());} else {System.out.println("Request failed");}// 关闭连接connection.disconnect();}
}
解释:
- URL: 请求的地址。
- HttpURLConnection: 用来创建 HTTP 连接。
- setRequestMethod("GET"): 设置请求方式(GET、POST 等)。
- getResponseCode(): 获取服务器响应的 HTTP 状态码(例如 200 表示成功,404 表示未找到页面)。
- getInputStream(): 获取服务器响应的内容。
- disconnect(): 关闭连接。
优缺点:
- 优点:比较简单、轻量,适合一般的网络请求。
- 缺点:API 较为底层,处理起来不如一些第三方库方便,且不支持很多现代化功能(例如请求体处理、文件上传等)。
2. HttpClient
HttpClient
是 Apache 提供的一个 HTTP 客户端库,可以用来发送 HTTP 请求。它比 HttpURLConnection
功能更强大,支持更丰富的功能(如请求重试、认证、文件上传等)。
在 Android 中,HttpClient
已经被废弃,但很多老版本的 Android 应用还是使用它。如果你要使用 HttpClient,需要将其作为依赖库导入。
使用示例:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;public class HttpClientExample {public static void main(String[] args) throws Exception {// 创建 HttpClient 实例CloseableHttpClient client = HttpClients.createDefault();// 创建 GET 请求HttpGet request = new HttpGet("https://api.example.com/data");// 设置请求头参数request.setHeader("User-Agent", "Mozilla/5.0");request.setHeader("Accept", "application/json");request.setHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN");// 执行请求CloseableHttpResponse response = client.execute(request);// 获取响应内容HttpEntity entity = response.getEntity();String content = EntityUtils.toString(entity);// 打印响应内容System.out.println("Response Content: " + content);// 关闭连接response.close();client.close();}
}
解释:
- HttpClients.createDefault(): 创建一个默认的
HttpClient
实例。 - HttpGet: 创建一个 GET 请求。
- execute(request): 执行 HTTP 请求并获取响应。
- EntityUtils.toString(entity): 从响应中提取字符串数据。
优缺点:
- 优点:功能强大、灵活,适合复杂的请求(如带有认证的请求、文件上传等)。
- 缺点:不再推荐使用,因为 Android 已经移除了
HttpClient
,并且它的性能较HttpURLConnection
更差。
1. BufferedReader 是什么?
想象一下,你在用吸管喝水。吸管就像是 BufferedReader
,它帮助你顺畅地喝水,而不是每次喝一点点。BufferedReader
就是一个帮你快速从大杯子里喝水的吸管,它能一次性把很多水(文本)都吸到嘴里,不需要你每次都喝一点点。
2. getInputStream 是什么?
假设你打开了一瓶饮料,这瓶饮料代表了一个连接,比如网络连接。getInputStream()
就像是打开瓶子后,你从瓶子里倒饮料(数据)出来喝。这时,你得到的饮料是字节流,它是一些看不懂的“数字”,就像是瓶子里的水看不出来是什么口味一样。
3. InputStreamReader 是什么?
现在你有了“饮料”(字节流),但是你还是不清楚它是什么味道,因为它是“数字”。为了知道它是什么味道,你需要一个工具,这个工具叫做 InputStreamReader
。它可以把这些“数字”转换成你能理解的“文字”或者“味道”,让你知道你喝的到底是什么。
4. 怎么一起使用这些东西?
假设你在喝饮料,整个过程是这样:
- 打开瓶子(通过
getInputStream()
获取字节流)。 - 倒出来(通过
InputStreamReader
把字节流转化为我们能理解的文字)。 - 吸管(
BufferedReader
)帮你一口气喝更多的水(高效读取文字)。
例子:
假设你想从互联网上读取数据(就像喝一瓶饮料),我们如何做呢?
getInputStream()
就像打开瓶子,获取网络上的数据。InputStreamReader
就是一个工具,可以把原本难懂的字节“数字”转换成你能读懂的“文字”。BufferedReader
就是帮你高效、快速读取每一口“文字”的吸管。
代码例子:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;public class Example {public static void main(String[] args) {try {// 就像打开瓶子,准备读取数据URL url = new URL("https://api.example.com/data");// 让连接到网络HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 获取网络数据(字节流)InputStreamReader inputStreamReader = new InputStreamReader(connection.getInputStream());// 使用BufferedReader(吸管)来读取数据(每次读取一口)BufferedReader reader = new BufferedReader(inputStreamReader);String line;StringBuilder response = new StringBuilder();// 一口一口地读取数据,直到全部读取完while ((line = reader.readLine()) != null) {response.append(line);}// 打印读取到的内容System.out.println(response.toString());// 关闭连接reader.close();connection.disconnect();} catch (IOException e) {e.printStackTrace();}}
}
总结:
getInputStream
: 就像是打开瓶子,获取饮料(数据)。InputStreamReader
: 就像是一个工具,可以把“数字”变成“文字”。BufferedReader
: 就像是吸管,帮你一次性高效地喝掉更多的饮料(读取更多的文字)。
什么是 SOAP?
SOAP(全名是 Simple Object Access Protocol)是一种用来在不同的系统之间交换信息的 协议,特别是在网络上交换数据时非常有用。它通常用于 Web 服务,Web 服务就是不同应用程序之间通过网络进行交流的一种方式。
举个例子:
想象一下,你有一个应用程序,它需要向另一个应用程序请求信息。你可能想要知道天气、股市数据,或者查询数据库里的数据。为了让两个应用程序能够互相交流,它们就需要一种 “通用的语言” 来进行数据交换,这就是 SOAP。
SOAP 的特点:
-
XML格式: SOAP 使用 XML(可扩展标记语言)作为消息的格式。XML 是一种类似于 HTML 的标记语言,可以用来表示结构化的数据。
-
通过 HTTP 传输: SOAP 消息通常是通过 HTTP 发送的,这意味着它可以在 Internet 或 Intranet 上使用。
-
协议无关: SOAP 是一个协议,意味着它独立于操作系统、编程语言和其他技术。只要你的系统支持 HTTP,你就能使用 SOAP。
SOAP 的结构:
SOAP 消息包含几个重要的部分,主要是:
-
Envelope(信封):这是 SOAP 消息的外层包装,用来包含消息的所有内容。
-
Header(头部):可选部分,包含一些消息的元信息(比如认证信息等)。
-
Body(主体):消息的主要内容,就是你要传输的数据。
SOAP 消息的例子:
下面是一个简单的 SOAP 请求消息的例子,使用 XML 格式表示:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:web="http://www.example.com/"><soapenv:Header/><soapenv:Body><web:GetWeather><web:CityName>Shanghai</web:CityName></web:GetWeather></soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope>
:是消息的信封,告诉接收方这个消息是一个 SOAP 消息。<soapenv:Body>
:是消息的主体部分,包含了你要传递的数据。在这里,我们请求获取天气信息。<web:GetWeather>
和<web:CityName>
:是你请求的 Web 服务的方法和参数。在这个例子中,你请求的是获取上海的天气。
是的,xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
是固定的,通常不需要更改。
为什么是固定的?
http://schemas.xmlsoap.org/soap/envelope/
这个 URL 指定了 SOAP 协议的标准格式和结构,它是 SOAP 消息的 命名空间。这个命名空间定义了 SOAP 消息的信封(Envelope),其中包括了消息的头(Header)和主体(Body)部分,任何符合 SOAP 标准的 Web 服务都会使用这个命名空间。
-
区分不同服务的元素:如果你的 Web 服务是
http://www.example.com/
,那么在 XML 请求中,所有的与http://www.example.com/
相关的元素都应该使用web
命名空间。这样就能确保请求中不会与其他 Web 服务产生冲突。 -
中间的接口:可以认为
web
命名空间就是连接客户端和服务器之间的“桥梁”,它帮助客户端明确指向某个特定的 Web 服务,并告诉服务器客户端请求的是什么内容。
为什么使用 SOAP?
SOAP 主要用在系统之间进行跨平台通信时,因为它可以使用 HTTP 来发送消息,而 HTTP 几乎可以在所有计算机系统中使用。
SOAP 的缺点:
- 相比一些现代的技术,SOAP 可能比较复杂。
- 它需要使用 XML 来进行消息的包装,比较繁琐,且数据量大。
总结:
- SOAP 是一种标准的协议,用来让不同的计算机系统通过网络交换数据。
- 它使用 XML 格式来表示消息,发送和接收数据。
- SOAP 通常用于 Web 服务,帮助不同的平台和编程语言的应用程序进行通信。
WebService 就像是不同计算机或手机之间的一种"语言"。它让你可以用电脑和其他设备进行沟通,互相交换信息。就像你跟朋友打电话问问题,朋友把答案告诉你,但你和朋友之间得有一个共同的语言或规则来沟通。
举个例子:
假设你想知道你家附近的天气,你可以通过手机向天气公司发出一个请求:“告诉我今天的天气”。然后,天气公司会用它们的计算机把天气信息返回给你。
这个过程的中介就是 WebService。它就像一个邮递员,把你发的问题(请求)带给天气公司(计算机),然后把答案带回给你。
用通俗的话来说:
- WebService 就是一个系统,让两个不一样的设备(比如手机和电脑)通过互联网相互交流和获取数据。
- 你向 WebService 提出一个问题,WebService 会把这个问题发送到一个服务端(比如一个天气系统),然后把回答返回给你。
所以,WebService 本质上就是一种帮助不同计算机之间互相“沟通”的工具,它让你可以从远程的计算机上获取数据或服务,就像从别人那里获取信息一样。
要使用 WebService 在 Android 上进行通信,通常我们会使用 SOAP
或 REST
这两种方式。下面是用 Android 调用 WebService 的一个简单例子,使用 SOAP 协议:
1. 添加依赖项
在 build.gradle
文件中,添加 SOAP 支持的库:
implementation 'com.koushikdutta.async:http:2.0.1'
2. SOAP WebService 调用代码
// 导入必要的库
import android.os.AsyncTask; // 用于异步执行任务
import android.os.Bundle; // 用于处理活动生命周期
import android.widget.TextView; // 用于显示文本信息
import androidx.appcompat.app.AppCompatActivity; // 用于支持现代 Android 活动
import org.ksoap2.SoapEnvelope; // 用于处理 SOAP 协议消息
import org.ksoap2.serialization.SoapObject; // 用于构建 SOAP 请求对象
import org.ksoap2.transport.HttpTransportSE; // 用于发送 SOAP 请求// 创建 MainActivity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity {// 定义 WebService 的相关常量private static final String NAMESPACE = "http://www.example.com/"; // WebService 的命名空间private static final String URL = "http://www.example.com/webservice"; // WebService 的 URLprivate static final String SOAP_ACTION = "http://www.example.com/GetWeather"; // SOAP 动作private static final String METHOD_NAME = "GetWeather"; // WebService 的方法名称private TextView textView; // 创建一个 TextView 变量用于显示结果@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); // 调用父类的 onCreate 方法setContentView(R.layout.activity_main); // 设置布局文件textView = findViewById(R.id.textView); // 获取布局中的 TextView// 执行异步任务来调用 WebServicenew WebServiceTask().execute(); // 执行 WebServiceTask 异步任务}// 定义一个异步任务类,用于调用 WebServiceprivate class WebServiceTask extends AsyncTask<Void, Void, String> {// doInBackground 方法在后台线程执行@Overrideprotected String doInBackground(Void... params) {try {// 创建 SOAP 请求对象,指定 WebService 的命名空间和方法名SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);// 添加请求参数(城市名称)request.addProperty("CityName", "Shanghai");// 创建 SOAP 包装对象,用于封装请求SoapEnvelope envelope = new SoapEnvelope(SoapEnvelope.VER11); // 使用 SOAP 1.1 版本envelope.setOutputSoapObject(request); // 设置请求对象// 创建 HTTP 请求传输对象,用于向 WebService 发送请求HttpTransportSE transport = new HttpTransportSE(URL); // 使用指定的 URLtransport.call(SOAP_ACTION, envelope); // 发送请求,调用 SOAP 方法// 获取 WebService 返回的响应SoapObject response = (SoapObject) envelope.getResponse(); // 获取响应对象return response.getProperty(0).toString(); // 获取响应的第一个属性值(即返回的天气信息)} catch (Exception e) {e.printStackTrace(); // 如果发生错误,打印异常信息return "Error"; // 返回错误信息}}// onPostExecute 方法在主线程执行,用于更新 UI@Overrideprotected void onPostExecute(String result) {// 在 UI 上显示 WebService 返回的结果textView.setText(result); // 将结果显示在 TextView 中}}
}
代码的解释:
private static final String NAMESPACE = "http://www.example.com/"; // WebService 的命名空间
private static final String URL = "http://www.example.com/webservice"; // WebService 的 URL
private static final String SOAP_ACTION = "http://www.example.com/GetWeather"; // SOAP 动作
private static final String METHOD_NAME = "GetWeather"; // WebService 的方法名称
- NAMESPACE:是 WebService 的命名空间,用来区分不同 WebService 的方法。它类似于一个标签,帮助服务器识别你请求的是哪个服务。
- URL:是 WebService 服务器的地址,告诉你请求的服务在哪儿。
- SOAP_ACTION:是 WebService 对应的动作,类似于方法,告诉服务器你要做的具体操作。
- METHOD_NAME:表示你请求的具体方法名,告诉服务器你想做什么(例如查询天气、获取数据等)。
总结:
- URL:指向服务器的地址,就像你去某个地方的门牌号。
- METHOD_NAME:表示你想做什么(比如查询天气,叫做
GetWeather
)。 - 请求参数:告诉 WebService 你需要哪些数据(例如城市名
Shanghai
)。
1. WebService 端 (模拟):
为了理解 WebService 调用,我们可以先创建一个简单的 WebService 端。假设 WebService 提供一个天气查询接口,客户端通过 SOAP 请求发送城市名称,WebService 返回该城市的天气。
示例 WebService (假设已发布在服务器上)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.example.com/"><soapenv:Header/><soapenv:Body><web:GetWeather><web:CityName>Shanghai</web:CityName></web:GetWeather></soapenv:Body>
</soapenv:Envelope>
这个示例包含一个 GetWeather
方法,它接受一个 CityName
参数,返回该城市的天气。
服务器端实现代码(示例):
为了在服务器端返回 Shanghai
的天气信息,你需要在 WebService 服务端编写代码来接收 SOAP 请求并返回响应。这里我们假设使用 Java 和 JAX-WS
来实现一个简单的 WebService。
import javax.jws.WebMethod;
import javax.jws.WebService;@WebService
public class WeatherService {// 定义一个方法,模拟获取城市天气@WebMethodpublic String GetWeather(String CityName) {// 根据城市名称返回天气信息(这里只是一个简单的示例)if ("Shanghai".equalsIgnoreCase(CityName)) {return "Temperature in Shanghai: 25°C"; // 返回天气信息} else {return "City not found"; // 返回未找到城市的信息}}
}
2. 客户端 (Android 中调用 WebService):
这个 Android 客户端代码通过 ksoap2
库发送 SOAP 请求,调用 WebService,并展示返回结果。
WebService 调用代码:
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.transport.HttpTransportSE;public class MainActivity extends AppCompatActivity {// WebService 的相关常量private static final String NAMESPACE = "http://www.example.com/"; // WebService 的命名空间private static final String URL = "http://www.example.com/webservice"; // WebService 的 URLprivate static final String SOAP_ACTION = "http://www.example.com/GetWeather"; // SOAP 动作private static final String METHOD_NAME = "GetWeather"; // WebService 的方法名称private TextView textView; // 显示结果的 TextView@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); // 设置布局文件textView = findViewById(R.id.textView); // 获取 TextView 实例// 执行异步任务来调用 WebServicenew WebServiceTask().execute(); // 执行任务}// 定义一个异步任务,用于调用 WebServiceprivate class WebServiceTask extends AsyncTask<Void, Void, String> {// 在后台线程执行 WebService 调用@Overrideprotected String doInBackground(Void... params) {try {// 创建 SOAP 请求对象,指定命名空间和方法名SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);// 添加请求参数(城市名称)request.addProperty("CityName", "Shanghai");// 创建 SOAP 包装对象SoapEnvelope envelope = new SoapEnvelope(SoapEnvelope.VER11); // 使用 SOAP 1.1 版本envelope.setOutputSoapObject(request); // 设置请求对象// 创建 HTTP 请求传输对象HttpTransportSE transport = new HttpTransportSE(URL);transport.call(SOAP_ACTION, envelope); // 发送请求并获取响应// 获取响应结果SoapObject response = (SoapObject) envelope.getResponse();return response.getProperty(0).toString(); // 返回天气信息} catch (Exception e) {e.printStackTrace(); // 出现错误时打印异常return "Error"; // 返回错误信息}}// 在主线程更新 UI@Overrideprotected void onPostExecute(String result) {textView.setText(result); // 显示 WebService 返回的结果}}
}
相关文章:
安卓基础(持续更新的笔记)
为什么要这样: // 创建请求体RequestBody body RequestBody.create(MediaType.parse("application/json; charsetutf-8"),jsonObject.toString()); jsonObject 就包含了一个 JSON 数据,它其实就是: {"name": "张…...
大模型Deepseek的使用_基于阿里云百炼和Chatbox
目录 前言1. 云服务商2. ChatBox参考 前言 上篇博文中探索了(本地)部署大语言模型,适合微调、数据高隐私性等场景。随着Deepseek-R1的发布,大语言模型的可及性得到极大提升,应用场景不断增加,对高可用的方…...
数学建模基础训练-1:概念解析
文章目录 数学建模基础训练-1:概念解析问题一:如何找到“概念”?问题二:如何全面理解概念的基础含义?问题三:如何深刻理解概念并作出创新点发掘?实际举例问题一 :研究并给出寒假开学某大学返校交…...
【mybatis】基本操作:详解Spring通过注解和XML的方式来操作mybatis
mybatis 的常用配置 配置数据库连接 #驱动类名称 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #数据库连接的url spring.datasource.urljdbc:mysql://127.0.0.1:3306/mybatis_test characterEncodingutf8&useSSLfalse #连接数据库的名 spring.datasourc…...
联邦学习中的“参数聚合“机制详解:医疗数据隐私保护的技术实现路径
一、技术原理:参数聚合的数学本质 1.1 核心数学公式 联邦平均算法(FedAvg): \theta_{global}^{t1} \sum_{k1}^K \frac{n_k}{N} \theta_k^t其中: K K K:参与本轮训练的客户端数量 n k n_k nkÿ…...
LVS 负载均衡集群(NAT模式)
一、环境准备 四台主机(一台 LVS、两台 RS、一台客户端) 注意每个虚拟机都需要关闭防火墙和 selinux 1.1.LVS 主机 LVS 主机(两块网卡) 第一块:NAT模式(内网) 第二块:添加网卡&am…...
Rocky Linux系统修改网卡全攻略
Rocky Linux系统修改网卡全攻略 Rocky Linux系统修改网卡全攻略一、了解网卡相关知识二、查看当前网卡配置(一)使用ip命令(二)使用ifconfig命令(需安装)三、修改网卡配置文件(一)修改IP地址(二)修改网关和DNS服务器(三)保存并退出配置文件四、重启网络服务使配置生…...
常用查找算法整理(顺序查找、二分查找、哈希查找、二叉排序树查找、平衡二叉树查找、红黑树查找、B树和B+树查找、分块查找)
常用的查找算法: 顺序查找:最简单的查找算法,适用于无序或数据量小的情况,逐个元素比较查找目标值。二分查找:要求数据有序,通过不断比较中间元素与目标值,将查找范围缩小一半,效率…...
自动化办公|xlwings 数据类型和转换
xlwings 数据类型和转换:Python 与 Excel 的桥梁 在使用 xlwings 进行 Python 和 Excel 数据交互时,理解两者之间的数据类型对应关系至关重要。本篇将详细介绍 Python 数据类型与 Excel 数据类型的对应关系,以及如何进行数据类型转换。 一、…...
Edge浏览器清理主页
我们都知道,Microsoft Edge浏览器是微软创造的搜索浏览器,Windows10、11自带。但是你可以看到,每次你打开Edge浏览器的时候都可以看到许多的广告,如图: 导致打开Edge浏览器的时候会遭受卡顿,广告骚扰&#…...
RedHat8安装postgresql15和 postgis3.4.4记录及遇到的问题总结
安装包对照版本参考 UsersWikiPostgreSQLPostGIS – PostGIS 如果Red Hat系统上有旧版本的PostgreSQL需要卸载 在较新的Red Hat版本,使用dnf包管理器卸载:sudo dnf remove postgresql-server postgresql 旧版本,使用yum包管理器卸载 sudo y…...
Java 大视界 -- 绿色大数据:Java 技术在节能减排中的应用与实践(90)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
Python 文本探秘:正则表达式的易错迷宫穿越 -- 7. 正则表达式
正则表达式是 Python 中处理文本的强大武器,但它复杂的语法和规则构成了一个易错迷宫。本文深入剖析了正则表达式模式编写的错误、匹配规则的误解、性能优化的忽视等问题。通过大量的文本处理实例,展示了错误的正则表达式使用方式以及正确的解决方案。帮…...
Ubuntu22.04通过Docker部署Jeecgboot
程序发布环境包括docker、mysql、redis、maven、nodejs、npm等。 一、安装docker 1、用如下命令卸载旧Docker: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done 2、安装APT环境依赖包…...
数据结构 二叉树
一、⼆叉树的定义 ⼆叉树是⼀种特殊的树型结构,它的特点是每个结点⾄多只有2棵⼦树(即⼆叉树中不存在度⼤于2的结点),并且⼆叉树的⼦树有左右之分,其次序不能任意颠倒。 ⼆叉的意思是这种树的每⼀个结点最多只有两个孩…...
基于python sanic框架,使用Nacos进行微服务管理
微服务软件系统构建方式,已经很普及了,通过开源的sanic进行微服务管理,便捷,技术也比较成熟,而在项目实际应用过程中,微服务类型不仅有java的,还有nodejs、python等,尤其是结合算法模型构建的python接口,需要在Nacos进行注册管理。本文内容耗时2天踏坑,亲测一切ok。 …...
hbase合并队列超长问题分析
问题现象 hbase集群合并队列超长,有节点上合并任务已经运行超过1天未结束,合并队列总长不断增加。 问题分析 参数配置: 配置参数默认值含义hbase.hregion.memstore.flush.size128MMemStore达到该值会Flush成StoreFilehbase.hregion.memstore.block.multiplier4当region中…...
【设计模式】【行为型模式】解释器模式(Interpreter)
👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 🎵 当你的天空突…...
DeepSeek-R1 蒸馏 Qwen 和 Llama 架构 企业级RAG知识库
“DeepSeek-R1的输出,蒸馏了6个小模型”意思是利用DeepSeek-R1这个大模型的输出结果,通过知识蒸馏技术训练出6个参数规模较小的模型,以下是具体解释: - **知识蒸馏技术原理**:知识蒸馏是一种模型压缩技术,核…...
无人机航迹规划:互联银行系统优化(Connected Banking System Optimizer,CBSO)求解无人机路径规划MATLAB
一、互联银行系统优化算法 互联银行系统优化(Connected Banking System Optimizer,CBSO)算法是2024年由Mehrdad Nemati等人提出的一种智能优化算法,其灵感来源于银行系统之间的连接和交易过程。在银行系统中,核心银行…...
学习web数据埋点
什么是埋点,以及为什么需要埋点 通过代码主动收集用户行为数据(如点击、浏览、停留时长等),用于数据分析驱动产品优化。 一、前端埋点 在客户端(浏览器、移动端应用)直接采集用户行为数据,通…...
Windows 11 安装 Docker
1.以管理员身份打开 Windows PowerShell 2.执行下面三行命令来启动WSL和虚拟机平台 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestartdism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norest…...
深度学习框架探秘|Keras:深度学习的魔法钥匙
一、引言:深度学习浪潮中的 Keras 前面的文章我们探秘了深度学习框架中的两大明星框架 —— TensorFlow 和 PyTorch 以及 两大框架的对比 在深度学习的众多框架中,还有一款框架备受开发者们的喜爱 —— Keras 。它就像是一位贴心的助手,为我…...
HTML【详解】input 标签
input 标签主要用于接收用户的输入,随 type 属性值的不同,变换其具体功能。 通用属性 属性属性值功能name字符串定义输入字段的名称,在表单提交时,服务器通过该名称来获取对应的值disabled布尔值禁用输入框,使其无法被…...
在vscode中拉取gitee里的项目并运行
拉取项目: 方法一:vscode点击查看--->终端(或者直接通过快捷键ctrol+ `打开) 在终端内通过cd命令定位到你想存放项目的文件夹 例如:cd h: 通过命令:git clone 地址 例如:git clone newbee-mall-vue-app: 前端代码 等待拉取完成即可在对应文件夹下看到项目啦 方…...
Spring Cloud微服务
一、定义 微服务,又叫微服务架构,也就是分布式架构,是软件架构的一种方式。它将一个大的单体架构应用拆分成一系列按业务领域划分模块的、小的自治服务。 如开发部有很多任务,如果把任务给了一个组的话,效率肯定会降低…...
打破AI黑盒,拥抱开源力量:基于openGauss+DeepSeek的本地知识库,打造你的专属AI助手!
引言:什么是RAG和LLM? LLM (Large Language Model,大语言模型): 就像 ChatGPT 这样的 AI 模型,拥有强大的语言理解和生成能力,但它们的知识局限于训练数据,且可能产生“幻觉”(即生成不准确的信…...
如何在 IntelliJ IDEA 中使用 Bito AI 插件
如何在 IntelliJ IDEA 中使用 Bito AI 插件 Bito: On-Demand AI Code Reviews Bito AI 插件是一个智能开发工具,能够帮助开发者提升编码效率,自动化生成代码、注释、单元测试等。本文将详细介绍 Bito AI 插件在 IntelliJ IDEA 中的使用方法,…...
用xml配置spring, bean标签有哪些属性?
用xml配置spring, bean标签有哪些属性? 在Spring框架中,使用XML配置文件时,<bean>标签用于定义一个Bean。以下是一些常用的<bean>标签属性: 1. class 描述:指定Bean的类名。示例:<bean id"myBe…...
微信小程序中缓存数据全方位解惑
微信小程序中缓存数据全方位解惑 微信小程序中的数据缓存是提升用户体验和优化性能的重要手段,跟电脑浏览器中的Local Storage的性质一样。以下是关于微信小程序数据缓存的相关知识点和示例的详细介绍: 1. 数据缓存的类型 微信小程序提供了两种数据缓…...
物联网平台-分布式的设备接入与管理系统
乐吾乐物联网平台是由乐吾乐自主研发的一款分布式的设备接入与管理系统,专为满足不断增长的设备接入和数据处理需求而设计。平台集数据采集、分析、监控、告警和通知等功能于一体,并融合了乐吾乐大屏可视化和乐吾乐3D数字孪生技术,帮助用户快…...
ABP - 事件总线之分布式事件总线
ABP - 事件总线之分布式事件总线 1. 分布式事件总线的集成1.2 基于 RabbitMQ 的分布式事件总线 2. 分布式事件总线的使用2.1 发布2.2 订阅2.3 事务和异常处理 3. 自己扩展的分布式事件总线实现 事件总线可以实现代码逻辑的解耦,使代码模块之间功能职责更清晰。而分布…...
ComfyUI流程图生图原理详解
一、引言 ComfyUI 是一款功能强大的工具,在图像生成等领域有着广泛应用。本文补充一点ComfyUI 的安装与配置过程遇到的问题,并深入剖析图生图过程及相关参数,帮助读者快速入门并深入理解其原理。 二、ComfyUI 的安装与配置中遇到的问题 &a…...
洛谷 P3660 USACO17FEB Why Did the Cow Cross the Road III 题解
题意 有一个圆,圆周上按顺时针方向给出 2 n 2n 2n个点。第 i i i个点的颜色是 c o l o r i color_i colori,其中数据保证 1 ≤ c o l o r i ≤ n 1\le color_i\le n 1≤colori≤n,而且每种不同的颜色有且只有两个点。不存在位置重叠的点…...
kubekey一键部署k8s高可用与kubesphere
kubekey一键安装k8s与kubesphere还是蛮方便的,kubesphere官网上面也提到了高可用安装的一些事宜,但是没有涉及到kubesphere资深的redis的系统的部署问题,本文简单给出对应配置,其实这个配置在kubephere的cluster-configuration.ya…...
SwiftUI 5.0 中宝藏视图修改器 containerRelativeFrame 趣谈(下)
概览 小伙伴们都知道,为了将 SwiftUI 中多如牛毛的视图井然有序、有条不紊的组织起来,我们必须借助容器(Container)伏虎降龙般地威力。而如何最大限度的让容器中的子视图能根据容器尺寸安排自己的空间,则需要一些技术手段来洞幽察微。 在过去,我们往往使用 GeometryRead…...
ElasticSearch基础和使用
ElasticSearch基础 1 初识ES相关组件 (1)Elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容。Elasticsearch结合kibana、Logstash、Beats组件 也就是elastic stack(ELK) 广泛应…...
我用 Cursor 开发了一款个人小记系统
https://note.iiter.cn 项目背景 在日常工作和学习中,我们经常需要快速记录一些想法、收藏一些有用的链接或者保存一些重要的文本、图片内容。虽然市面上已经有很多笔记软件,但我想要一个更轻量、更简单的工具,专注于快速记录和智能检索。于是我开发了这款个人小记系统。 系统…...
如何使用Three.js制作3D月球与星空效果
目录 1. 基本设置2. 创建星空效果3. 创建月球模型4. 添加中文3D文字5. 光照与相机配置6. 动画与控制7. 响应式布局8. 结语 在本文中,我们将一起学习如何利用Three.js实现一个3D月球与星空的效果,并添加一些有趣的元素,比如中文3D文字和互动功…...
DeepSeek接入网络安全领域,AI高效驱动,重新定义网络防御边界!
DeepSeek新一代模型的发布,标志着AI大模型的应用将逐步走向普及,并加速AI技术在各行业的赋能与全面落地。在科技日新月异的今天,AI技术凭借其强大的数据处理与分析能力,已成为推动社会进步的核心动力。 在网络安全领域࿰…...
【动态规划】斐波那契数列模型
目录 动态规划 动态规划的基本步骤 1137. 第 N 个泰波那契数 - 力扣(LeetCode) 算法分析 算法代码 算法代码 面试题 08.01. 三步问题 - 力扣(LeetCode) 算法分析 算法代码 优化 746. 使用最小花费爬楼梯 - 力扣&#x…...
Spring中的IOC详解
文章目录 IOC IOC容器的工作原理Bean的生命周期Bean的自动装配 AutowiredResourceInject 使用Spring底层组件 IOC Spring的核心之一是IOC,IOC全称为Inversion of Control,中文译为控制反转,是面向对象编程中的一种设计原则,可…...
深挖vue3基本原理之七 —— 功能模块的深度技术解析
Vue 3 四个核心功能模块的深度技术解析 一、Effect 调度系统:同步/异步任务队列 实现原理 // runtime-core/src/scheduler.ts const queue: (EffectJob | null)[] [] let isFlushing false const resolvedPromise Promise.resolve()function queueJob(job: Ef…...
数据结构 day 07
数据结构 day07 7. 树7.3. 层次遍历代码实现 8. 查询算法8.1. 顺序查找 seqSearch代码实现 8.2. 二分法查找 binarySearch代码实现 8.2. 分块查找 blockSearch代码实现 8.3. 哈希表 hash 9. 排序算法9.1. 冒泡排序 bubSort代码实现 9.2. 选择排序 selSort代码实现 9.3. 插入排序…...
《代码随想录》刷题笔记——回溯篇【java实现】
文章目录 组合组合总和 III电话号码的字母组合组合总和组合总和II思路代码实现 分割回文串※思路字符串分割回文串判断效率优化※ 复原 IP 地址优化版本 子集子集 II使用usedArr辅助去重不使用usedArr辅助去重 递增子序列※全排列全排列 II重新安排行程题意代码 N 皇后解数独直…...
React:初识React
React是什么? React是由Meta公司研发,也就是Facebook的公司(马克扎克伯格这个见人)研发的构建Web和原生交互界面的库 不仅可以写网页,还可以写苹果和安卓上面的app React的优势: React也是前端里最流行的…...
全面理解-c++中的内存布局
在 C 中,程序的内存布局指的是程序运行时,代码和数据在内存中的组织和分布方式。一般来说,C 程序的内存可以划分为以下几个主要区域: 1. 代码段(Text Segment,也称为 .text 段) 存储内容&…...
百度沈抖:传统云计算不再是主角,智能计算呼唤新一代“操作系统”
Create 2024 百度AI开发者大会 4月16日,Create 2024 百度AI开发者大会在深圳召开。期间,百度集团执行副总裁、百度智能云事业群总裁沈抖正式发布新一代智能计算操作系统——万源,通过对AI原生时代的智能计算平台进行抽象与封装设计ÿ…...
【银河麒麟高级服务器操作系统】服务器卡死后恢复系统日志丢失-分析及处理全过程
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://document.kylinos.cn 服务器环境以及配置 【机型】 处理器ÿ…...
VSCode Error Lens插件介绍(代码静态检查与提示工具)(vscode插件)
文章目录 VSCode Error Lens 插件介绍**功能概述****开发背景****使用方法****适用场景** VSCode Error Lens 插件介绍 功能概述 Error Lens 是一款增强 VS Code 错误提示的扩展工具,通过 内联显示错误和警告信息,直接定位代码问题,提升开发…...