Java sdk连接fabric网络的谜之报错

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Java sdk连接fabric网络的谜之报错

谜之报错

下面是一个使用fabric-java-sdk和fabric-java-gateway尝试连接上述虚拟机的未解决的一堆报错。更离谱的是,每一次报错都还不一样。。。

由于这是一个未解决的连接错误,我只阐述我做了什么和得到的反馈,也希望有类似经历的伙伴提供一些建议。

connection.json配置文件

{
  "name": "basic-network",
  "version": "1.0.0",
  "dependencies": {
  },
  "client": {
    "organization": "Department1",
    "connection": {
      "timeout": {
        "peer": {
          "endorser": "30000"
        },
        "orderer": "30000"
      }
    },
    "organization": "Department2",
    "connection": {
      "timeout": {
        "peer": {
          "endorser": "30000"
        },
        "orderer": "30000"
      }
    }
  },
  "channels": {
    "tracechannel": {
      "orderers": [
        "orderer.trace.com"
      ],
      "peers": {
        "peer0.department1.trace.com": {
          "endorsingPeer": true,
          "chaincodeQuery": true,
          "ledgerQuery": true,
          "eventSource": true
        },
        "peer0.department2.trace.com": {
          "endorsingPeer": true,
          "chaincodeQuery": true,
          "ledgerQuery": true,
          "eventSource": true
        },
      }
    }
  },
  "organizations": {
    "Department1": {
      "mspid": "Department1MSP",
      "peers": [
        "peer0.department1.trace.com",
      ],
      "adminPrivateKeyPEM": {
        "path": "src/main/resources/crypto-config/peerOrganizations/department1.trace.com/users/Admin@department1.trace.com/msp/keystore/priv_sk"
      },
      "signedCertPEM": {
        "path": "src/main/resources/crypto-config/peerOrganizations/department1.trace.com/users/Admin@department1.trace.com/msp/signcerts/Admin@department1.trace.com-cert.pem"
      }
    },
    "Department2": {
      "mspid": "Department2MSP",
      "peers": [
        "peer0.department2.trace.com",
      ],
      "adminPrivateKeyPEM": {
        "path": "src/main/resources/crypto-config/peerOrganizations/department2.trace.com/users/Admin@department2.trace.com/msp/keystore/priv_sk"
      },
      "signedCertPEM": {
        "path": "src/main/resources/crypto-config/peerOrganizations/department2.trace.com/users/Admin@department2.trace.com/msp/signcerts/Admin@department2.trace.com-cert.pem"
      }
    }
  },
      "mspid": "OrdererMSP",
      "grpcOptions": {"orderers": {
        "orderer.trace.com": {
          "url": "grpcs://127.0.0.1:7050",
        "ssl-target-name-override": "orderer.trace.com",
        "hostnameOverride": "orderer.trace.com"
      },
      "tlsCACerts": {
        "path": "src/main/resources/crypto-config/ordererOrganizations/trace.com/orderers/orderer.trace.com/tls/ca.crt"
      },
      "adminPrivateKeyPEM": {
        "path": "src/main/resources/crypto-config/ordererOrganizations/trace.com/users/Admin@trace.com/msp/keystore/priv_sk"
      },
      "signedCertPEM": {
        "path": "src/main/resources/crypto-config/ordererOrganizations/trace.com/users/Admin@trace.com/msp/signcerts/Admin@trace.com-cert.pem"
      }
    }
  },
  "peers": {
    "peer0.department1.trace.com": {
      "url": "grpcs://127.0.0.1:7051",
      "grpcOptions": {
        "ssl-target-name-override": "peer0.department1.trace.com",
        "hostnameOverride": "peer0.department1.trace.com",
        "request-timeout": 120001
      },
      "tlsCACerts": {
        "path": "src/main/resources/crypto-config/peerOrganizations/department1.trace.com/peers/peer0.department1.trace.com/tls/ca.crt"
      }
    },
    "peer0.department2.trace.com": {
      "url": "grpcs://127.0.0.1:8051",
      "grpcOptions": {
        "ssl-target-name-override": "peer0.department2.trace.com",
        "hostnameOverride": "peer0.department2.trace.com",
        "request-timeout": 120001
      },
      "tlsCACerts": {
        "path": "src/main/resources/crypto-config/peerOrganizations/department2.trace.com/peers/peer0.department2.trace.com/tls/ca.crt"
      }
    },
  }
}

官方案例测试Sample.java

package com.zcongfly;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.gateway.impl.GatewayImpl;
import org.hyperledger.fabric.sdk.HFClient;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
 * @author admin
 */
public class Sample {
    private Gateway gateway;
    private Network network;
    private static final Path NETWORK_CONFIG_PATH = Paths.get("src","main", "resources", "connection.json");
    private static final Path credentialPath = Paths.get("src","main","resources", "crypto-config", "peerOrganizations", "department1.trace.com", "users", "User1@department1.trace.com", "msp");
    public static void main(String[] args) throws IOException {
        X509Certificate certificate = null;
        PrivateKey privateKey = null;
        Gateway gateway = null;
        try {
            //使用org1中的user1初始化一个网关wallet账户用于连接网络
            Wallet wallet = Wallets.newInMemoryWallet();
            Path certificatePath = credentialPath.resolve(Paths.get("signcerts", "User1@department1.trace.com-cert.pem"));
            certificate = readX509Certificate(certificatePath);
            Path privateKeyPath = credentialPath.resolve(Paths.get("keystore", "priv_sk"));
            privateKey = getPrivateKey(privateKeyPath);
            wallet.put("user",Identities.newX509Identity("Department1MSP",certificate,privateKey));
            //根据connection.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder();
            builder.identity(wallet, "user").networkConfig(NETWORK_CONFIG_PATH);
            //连接网关
            gateway = builder.connect();
            System.out.println("=====================已连接到网关!=======================");
            //获取mychannel通道
            Network network = gateway.getNetwork("mychannel");
            System.out.println(network);
            System.out.println("===================已连接到指定通道!========================================");
            //获取合约对象
            Contract myoilcc = network.getContract("myoilcc");
            System.out.println(myoilcc);
            // 提交事务 存储到账本
            //byte[] createSaccResult = myprovocoilContract.createTransaction("addoilaccount").submit("3","2022.04.21","136.0","3","1","","36");
            //System.out.println("myprovocoil油料存储:" + new String(createSaccResult, StandardCharsets.UTF_8));
            // 查询
            //byte[] queSaccResult = myprovocoilContract.createTransaction("query").submit("001油品");
            //System.out.println("myprovocoil油料查询结果:" + new String(queSaccResult, StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 从文件或流中读取X.509证书并返回一个X509Certificate对象。
     *X.509证书是一种数字证书格式,常用于加密、签名和身份验证等安全应用程序中。
     * 在Hyperledger Fabric中,X.509证书也被广泛用于身份验证和授权。
     * 使用Java编写的Hyperledger Fabric客户端应用程序通常需要读取和解析X.509证书以进行身份验证和交易提交。
     * readX509Certificate方法接受一个InputStream参数,该参数指定了包含X.509证书数据的输入流。
     * 该方法首先创建一个CertificateFactory实例,并使用该实例从输入流中加载证书数据并返回一个X509Certificate对象。
     */
    private static X509Certificate readX509Certificate(final Path certificatePath) throws IOException, CertificateException {
        try (Reader certificateReader =
                     Files.newBufferedReader(certificatePath, StandardCharsets.UTF_8)) {
            return Identities.readX509Certificate(certificateReader);
        }
    }
    /**
     * 从文件或流中读取私钥数据并返回一个PrivateKey对象。
     * 在Hyperledger Fabric中,使用X.509证书进行身份验证和授权时,通常需要提供与证书关联的私钥。
     * 使用Java编写的Hyperledger Fabric客户端应用程序通常需要读取和解析私钥以进行身份验证和交易提交。
     * getPrivateKey方法接受两个参数,分别是包含私钥数据的InputStream对象和私钥的密码。
     * 该方法首先创建一个KeyStore实例,并使用该实例从输入流中加载私钥数据和相关证书链。
     * 然后,该方法使用密码解密私钥数据,并返回一个PrivateKey对象。
     */
    private static PrivateKey getPrivateKey(final Path privateKeyPath) throws IOException, InvalidKeyException {
        try (Reader privateKeyReader =
                     Files.newBufferedReader(privateKeyPath, StandardCharsets.UTF_8)) {
            return Identities.readPrivateKey(privateKeyReader);
        }
    }
}

报错1:

虚拟机使用的是NAT模式,已开启ssh服务,并在虚拟机上设置了端口转发,将22端口映射成主机上的2222端口,目前主机可以通过ssh命令连接到虚拟机,命令是ssh username@127.0.0.1 -p 2222,但是再使用fabric-java-sdk连接连接到该虚拟机上启动的fabric网络时一直报错,目前主机仍然无法ping通虚拟机的ip地址,只能通过ssh username@127.0.0.1 -p 2222命令与虚拟机进行连接和通信。

以下是connection.json的当前配置:

"orderers": {
    "orderer.trace.com": {
      "url": "grpcs://localhost:7050",

不论将url改成127.0.0.1、localhost、虚拟机ip、虚拟机内部IP均报错Connection refused

ERROR org.hyperledger.fabric.sdk.Channel - Channel Channel{id: 1, name: mychannel} Sending proposal with transaction: 7d61cbf1e1cbdab5a17d552254cd5957bbd19006813169c2c6031e90dfd384ae to Peer{ id: 2, name: peer0.department2.trace.com, channelName: mychannel, url: grpcs://localhost:8051, mspid: Department2MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=io exception, cause=io.grpc.netty.shaded.io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/[0:0:0:0:0:0:0:1]:8051
Caused by: java.net.ConnectException: Connection refused: no further information

将url改为grpcs://localhost:2222,报错Connection refused

ERROR org.hyperledger.fabric.sdk.Channel - Channel Channel{id: 1, name: mychannel} Sending proposal with transaction: ca2ff093f2624894dc15a90ef9f7f497d5510fad9e3e29663a143b1609007447 to Peer{ id: 2, name: peer0.department2.trace.com, channelName: mychannel, url: grpcs://localhost:2222, mspid: Department2MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=io exception, cause=io.grpc.netty.shaded.io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/[0:0:0:0:0:0:0:1]:2222
Caused by: java.net.ConnectException: Connection refused: no further information

这应该属于同一类错误。

报错2:

查阅资料,启用ssh隧道:

ssh -L 5000:localhost:5000 zcongfly@127.0.0.1 -p 2222

修改所有节点的grpc的url为:

"url": "grpcs://localhost:5000",

报错变成了Connection reset

ERROR org.hyperledger.fabric.sdk.Channel - Channel Channel{id: 1, name: mychannel} Sending proposal with transaction: d98f80a464b5011fa2cbee88d74a6ce8bcab09c39244bb0670ccabd2325b9347 to Peer{ id: 2, name: peer0.department2.trace.com, channelName: mychannel, url: grpcs://127.0.0.1:5000, mspid: Department2MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=io exception
Channel Pipeline: [SslHandler#0, ProtocolNegotiators$ClientTlsHandler#0, WriteBufferingAndExceptionHandler#0, DefaultChannelPipeline$TailContext#0], cause=java.net.SocketException: Connection reset

报错3:

进一步查阅资料:

https://stackoverflow.com/questions/62897216/why-am-i-getting-tls-handshake-error-when-i-try-to-connect-from-hyperledger-java

https://stackoverflow.com/questions/53625506/hyperledger-fabric-java-sdk-use-grpcs-for-peer-and-orderer-connections/53676602?r=SearchResults&s=2%7C14.4806#53676602

在crypto-config.ymal中添加SANS:

SANS:
  - "localhost"

在Java工程的src/main/resources文件夹下以管理员身份运行cmd,输入命令:

# 添加证书到java的jvm密钥库中
keytool -import -file crypto-config\peerOrganizations\department2.trace.com\peers\peer0.department2.trace.com\tls\server.crt -alias peer0.department2.trace.com -keystore "C:\Program Files\Java\jre1.8.0_281\lib\security\cacerts" -storepass changeit
keytool -import -file crypto-config\peerOrganizations\department1.trace.com\peers\peer0.department1.trace.com\tls\server.crt -alias peer0.department1.trace.com -keystore "C:\Program Files\Java\jre1.8.0_281\lib\security\cacerts" -storepass changeit
keytool -import -file crypto-config\ordererOrganizations\trace.com\orderers\orderer.trace.com\tls\server.crt -alias orderer.trace.com -keystore "C:\Program Files\Java\jre1.8.0_281\lib\security\cacerts" -storepass changeit

再次运行Sample.java,报错你的主机中的软件中止了一个已建立的连接

ERROR org.hyperledger.fabric.sdk.Channel - Channel Channel{id: 1, name: mychannel} Sending proposal with transaction: 9f9972c50afe9e23dd8ba4a9ca1cb9d81ec950b53bcc51d75991adf601b66964 to Peer{ id: 2, name: peer0.department2.trace.com, channelName: mychannel, url: grpcs://127.0.0.1:5000, mspid: Department2MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=io exception
Channel Pipeline: [SslHandler#0, ProtocolNegotiators$ClientTlsHandler#0, WriteBufferingAndExceptionHandler#0, DefaultChannelPipeline$TailContext#0], cause=java.io.IOException: 你的主机中的软件中止了一个已建立的连接。

这个错误在网上倒也能找到些东西,也是Java连接远程数据库啥的。大致就是有可能虚拟机那边响应慢,sdk发送ssl连接请求时没等响应就断开或者发了一个新的请求,把连接中断了;或者是设置了timeout,超时就直接给断开了连接;又或者是短时间内重复提交了同一个表单导致连接中断,总之,都不是我这类情况。

参考:https://blog.csdn.net/qq_54070103/article/details/127441068

https://www.bbsmax.com/A/qVdepjbr5P/

此时,每运行一次Simple.java,cmd窗口中开始不断显示channel 3: open failed: connect failed: Connection refused

C:\WINDOWS\system32>ssh -L 7050:localhost:7050 zcongfly@127.0.0.1 -p 2222
zcongfly@127.0.0.1's password:
Last login: Fri Mar 31 08:15:03 2023 from gateway
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused
[zcongfly@localhost ~]$ channel 3: open failed: connect failed: Connection refused

这一度带给过我希望,是不是只要解决了信任问题就可以连接上了。

报错4:

求助于chat-gpt:

“如果您使用SSH端口转发将CentOS虚拟机上的peer节点端口映射到本地主机上的端口,则您可以在url中指定本地主机上的端口。在这种情况下,您应该将localhost设置为本地主机的IP地址(通常为127.0.0.1),并将端口设置为您在SSH端口转发命令中指定的本地端口(默认为2222)。

例如,如果您在本地主机上执行了以下SSH端口转发命令:

ssh -L 2222:localhost:7051 user@192.168.1.100

则您的url应该类似于:

"url": "grpc://127.0.0.1:2222"

这将允许Java SDK客户端通过本地主机上的端口2222连接到CentOS虚拟机上的peer节点的GRPC服务。”

如果要连接多个peer节点该如何操作呢?比如连接到peer0的7051端口、peer1的8051端口、peer2的9051端口?

如果要连接多个peer节点,您需要为每个peer节点执行SSH端口转发命令,并将它们映射到本地主机的不同端口。例如:

ssh -L 2222:localhost:7051 user@192.168.1.100
ssh -L 3333:localhost:8051 user@192.168.1.100
ssh -L 4444:localhost:9051 user@192.168.1.100

以上命令将分别将CentOS虚拟机上peer0、peer1和peer2的GRPC服务端口映射到本地端口2222、3333和4444上。

接下来,您可以在Java SDK客户端中使用以下代码来连接这些peer节点:

List<Peer> peers = new ArrayList<>();
peers.add(HFClient.createNewDefaultPeer("peer0", "grpc://127.0.0.1:2222"));
peers.add(HFClient.createNewDefaultPeer("peer1", "grpc://127.0.0.1:3333"));
peers.add(HFClient.createNewDefaultPeer("peer2", "grpc://127.0.0.1:4444"));
Channel channel = HFClient.createNewChannel("mychannel", orderer, config);
channel.addPeers(peers);

以上代码创建了一个包含所有peer节点的peers列表,并将其添加到一个名为mychannel的通道中。请注意,在每个grpc:// URL中,您需要指定正确的本地端口,以便连接到相应的peer节点。

这样,您就可以通过Java SDK客户端连接到多个peer节点的GRPC服务了。

先到虚拟机中在添加3333和4444的端口转发,然后以管理员身份启用3个cmd窗口,分别输入:

ssh -L 7050:localhost:7050 zcongfly@127.0.0.1 -p 2222
ssh -L 7051:localhost:7051 zcongfly@127.0.0.1 -p 3333
ssh -L 8051:localhost:8051 zcongfly@127.0.0.1 -p 4444

建立起3个ssh隧道并成功连接上之后,修改connection.json文件中各个节点url分别为:

"url": "grpcs://localhost:7050"
"url": "grpcs://localhost:7051"
"url": "grpcs://localhost:8051"

运行Sample.java,报错Connection closed while performing TLS negotiation

ERROR org.hyperledger.fabric.sdk.Channel - Channel Channel{id: 1, name: mychannel} Sending proposal with transaction: d2915393c441925665cb31c87a9c1803c0022707b124e35f27e72c20e762fedd to Peer{ id: 2, name: peer0.department2.trace.com, channelName: mychannel, url: grpcs://127.0.0.1:8051, mspid: Department2MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=Connection closed while performing TLS negotiation
Channel Pipeline: [SslHandler#0, ProtocolNegotiators$ClientTlsHandler#0, WriteBufferingAndExceptionHandler#0, DefaultChannelPipeline$TailContext#0], cause=java.nio.channels.ClosedChannelExceptionERROR org.hyperledger.fabric.sdk.Channel - Channel Channel{id: 1, name: mychannel} Sending proposal with transaction: d2915393c441925665cb31c87a9c1803c0022707b124e35f27e72c20e762fedd to Peer{ id: 2, name: peer0.department2.trace.com, channelName: mychannel, url: grpcs://127.0.0.1:8051, mspid: Department2MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=Connection closed while performing TLS negotiation

这回变为TSL证书错误了。。。

这个错误表明在与peer节点进行TLS协商期间,连接已经被关闭,导致无法发送建议。这通常表示由于某些网络问题或配置错误而无法建立稳定的TLS连接。

您可以尝试检查以下几点:

  1. 确认您的peer节点是否正确启动并正在运行。您可以使用peer node status命令来检查。
  2. 检查peer节点的TLS证书和密钥是否正确生成,并且Java SDK客户端是否正确加载了这些证书和密钥。您可以检查SDK客户端的TLS设置,并确保它们与peer节点的TLS设置匹配。
  3. 检查您的网络环境,确保从Java SDK客户端到peer节点的网络连接是可用的,并且没有任何防火墙或网络代理阻止了通信。

如果您仍然无法解决问题,请尝试将日志级别设置为更高的水平,并检查详细的日志信息,以便更好地理解问题所在。

要检查Java SDK客户端中使用的TLS配置和证书,您可以检查以下内容:

  1. 客户端配置文件:检查您在创建SDK客户端时传递的配置文件。如果您使用了默认配置,该文件应为connection-profile.yaml
  2. TLS证书和密钥:检查配置文件中包含的TLS证书和密钥路径是否正确,并确保这些证书和密钥与peer节点的TLS设置匹配。
  3. TLS设置:检查配置文件中的TLS设置,例如是否启用了TLS,是否使用了正确的加密算法等。确保客户端的TLS设置与peer节点的TLS设置匹配。
  4. 日志输出:启用更详细的日志输出,以便检查TLS握手期间发生的任何错误或异常情况。您可以通过在SDK客户端代码中调用Logger.getLogger("org.hyperledger.fabric").setLevel(Level.DEBUG)来设置更高的日志级别。这将打印出更多的详细信息,包括TLS握手期间发生的事件和错误。
  5. 测试工具:您可以使用OpenSSL等工具测试从SDK客户端到peer节点的TLS连接是否正常工作。例如,您可以使用以下命令来测试与peer节点的TLS连接:
openssl s_client -connect <peer-hostname>:<peer-port> -tls1_2

以上命令将使用TLS 1.2连接到指定的peer节点,并打印出与TLS握手相关的详细信息。如果该命令能够成功连接到peer节点并打印出TLS握手信息,则可以确认TLS配置和证书设置正确。

(一下午了,Java也好fabric也罢,求求你们做个人吧。。。)

TSL一下触及到知识盲区了,其实前边的ssh和什么ssl连接的Java密钥就已经是盲区了。

先记录下,让我歇会儿。

目录
相关文章
|
7天前
|
关系型数据库 MySQL 数据库
实时计算 Flink版操作报错合集之网络缓冲池(NetworkBufferPool)中可用内存不足,该如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
19天前
|
开发工具 iOS开发 容器
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
iOS Objective-C 应用连接Azure Storage时,若不关闭账号的匿名访问,程序能正常运行。但关闭匿名访问后,上传到容器时会出现错误:“Public access is not permitted”。解决方法是将创建容器时的公共访问类型从`AZSContainerPublicAccessTypeContainer`改为`AZSContainerPublicAccessTypeOff`,以确保通过授权请求访问。
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
|
3天前
|
网络协议 Java Linux
|
26天前
|
机器学习/深度学习 Serverless 文件存储
函数计算操作报错合集之在网络设置完成后进行挂载的指令,报错:找不到网络路径,该如何处理
在使用函数计算服务(如阿里云函数计算)时,用户可能会遇到多种错误场景。以下是一些常见的操作报错及其可能的原因和解决方法,包括但不限于:1. 函数部署失败、2. 函数执行超时、3. 资源不足错误、4. 权限与访问错误、5. 依赖问题、6. 网络配置错误、7. 触发器配置错误、8. 日志与监控问题。
|
6天前
|
分布式计算 Java 调度
MaxCompute产品使用合集之使用Tunnel Java SDK上传BINARY数据类型时,应该使用什么作为数据类字节
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
1月前
|
SQL Java 数据库连接
Java开发者必知:JDBC连接数据库的“三大法宝”
【6月更文挑战第24天】Java JDBC的三大法宝简化数据库操作:①统一API接口,跨平台与各类数据库交互;②参数化查询,提升效率,防止SQL注入;③事务管理,确保数据一致性。通过这三个核心特性,开发者能更安全高效地处理数据库任务。示例代码展示了如何使用这些功能。
|
1月前
|
Java Android开发
Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。
【6月更文挑战第23天】 Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。客户端连接服务器,发送&quot;Hello, Server!&quot;后关闭。注意Android中需避免主线程进行网络操作。
48 4
|
1月前
|
存储 人工智能 Java
2024创建boot时 项目SDK11不支持所选的版本Java21 请选择较低版本的java 解决方案
2024创建boot时 项目SDK11不支持所选的版本Java21 请选择较低版本的java 解决方案
26 2
|
1月前
|
网络协议 Java 程序员
TCP/IP协议栈是网络通信基础,Java的`java.net`包提供工具,使开发者能利用TCP/IP创建网络应用
【6月更文挑战第23天】 **TCP/IP协议栈是网络通信基础,它包含应用层(HTTP, FTP等)、传输层(TCP, UDP)、网络层(IP)、数据链路层(帧, MAC地址)和物理层(硬件信号)。Java的`java.net`包提供工具,使开发者能利用TCP/IP创建网络应用,如Socket和ServerSocket用于客户端和服务器通信。**
35 3
|
14天前
|
SQL Java 关系型数据库
Java面试题:描述JDBC的工作原理,包括连接数据库、执行SQL语句等步骤。
Java面试题:描述JDBC的工作原理,包括连接数据库、执行SQL语句等步骤。
24 0

热门文章

最新文章