Java中的远程方法调用——RPC详解
1. 什么是RPC?
RPC基础介绍
Java中的远程方法调用(Remote Procedure Call,RPC)是一种允许一个程序调用另一台计算机上方法的技术,就像在本地一样。RPC的核心思想是简化分布式计算,让我们可以跨网络调用远程服务,而不需要关心底层网络细节。简单来说,在它调用另一台计算机上的方法的技术时,效果类似于调用本地方法。用一个例子来说明:
假设我们有一个客户端程序,它需要访问一个服务器上的资源,比如用户信息。使用RPC,客户端就可以像调用自己机器上的方法一样,远程调用服务器上提供的“获取用户信息”的方法。在客户端的角度,它并不知道这个方法实际在另一台机器上执行,一切都像是本地操作。
RPC背后的核心目标
RPC的目标是让分布式系统中的方法调用变得简单。通过RPC,开发者不必关心网络传输、数据格式转换等细节,只需要按照调用本地方法的方式来调用远程方法。这种透明性为分布式应用程序开发带来了极大的便利。
RPC实现了“本地调用”的效果,但它实际是在网络上完成了远程方法调用。
2. 为什么使用RPC?
在分布式系统或微服务架构中,应用程序通常被分解为多个独立的服务,每个服务都可能运行在不同的服务器上。为了实现这些服务之间的通信,我们可以使用RPC。以下是使用RPC的几个主要原因:
1. 解耦服务,提升灵活性
- RPC允许不同的服务在不同的机器上独立运行。每个服务都可以独立开发、部署和扩展。
- 使用RPC后,服务之间只通过方法调用进行交互,而不需要知道彼此的内部实现。这样,服务的实现方式可以自由改变,而不会影响到依赖它的其他服务。
2. 简化网络通信
- 在没有RPC的情况下,我们需要手动处理网络通信,比如套接字编程、序列化/反序列化数据、处理网络延迟等。
- RPC将这些网络细节都隐藏在底层,使开发者可以像调用本地方法一样简单地调用远程服务,降低了开发复杂度。
3. 提高开发效率
- 通过RPC,开发者不需要学习复杂的网络编程知识。这对跨团队协作、快速开发原型等都有帮助,极大地提升了开发效率。
4. 便于跨语言、跨平台调用
- 现代RPC协议(例如gRPC)支持不同的编程语言,能使Java客户端调用Python或Go编写的服务。
- 这让服务能够运行在不同平台上,支持多样化的技术栈,给系统设计带来了更大灵活性。
RPC为分布式系统提供了强大的跨服务、跨语言通信能力,简化了复杂的网络编程工作,使得多服务协作变得更加自然。
3. RPC的基本原理
RPC的工作过程看似简单,但它其实包含了多个步骤。在概念上,可以将RPC分为客户端请求和服务器响应两个部分,我们先简要了解流程,再详细拆解每一步的工作机制。
RPC的基本流程
- 客户端请求:客户端调用一个“本地代理方法”,这个方法会将请求传递给远程服务器。
- 网络传输:客户端将请求的数据通过网络发送到远程服务器。
- 服务器处理:服务器接收到请求,找到相应的服务方法,执行并将结果返回。
- 结果返回:服务器将结果传回客户端,客户端接收并使用结果,完成调用。
关键组成部分
要实现这一流程,RPC通常需要以下几个关键组成部分:
- 客户端代理(Client Stub):客户端的“本地代理方法”,它伪装成一个本地方法调用,背后却是将请求打包并发送给服务器。
- 服务器代理(Server Stub):服务器上的代理,它负责接收客户端请求,解包请求参数并调用实际的远程方法。
- 网络传输:负责在客户端和服务器之间传输数据,通常采用TCP/IP协议。
- 序列化与反序列化:将方法参数转换成可以传输的格式(比如JSON、XML等),并在接收到数据后反向还原成对象。
流程拆解
我们再来看一下具体每一步发生了什么:
-
方法调用(客户端代理)
- 客户端调用一个本地的“代理方法”,这个方法看似本地,但会触发远程调用。
- 代理会把调用的方法名称和参数打包,并交给下一个环节(序列化)。
-
序列化(客户端代理)
- 代理将方法名称和参数序列化为一种通用的格式(如JSON、XML),方便跨网络传输。
- 序列化后的数据包被发送到服务器。
-
数据传输(网络传输)
- 序列化数据包通过网络(一般是TCP/IP)传输到目标服务器。
- 这部分由RPC框架负责封装,使调用方无须处理底层网络操作。
-
解包与方法执行(服务器代理)
- 服务器代理接收到数据包后,先进行反序列化,将其还原为方法名称和参数。
- 然后,代理找到相应的方法,并传入参数执行。
-
返回结果
- 方法执行完毕后,结果数据被序列化,打包并通过网络返回给客户端。
- 客户端收到结果后,代理将数据反序列化,还原成方法调用结果,调用完成。
RPC通过客户端代理、服务器代理和网络传输的配合,模仿了“本地调用”的效果。每一个步骤背后都由RPC框架完成复杂的底层工作,让开发者无需关注复杂的网络细节。
4. Java中的RPC实现方式
RMI(Remote Method Invocation)
简介
RMI是Java内置的RPC实现,它允许Java应用程序之间调用远程对象,类似于本地调用。RMI只支持Java语言,因此在Java应用之间通信时相对方便,但只能用于Java环境,限制了跨语言调用。
特点
- 单一语言:只支持Java,无法在其他语言环境中使用。
- 序列化机制:基于Java自带的序列化机制,传输Java对象较为方便,但序列化性能相对较慢。
- 简单实现:因为是Java自带的API,开发和部署相对简单,不需要额外的第三方依赖。
- 同步调用:通常采用同步的调用方式,不适合高并发环境。
使用场景
RMI适用于小型Java系统之间的简单远程调用,例如在单一Java环境中做分布式处理、调用Java应用中的服务等。但是,由于其性能和跨语言局限性,它并不适合复杂的大规模微服务架构。
Hessian
简介
Hessian是一个轻量级的二进制RPC协议,支持Java与多种其他语言间的跨语言调用。Hessian使用二进制格式来传输数据,相较于文本协议(如JSON、XML)具有更好的传输性能。
特点
- 跨语言支持:Hessian提供多种语言实现,支持Java与Python、PHP等其他语言之间的通信。
- 二进制序列化:采用二进制格式,传输数据体积小,序列化与反序列化性能较高。
- 轻量级:Hessian实现较为简单,适合快速集成到应用中。
- 较好的兼容性:不依赖复杂的第三方组件,适合与微服务架构结合。
使用场景
Hessian适合跨语言、轻量级分布式系统,尤其是在服务间传递大量数据时,Hessian的二进制传输可以减少网络开销。常用于内部微服务通信,如Java与其他语言服务的接口调用,适合数据传输量较大的应用场景。
Dubbo
简介
Dubbo是阿里巴巴开源的高性能Java RPC框架,提供了更加完整的分布式服务治理功能。Dubbo不仅仅是RPC,还支持服务注册与发现、负载均衡、容错机制、监控等特性,适合构建复杂的微服务架构。
特点
- 支持服务治理:内置服务注册、发现、负载均衡、容错处理等功能,支持多种注册中心(如Zookeeper、Nacos)。
- 高性能:Dubbo采用了高效的网络协议和线程模型,能支持高并发和低延迟。
- 丰富的协议支持:Dubbo支持多种传输协议(如Dubbo协议、RMI、Hessian等),开发者可以根据需求选择。
- 支持异步调用:Dubbo支持异步调用,能够处理高并发场景。
使用场景
Dubbo适合大型微服务架构和分布式系统,特别是需要服务治理和负载均衡的复杂系统。它广泛应用于企业级分布式应用,例如电商系统的订单服务、支付服务等,支持服务的快速扩展和高性能需求。
三者对比与选择
特性 | RMI | Hessian | Dubbo |
---|---|---|---|
语言支持 | 仅支持Java | 支持Java和其他语言 | 主要支持Java |
序列化方式 | Java内置序列化 | 二进制序列化 | 支持多种协议和序列化 |
性能 | 较低 | 较高 | 高(适合高并发) |
服务治理 | 无 | 无 | 有,支持注册、发现、负载均衡等 |
适用场景 | 简单的Java远程调用 | 跨语言轻量级RPC | 大型分布式系统、微服务架构 |
- RMI:适合简单、轻量的Java系统间调用,不需要复杂的服务治理。
- Hessian:适合跨语言、轻量级服务调用,有较好的传输效率,适用于小型分布式系统。
- Dubbo:适合需要服务治理的大规模Java微服务架构,性能高、功能丰富,是企业级分布式系统的优选。
如果对多语言支持需求高,选Hessian;如果是单一Java微服务场景,选Dubbo。
5. RMI、Hessian、Dubbo的实现详解
RMI(Remote Method Invocation)
RMI是Java内置的RPC实现方式,适合Java-to-Java的远程调用。在RMI中,服务器端的远程对象可以被客户端远程调用,像在本地调用一样。下面,我们通过四个步骤来实现RMI的基本过程。
实现步骤
- 定义远程接口:指定哪些方法可以被远程调用。
- 实现远程接口:服务器端实现远程接口中的方法。
- 启动RMI服务器:将远程对象注册到RMI注册表中,以便客户端查找。
- 客户端调用远程方法:客户端通过RMI注册表查找远程对象,并调用方法。
代码示例
Step 1: 定义远程接口
首先,定义一个远程接口,继承java.rmi.Remote
,并声明抛出RemoteException
。例如,我们创建一个HelloService
接口。
import java.rmi.Remote;
import java.rmi.RemoteException;public interface HelloService extends Remote {String sayHello(String name) throws RemoteException;
}
Step 2: 实现远程接口
在服务器端,我们创建HelloService
的实现类,并实现其中的方法。
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {protected HelloServiceImpl() throws RemoteException {super();}@Overridepublic String sayHello(String name) throws RemoteException {return "Hello, " + name + "!";}
}
Step 3: 启动RMI服务器
将实现类实例化,并将其注册到RMI注册表中。这样,客户端可以通过注册表找到这个远程对象。
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;public class RMIServer {public static void main(String[] args) {try {HelloService service = new HelloServiceImpl();Registry registry = LocateRegistry.createRegistry(1099);registry.bind("HelloService", service);System.out.println("RMI server is running...");} catch (Exception e) {e.printStackTrace();}}
}
Step 4: 客户端调用远程方法
在客户端,连接到RMI注册表,查找远程对象,并调用方法。
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;public class RMIClient {public static void main(String[] args) {try {Registry registry = LocateRegistry.getRegistry("localhost", 1099);HelloService service = (HelloService) registry.lookup("HelloService");String response = service.sayHello("Alice");System.out.println("Response from server: " + response);} catch (Exception e) {e.printStackTrace();}}
}
Hessian
Hessian是一个轻量级的二进制协议,支持跨语言调用,适用于Java与其他语言间的通信。Hessian实现简单,传输数据体积小,序列化效率高。以下是Hessian的服务端与客户端实现步骤。
实现步骤
- 添加Hessian依赖:引入Maven依赖。
- 定义远程接口和实现:编写接口和实现类。
- 配置HessianServlet:暴露服务接口。
- 客户端调用远程服务:客户端通过Hessian代理调用服务。
代码示例
Step 1: 添加Hessian依赖
在Maven项目的pom.xml
中加入以下依赖。
<dependency><groupId>com.caucho</groupId><artifactId>hessian</artifactId><version>4.0.63</version>
</dependency>
Step 2: 定义远程接口和实现
定义远程接口HelloService
并实现它:
public interface HelloService {String sayHello(String name);
}
public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name) {return "Hello, " + name + "!";}
}
Step 3: 配置HessianServlet
在Web应用中使用HessianServlet
,将接口暴露为远程服务。
<!-- web.xml -->
<servlet><servlet-name>helloService</servlet-name><servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class><init-param><param-name>home-api</param-name><param-value>com.example.HelloService</param-value></init-param><init-param><param-name>home-class</param-name><param-value>com.example.HelloServiceImpl</param-value></init-param>
</servlet><servlet-mapping><servlet-name>helloService</servlet-name><url-pattern>/helloService</url-pattern>
</servlet-mapping>
Step 4: 客户端调用远程服务
客户端通过Hessian的HessianProxyFactory
代理远程服务。
import com.caucho.hessian.client.HessianProxyFactory;public class HessianClient {public static void main(String[] args) {try {String url = "http://localhost:8080/helloService";HessianProxyFactory factory = new HessianProxyFactory();HelloService service = (HelloService) factory.create(HelloService.class, url);String result = service.sayHello("Alice");System.out.println(result);} catch (Exception e) {e.printStackTrace();}}
}
Dubbo
Dubbo是一个高性能Java RPC框架,广泛应用于企业级微服务架构中。Dubbo提供了服务治理功能,支持负载均衡、服务发现、熔断等,适合大规模分布式系统。
实现步骤
- 添加Dubbo和Zookeeper依赖:引入Dubbo和Zookeeper依赖。
- 定义远程接口和实现:编写服务接口和实现类。
- 配置Dubbo注册中心和服务:使用Zookeeper等注册中心管理服务。
- 客户端调用远程服务:通过Dubbo动态代理调用服务。
代码示例
Step 1: 添加Dubbo和Zookeeper依赖
在Maven项目的pom.xml
中加入以下依赖:
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>2.7.8</version>
</dependency>
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.5.7</version>
</dependency>
Step 2: 定义远程接口和实现
和前面类似,定义HelloService
接口和实现类。
public interface HelloService {String sayHello(String name);
}
import org.apache.dubbo.config.annotation.Service;@Service // Dubbo的Service注解
public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name) {return "Hello, " + name + "!";}
}
Step 3: 配置Dubbo注册中心和服务
Dubbo支持服务注册与发现,通常使用Zookeeper作为注册中心。
<!-- Dubbo配置 -->
<dubbo:application name="HelloServiceProvider"/>
<dubbo:registry address="zookeeper://localhost:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="com.example.HelloService" ref="helloService"/>
Step 4: 客户端调用远程服务
客户端通过Dubbo的动态代理机制来调用远程服务。
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;public class DubboClient {public static void main(String[] args) {ReferenceConfig<HelloService> reference = new ReferenceConfig<>();reference.setApplication(new ApplicationConfig("HelloServiceConsumer"));reference.setRegistry(new RegistryConfig("zookeeper://localhost:2181"));reference.setInterface(HelloService.class);HelloService service = reference.get();String result = service.sayHello("Alice");System.out.println(result);}
}
总结
- RMI适合简单Java-to-Java调用。
- Hessian支持跨语言、轻量级的远程调用。
- Dubbo适合大规模分布式系统,提供服务治理功能。
每种实现方式都有独特的使用场景,选择时可根据系统需求灵活决定。
相关文章:

Java中的远程方法调用——RPC详解
1. 什么是RPC? RPC基础介绍 Java中的远程方法调用(Remote Procedure Call,RPC)是一种允许一个程序调用另一台计算机上方法的技术,就像在本地一样。RPC的核心思想是简化分布式计算,让我们可以跨网络调用远程…...

【kafka】大数据编写kafka命令使用脚本,轻巧简洁实用kafka
kafka是大数据技术中举足轻重的技术,市面上也有很多kafka的ui界面,但是都会占用比较大的内存和性能,这里我编写好了一个fakfa的脚本集成了kafka常见的命令使用。脚本资源放在文章顶部可自行拿取。 《Kafka 命令大全系统脚本使用指南》 在大数…...

交换区(Swap Area或Swap Partition)
在操作系统中,交换区(Swap Area或Swap Partition)扮演着至关重要的角色,主要用于在物理内存(RAM)不足时提供额外的虚拟内存空间。以下是交换区的主要功能和作用: 一、内存扩展 当系统的物理内…...

Excel 无法打开文件
Excel 无法打开文件 ‘新建 Microsoft Excel 工作表.xlsx",因为 文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。...

MySQL —— Innodb 索引数据结构
文章目录 不用平衡二叉树或红黑树作为索引B树适合作为索引比B树更适合作为索引的结构——B树总结 MySQL 使用 B树索引数据结构(因为默认使用 innodb 存储引擎) B树:有序数组 平衡多叉树;B树:有序数组链表 平衡多叉树…...

探索C语言数据类型
目录 前言 一、基本数据类型 1.整型(Integer) 2.浮点型(Floating - point) 3.字符型(Character) 4.布尔型(Boolean) 二、派生数据类型 1.数组(Array)…...

凌晨官宣离婚,他们为何让老粉直呼天塌?
你说的是影视飓风MediaStorm的创始人Tim和小鱼吧,他们确实在11月5日凌晨官宣离婚了。以下是具体介绍:官宣离婚2024年11月5日凌晨,影视飓风MediaStorm的创始人Tim(潘天鸿)在社交媒体上发文,宣布与小鱼&#…...

Spring Boot 导出 Excel 文件
本文将详细介绍如何使用 Spring Boot 和 Apache POI 实现 Excel 文件的导出功能,帮助开发者快速上手。 1. 准备工作 首先,确保你的 Spring Boot 项目已成功创建并运行。接下来,需要在 pom.xml 文件中添加 Apache POI 相关依赖,以…...

HTTPSOK:SSL/TLS证书自动续期工具
HTTPSOK 是一个支持 SSL/TLS 证书自动续期 的工具,旨在简化 SSL 证书的管理,尤其是自动化处理证书续期的工作。对于大多数网站而言,SSL 证书的续期是一项必要但容易被忽视的工作,因为 SSL 证书的有效期通常为 90 天。使用 HTTPSOK…...

Uniapp安装Pinia并持久化(Vue3)
安装pinia 在uni-app的Vue3版本中,Pinia已被内置,无需额外安装即可直接使用(Vue2版本则内置了Vuex)。 HBuilder X项目:直接使用,无需安装。CLI项目:需手动安装,执行yarn add pinia…...

基于Dpabi和spm12的脑脊液(csf)分割和提取笔记
一、前言 脑脊液(csf)一直被认为与新陈代谢有重要关联,其为许多神经科学研究提供重要价值,从fMRI图像中提取脑脊液信号可用于多种神经系统疾病的诊断。特别是自2019年Science上那篇著名的csf-BOLD文章发表后,大家都试图…...

【每日一题】2012考研数据结构 - 求字符串链表公共后缀
本篇文章将为大家讲解一道关于链表的经典题目——求两个链表的共同后缀节点。该问题在实际开发中同样具有很大的应用价值,是每一位数据结构学习者不可错过的重要题目。 问题描述 假设我们有一个带头结点的单链表来保存单词,每个节点包含一个字符和指向…...

数据结构和算法-贪心算法01- 认识贪心
贪心算法 什么是贪心算法 一个贪心算法总是做出当前最好的选择,也就是说,它期望通过局部最优选择从而得到全局最优的解决方案。 ----《算法导论》 贪心算法(Greedy Method): 所谓贪心算法就是重复地(或贪婪地)根据一个法则挑选解的一部分。当挑选完毕…...

Bash Shell - 获取日期、时间
1. 使用date获取日期 以下代码将date的执行结果存储在today变量中。date 是获取日期和时间的命令。 选择使用 quotes()或$ #!/bin/bashtodaydate echo $todaytoday$(date) echo $today 2. 使用 Format 输出所需日期和时间 date FORMAT 2.1 "MM-DD-YY" 形式输出…...

runnable和callable区别和底层原理
确实,Runnable 可以直接通过 Thread 类来运行,而 Callable 不能直接用于创建和运行线程。Callable 和 Runnable 都是 Java 中用于定义异步任务的接口,但它们的用法和目的有所不同。 ### Runnable 和 Thread Runnable 是接口,它不返…...

Springboot 整合 Java DL4J 打造自然语言处理之语音识别系统
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...

虚幻引擎5(UE5)学习教程
虚幻引擎5(UE5)学习教程 引言 虚幻引擎5(Unreal Engine 5,简称UE5)是Epic Games开发的一款强大的游戏引擎,广泛应用于游戏开发、影视制作、建筑可视化等多个领域。UE5引入了许多先进的技术,如…...

从0开始深度学习(26)——汇聚层/池化层
池化层通过减少特征图的尺寸来降低计算量和参数数量,同时增加模型的平移不变性和鲁棒性。汇聚层的主要优点之一是减轻卷积层对位置的过度敏感。 1 最大汇聚层、平均汇聚层 汇聚层和卷积核一样,是在输入图片上进行滑动计算,但是不同于卷积层的…...

兼职发薪系统:高效、便捷的劳务发薪解决方案
在快速发展的数字化时代,企业对于高效、便捷的薪酬发放和管理解决方案的需求日益增长。特别是对于兼职人员众多的企业,如何实现快速、准确的发薪,同时确保员工信息的安全与保密,成为了一个亟待解决的问题。今天,我们将…...

MySQL数据库单表查询习题
目录 数据内容介绍习题题目答案 数据内容介绍 数据库中有两个表 内容如下: 习题 题目 查询出部门编号为D2019060011的所有员工所有财务总监的姓名、编号和部门编号。找出奖金高于工资的员工。找出奖金高于工资40%的员工。找出部门编号为D2019090011中所有…...

多模态PaliGemma——Google推出的基于SigLIP和Gemma的视觉语言模型
前言 本文怎么来的呢?其实很简单,源于上一篇文章《π0——用于通用机器人控制的流匹配VLA模型:一套框架控制7种机械臂(改造了PaliGemma和ACT的3B模型)》中的π0用到了PaliGemma 故本文便来解读下这个PaliGemma 第一部分 PaliGemma 1.1 Pal…...

电路原理:电阻桥。
电路的基础是电阻电路。电阻电路有两种基本接线方法(串连和并连,二者有不同的解算与用法:串连分压、并连分流)。电阻电路就是使用基本接线方法的组合方案,其解算方法主要内容是判断好整体布局以及各个局部的串并连关系…...

实践出真知:MVEL表达式中for循环的坑
目录标题 背景MVEL脚本(有问题的)MVEL脚本(正确的)结论分析 背景 需要从一个URL的拼接参数中解析出id的值并输出 比如: 存在URLhttps://xxxxxxxxxx?id999999&type123&name345 然后需要输出id999999 MVEL脚本(有问题的) 入参:parseThisUrlhttp…...

Flutter运行App时出现“Running Gradle task ‘assembleDebug“问题解决
在参考了众多解决办法中最有用并且最快的方法 Gradle Distributions 在这个地方下载对应你这个文件中的gradle版本 然后将 最后一行本来不是这样的,我们把下载好的zip包保存到本地,然后用这个代替网址,最后成功运行...

基于SSM(Spring + Spring MVC + MyBatis)框架的咖啡馆管理系统
基于SSM(Spring Spring MVC MyBatis)框架的咖啡馆管理系统是一个综合性的Web应用程序,用于管理和优化咖啡馆的运营。下面我将提供一个详细的案例程序概述,包括主要的功能模块和技术栈介绍。 项目概述 功能需求 用户管理&…...

【SpringBoot】18 上传文件到数据库(Thymeleaf + MySQL)
Git仓库 https://gitee.com/Lin_DH/system 介绍 使用 Thymeleaf 写的页面,将(txt、jpg、png)格式文件上传到 MySQL 数据库中。 依赖 pom.xml <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --><depende…...

计算机体系结构之系统吞吐量(三)
前面章节《计算机体系结构之多级缓存、缓存miss及缓存hit(二)》讲了关于系统多级缓存的相关内容,其中提及了系统吞吐量一词。在此章将对其进行讲解。 系统吞吐量是计算机体系结构的一个重要指标,其衡量的是系统在单位时间内处理工…...

高级 HarmonyOS主题课—— 帮助快速构建各种文本识别应用的课后习题
天地不仁,以万物为刍狗; 圣人不仁,以百姓为刍狗。 天地之间,其犹橐龠乎? 虚而不屈,动而俞出。 多闻数穷,不若守于中。 本文内容主要来自 <HarmonyOS主题课>帮助快速构建各种文本识别应用 …...

windows C#-异常和异常处理概述
C# 语言的异常处理功能有助于处理在程序运行期间发生的任何意外或异常情况。 异常处理功能使用 try、catch 和 finally 关键字来尝试执行可能失败的操作、在你确定合理的情况下处理故障,以及在事后清除资源。 公共语言运行时 (CLR)、.NET/第三方库或应用程序代码都可…...

每日一题——第一百二十四题
题目:进制转换 #pragma once#include<stdio.h> #include<ctype.h> #include<string.h>/// <summary> /// //将字符串表示的任意进制数转为十进制 /// </summary> /// <param name"str">字符串</param> /// &l…...