首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Spring Cloud 学习之路 | 第一章 :Eureka 服务的注册和发现

一. Spring Cloud 简介 Spring Cloud 为开发者提供了快熟构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话,集群状态等。协调分布式系统导致样板模式,并且Spring Cloud的开发人员可以快速建立实现这些模式的服务和应用程序。他们适用于任何分布式环境,包括开发人员的笔记本,裸机数据中心和Cloud Foundry等托管平台。此外Spring Cloud基于Spring Boot,需要对Spring Boot 有一定的了解,可参见SpringBoot非官方教程link。 二. Eureka 简介Eureka 是Spring Cloud Netflix微服务套件中的一部分,易于和Spring Boot 构建的微服务整合起来。 Eureka包含了服务端和客户端组件。服务端也被称作为服务注册中心,用于提供服务的注册和发现。Eureka支持高可用的配置,当集群中有分片出现故障时,Eureka就会转入自动保护模式,它允许分片故障期间继续提供服务的发现和注册,当故障分片恢复正常时,集群中其他分片会把他们的状态再次同步回来。客户端组件包含服务消费者与服务提供者。在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性的发送心跳来更新它的服务租约。同时也可以从服务端查询当前注册的服务信息并把他们缓存到本地并周期性的刷新服务状态。 三. 构建服务注册中心 创建主maven工程 首先创建一个主Maven工程,在其pom文件引入依赖,Spring Boot版本为2.1.3.RELEASE,Spring Cloud版本为Greenwich.RELEASE。这个pom文件作为父pom文件,起到依赖版本控制的作用,其他module工程继承该pom。这一系列文章全部采用这种模式。主pom代码如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.kimframework</groupId> <artifactId>eureka-cloud</artifactId> <version>1.0-SNAPSHOT</version> <modules> <module>eureka-server</module> <module>eureka-client</module> </modules> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 创建Eureka Server 创建一个Eureka Server 为服务注册中心 右键工程-->New Module-->Spring Initializr 如下图: 下一步-->Cloud Discovery-->Eureka Server-->下一步 创建完成后的Module(eureka-server) 其 pom继承主pom 文件,并引入spring-cloud-starter-netflix-eureka-server, pom文件如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kimframework</groupId> <artifactId>eureka-cloud</artifactId> <version>1.0-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.kimframework</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-server</name> <description>Eureka Server</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </project> 在eureka-server的启动类上添加注解@EnableEurekaServer,开启服务注册中心的功能,代码如下: @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } 配置application.yml server: port: 8000 spring: application: name: eureka-server eureka: instance: hostname: localhost client: fetch-registry: false register-with-eureka: false service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 在默认情况下,服务注册中心也会把自己当做是一个服务,将自己注册进服务注册中心,所以我们可以通过配置来禁用他的客户端注册行为。配置说明:server.port : 服务端口spring.application.name : 应用名称eureka.instance.hostname: eureka服务实例名称eureka.client.fetch-registry : 禁用客户端服务检索功能eureka.client.register-with-eureka: 表示不向服务注册中心注册自己eureka.client.service-ur.defaultZone: 指定服务注册中心的地址 启动工程,浏览器访问eureka-server的主界面:http://localhost:8000/ 界面如下:No application available 没有服务被发现 ……,因为还没有服务注册,所以暂时没有服务信息 - 创建Eureka Client 当client向server注册时,它会提供一些元数据,例如主机和端口,URL,主页等。Eureka server 从每个client实例接收心跳消息。 如果心跳超时,则通常将该实例从注册server中删除。 创建一个Module(eureka-client),创建过程通eureka-server相同, 选择引入Eureka Discovery 和Web 其pom文件如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kimframework</groupId> <artifactId>eureka-cloud</artifactId> <version>1.0-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.kimframework</groupId> <artifactId>eureka-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-client</name> <description>Eureka Client</description> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> </project> 配置eureka-client的启动类,配置@EnableEurekaClient注解 @SpringBootApplication @EnableEurekaClient public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } } application.yml : server: port: 8001 spring: application: name: eureka-client eureka: client: service-url: defaultZone: http://localhost:8000/eureka # 服务注册中心地址 需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name 。启动eureka-client工程,打开http://localhost:8000 ,即eureka server 的网址: 发现eureka-client已经注册在服务注册中心了。服务名为:EUREKA-CLIENT 端口为:8001 该警告就是发出了Eureka的自我保护机制!服务注册到Eureka服务器后,会向其发送心跳,Eureka在运行期间,会统计心跳失败的比率在15分钟是否低于85%,如果低于,Eureka服务器会将这些服务保护起来,不会剔除。 四: 参考资料 https://blog.csdn.net/forezp/article/details/81040925 https://blog.csdn.net/qq_27046951/article/details/82880609

优秀的个人博客,低调大师

go微服务框架go-micro深度学习(五) stream 调用过程详解

上一篇写了一下rpc调用过程的实现方式,简单来说就是服务端把实现了接口的结构体对象进行反射,抽取方法,签名,保存,客户端调用的时候go-micro封请求数据,服务端接收到请求时,找到需要调用调用的对象和对应的方法,利用反射进行调用,返回数据。 但是没有说stream的实现方式,感觉单独写一篇帖子来说这个更好一些。上一篇帖子是基础,理解了上一篇,stream实现原理一点即破。先说一下使用方式,再说原理。当前go-micro对 rpc 调用的方式大概如下:普通的rpc调用 是这样: 1.连接服务器或者从缓存池得到连接 2.客户端 ->发送数据 -> 服务端接收 3.服务端 ->返回数据 -> 客户端处理数据 4.关闭连接或者把连接返回到缓存池 当前 rps stream的实现方式 是这样子: 1. 连接服务器 2. 客户端多次发送请求-> 服务端接收 3. 服务端多次返回数据-> 客户端处理数据 4. 关闭连接 当数据量比较大的时候我们可以用stream方式分批次传输数据。对于客户端还是服务端没有限制,我们可以根据自己的需要使用stream方式,使用方式也非常的简单,在定义接口的时候在参数或者返回值前面加上stream然后就可以多次进行传输了,使用的代码还是之前写的例子,代码都在github上: 比如我的例子中定义了两个使用stream的接口,一个只在返回值使用stream,另一个是在参数和返回值前都加上了stream,最终的使用方式没有区别 rpc Stream(model.SRequest) returns (stream model.SResponse) {} rpc BidirectionalStream(stream model.SRequest) returns (stream model.SResponse) {} 看一下go-micro为我们生成的代码rpcapi.micro.go里,不要被吓到,生成了很多代码,但是没啥理解不了的Server端 // Server API for Say service type SayHandler interface { // .... others Stream(context.Context, *model.SRequest, Say_StreamStream) error BidirectionalStream(context.Context, Say_BidirectionalStreamStream) error } type Say_StreamStream interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error Send(*model.SResponse) error } type Say_BidirectionalStreamStream interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error Send(*model.SResponse) error Recv() (*model.SRequest, error) } // .... others Client端 // Client API for Say service type SayService interface { //... others Stream(ctx context.Context, in *model.SRequest, opts ...client.CallOption) (Say_StreamService, error) BidirectionalStream(ctx context.Context, opts ...client.CallOption) (Say_BidirectionalStreamService, error) } type Say_StreamService interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error Recv() (*model.SResponse, error) } type Say_BidirectionalStreamService interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error Send(*model.SRequest) error Recv() (*model.SResponse, error) } 你会发现参数前面加了 Stream后,生成的代码会把你的参数变成一个接口,这个接口主要要的方法是 SendMsg(interface{}) error RecvMsg(interface{}) error Close() error 剩下的两个接口方法是根据你是发送还是接收生成的,如果有发送就会有Send(你的参数),如果有接收会生成Rev() (你的参数, error),但这两个方法只是为了让你使用时方便,里面调用的还是SendMsg(interface)和RecvMsg(interface)方法,但是他们是怎么工作的,如何多次发送和接收传输的数据,是不是感觉很神奇。 我就以TsBidirectionalStream 方法为例开始分析,上一篇和再早之前的帖子已经说了服务端启动的时候都做了哪些操作,这里就不再赘述,服务端的实现,很简单,不断的获取客户端发过来的数据,再给客户端一次一次的返回一些数据。 /* 模拟数据 */ func (s *Say) BidirectionalStream(ctx context.Context, stream rpcapi.Say_BidirectionalStreamStream) error { for { req, err := stream.Recv() if err == io.EOF { break } if err != nil { return err } for i := int64(0); i < req.Count; i++ { if err := stream.Send(&model.SResponse{Value: []string {lib.RandomStr(lib.Random(3, 6))}}); err != nil { return err } } } return nil } 启动服务,服务开始监听客户端传过来的数据.....客户端调用服务端方法: // 调用 func TsBidirectionalStream(client rpcapi.SayService) { rspStream, err := client.BidirectionalStream(context.Background()) if err != nil { panic(err) } // send go func() { rspStream.Send(&model.SRequest{Count: 2}) rspStream.Send(&model.SRequest{Count: 5}) // close the stream if err := rspStream.Close(); err != nil { fmt.Println("stream close err:", err) } }() // recv idx := 1 for { rsp, err := rspStream.Recv() if err == io.EOF { break } else if err != nil { panic(err) } fmt.Printf("test stream get idx %d data %v\n", idx, rsp) idx++ } fmt.Println("Read Value End") } 当客户端在调用rpc的stream方法是要很得到stream rspStream, err := client.BidirectionalStream(context.Background()) // func (c *sayService) BidirectionalStream(ctx context.Context, opts ...client.CallOption) (Say_BidirectionalStreamService, error) { req := c.c.NewRequest(c.name, "Say.BidirectionalStream", &model.SRequest{}) stream, err := c.c.Stream(ctx, req, opts...) if err != nil { return nil, err } return &sayServiceBidirectionalStream{stream}, nil } 这个调用c.c.Stream(ctx, req, opts...)是关键,他的内部实现就是和服务器进行连接,然后返回一个stream,进行操作。 客户端:和服务端建立连接,返回Stream,进行接收和发送数据 服务端:接收客户端连接请求,利用反射找到相应的方法,组织Strem,传给方法,进行数据的发送和接收 建立连接的时候就是一次rpc调用,服务端接受连接,然后客户端发送一次调用,但是传输的是空数据,服务端利用反射找到具体的方法,组织stream,调用具体方法,利用这个连接,客户端和服务端进行多次通信。

优秀的个人博客,低调大师

【翻译】Sklearn与TensorFlow机器学习实用指南 —— 第15章 自编码器

本文来自云栖社区官方钉群“Python技术进阶”,了解相关信息可以关注“Python技术进阶”。 关联权重 当自编码器整齐地对称时,就像我们刚刚构建的那样,一种常用技术是将解码器层的权重与编码器层的权重相关联。 这样减少了模型中的权重数量,加快了训练速度,并限制了过度拟合的风险。 不幸的是,使用fully_connected()函数在 TensorFlow 中实现相关权重有点麻烦;手动定义层实际上更容易。 代码结尾明显更加冗长: activation = tf.nn.elu regularizer = tf.contrib.layers.l2_regularizer(l2_reg) initializer = tf.contrib.layers.variance_scaling_initializer() X = tf.placehol

优秀的个人博客,低调大师

Python零基础学习笔记(三十八)—— 递归方法、栈、队列模拟遍历目录

用递归方法遍历目录: 使用到os模块,所以要先引入os模块 处理文件: 核心是判断文件是否是目录文件,如果是目录文件就进行递归处理,直接将文件名打印出来 下面是文件代码: import os def getAllDir(path, sp = " "): fileList = os.listdir(path) #处理每一个文件 sp += " " for fileName in fileList: #判断是否是路径(用绝对路径) absFliePath = os.path.join(path, fileName) if os.path.isdir(absFliePath): print(sp + "目录:", fileName) #递归调用 getAllDir(absFliePath, sp) else: print(sp + "普通文件", fileName) return fileList getAllDir(r"C:\Users\Administrator\PycharmProjects\untitled\day011") 栈方法: import os def getAllDirDE(path): stack = [] stack.append(path) #处理栈,当栈为空的时候结束循环 while len(stack) != 0: dirPath = stack.pop() fileDir = os.listdir(dirPath) for fileName in fileDir: fileAbsPath = os.path.join(dirPath, fileName) if os.path.isdir(fileAbsPath): print("目录:"+ fileName) stack.append(fileAbsPath) else: print("普通文件:", fileName) getAllDirDE(r"C:\Users\Administrator\PycharmProjects\untitled\day011") 队列方法: import os import collections def getAllDir(path): queue = collections.deque() #进队 queue.append(path) while len(queue) != 0: dirPath = queue.popleft() fileList = os.listdir(dirPath) for fileName in fileList: fileAbsPath = os.path.join(dirPath, fileName) if os.path.isdir(fileAbsPath): print("目录:"+fileName) queue.append(fileAbsPath) else: print("文件:"+fileName) getAllDir(r"C:\Users\Administrator\PycharmProjects\untitled\day011")

优秀的个人博客,低调大师

Python零基础学习代码实践 —— 模拟播放器中的歌词显示

import time musucLrc = ''' [00:00.01]给我你的爱 [00:02.01]林宥嘉,张杰 [00:05.53] 作词:秋风 [00:09.83] 作曲:秋风 [00:14.90] [00:15.65]相信我 在每个生命的路口 [00:20.98]在每个无助的时候 [00:24.75]都有对爱的渴求 [00:30.47]我想把 真的爱向你传达 [00:36.53]无论你在海角天涯 [00:39.52]都能感到 我的牵挂 [00:44.28]请给我你的爱 [00:47.84]请伸出手来传递这信赖 [00:51.54]就在这茫茫人海 [00:53.79]真心的爱 让世界变色彩 [00:59.02]请给我你的爱 [01:02.45]让我们用爱改变着未来 [01:06.10]在每个艰难时刻 [01:08.88]伸你的手 感觉真的爱 [01:14.81]牵着手 让我们静静地感受 [01:19.92]当风雨艰难过去后 [01:23.79]那种美好的自由 [01:29.29]我们都曾 错过幸福的意义 [01:34.77]只希望我还来得及 [01:38.45]去告诉你 真心爱你 [01:43.15]请给我你的爱 [01:47.39]请伸出手来传递这信赖 [01:50.42]就在这茫茫人海 [01:53.18]真心的爱 让世界变色彩 [01:57.72]请给我你的爱 [02:01.53]让我们用爱改变着未来 [02:05.19]在每个艰难时刻 [02:07.86]伸你的手 感觉真的爱 [02:14.27]我不再想要错过 [02:15.81]你的每个热切期待 [02:19.18]用爱 在明天到来之前 [02:22.56]向你大声说出爱~~爱 [02:29.44]请给我你的爱 [02:32.65]请伸出手来传递这信赖 [02:36.33]就在这茫茫人海 [02:39.08]真心的爱 让世界变色彩 [02:43.89]请给我你的爱 [02:47.56]让我们用爱改变着未来 [02:51.05]在每个艰难时刻 [02:53.96]伸你的手 感觉真的爱 [03:01.38]给我你的爱~~ ''' #将数据分解存储到字典里 lrcDict = {} musicList = musucLrc.splitlines() for lrcLine in musicList: #runCount = lrcLine.count(":") lrcLineList = lrcLine.split("]") for index in range(len(lrcLineList) - 1): timeStr = lrcLineList[index][1:] #print(timeStr) timeList = timeStr.split(":") timea = float(timeList[0]) * 60 + float(timeList[1]) #print(timea) lrcDict[timea] = lrcLineList[-1] #print(lrcDict) allTimeList = [] for t in lrcDict: allTimeList.append(t) allTimeList.sort() #print(allTimeList) #在字典里将数据调出来然后按照时间间隔将数据显示出来 #效果是一行一行的刷新 getTime = 0 while 1: for n in range(len(allTimeList)): tempTime = allTimeList[n] if getTime < tempTime: break lrc = lrcDict.get(allTimeList[n]) if lrc == None: pass else: print(lrc) if n in range(len(allTimeList) - 1): time.sleep(allTimeList[n + 1] - allTimeList[n]) getTime += (allTimeList[n + 1] - allTimeList[n]) else: break

优秀的个人博客,低调大师

Python零基础学习笔记(十一)—— 运算符和表达式2

''' 位运算符:按位运算是把数字看作是二进制数来计算 & / ^ ~ << >> ''' #与运算: & (同 1 为 1,否则为 0) print(5 & 7) #或运算: | (有 1 为 1,同 0 则 0) print(5 | 7) #异或运算:^ (相同为 0,不同为 1) print(5 ^ 7) # 取反:~ (1 变为 0, 0 变为 1) print(~2) #左移运算符: << () #各二进制位全部左移若干位,高位丢弃,低位补零,<< 右侧的数字决定移动几位 print(2<<2) #右移运算符: >> () #各二进制位全部右移若干位,高位丢弃,低位补零,<< 右侧的数字决定移动几位 print(10>>1) ''' 关系运算符和关系运算表达式 关系运算符: == != > < >= <= 关系运算表达式: 格式: 【表达式1】 关系运算符 【表达式2】 功能:计算【表达式1】和【表达式2】的值 值:如果关系成立,整个关系运算表达式的值为真,否则为假 ''' ''' 逻辑运算符(3种) 逻辑与: and 逻辑与运算表达式: 【表达式1】 and 【表达式2】 值:【表达式1】【表达式2】同真为真,有假则为假 **短路原则:【表达式1】 and 【表达式2】 and 【表达式3】 .....and 【表达式n】 从前向后执行,遇到假就立刻停止 逻辑或: or 逻辑或运算表达式: 【表达式1】 or 【表达式2】 值:【表达式1】【表达式2】有一个为真就是真,都是假为假 **短路原则:【表达式1】 or 【表达式2】 or 【表达式3】 .....or 【表达式n】 从前向后执行,遇到真就立刻停止 逻辑非: not 逻辑非运算表达式: not 【表达式1】 值:真变假,假变真 ''' ''' 成员运算符 in:如果在指定序列中找到值返回True,否则返回False not in:如果在指定序列中没有找到值返回True,否则返回False ''' ''' 身份运算符 is:判断两个标识符是不是引用同一个对象 is not:判断两个标识符是不是引用不同的对象 ''' ''' 运算符优先级 ** ~ +(正) -(负) * / % // +(加) -(减) >> << & ^ | <= < > >= == != = %= += -= //= **= /= is is not in not in not or and ''' print(~2) ''' 取反过程: 内存中都是补码的形式存储 2在内存中存的补码是 00000000 00000000 00000000 00000010 2在内存中存的补码取反 11111111 11111111 11111111 11111101 求原码(除符号位,逐位取反,末位+1) 10000000 00000000 00000000 00000011 则结果为-3 '''

优秀的个人博客,低调大师

Golang学习笔记之错误处理error、panic (抛出错误),recover(捕获错误)

一、error错误表示程序中出现了异常情况。Go 语言通过内置的错误接口提供了非常简单的错误处理机制。 • error类型是go语言的一种内置类型,使用的时候不用特定去import因为它本质上是一个接口error类型是一个接口类型,这是它的定义: 1type error interface { 2 Error() string 3} (1)一个例子理解error 1package main 2import ( 3 "fmt" 4 "os" 5) 6func main() { 7 //试图打开一个并不存在的文件,这将会返回一个error 8 f, err := os.Open("/test.txt") 9 if err != nil { 10 fmt.Println(err

优秀的个人博客,低调大师

SQL数据库学习之路(练习)---C#登录界面连数据库

目录 C#登录界面连数据库 一、在数据库中先创建一个数据库。 二、在VS中创建C#的windows窗体应用程序 三、在VS中连接到数据库 四、设计登录界面 五、设置注册界面 六、将form1的按钮和form2进行关联 七、设置form2界面的注册按钮 八、form1的登录按钮设置 九、运行成果 参考文章: C#登录界面连数据库 一、在数据库中先创建一个数据库。 数据库命名为NamePwd,使用SQL语言创建两个表,一个表命名为name,另一个表命名为pwd。在两个表中都只创建一个列。 create table [name] ( Pname varchar(16) ) create table [pwd] ( pwd varchar(32) ) 运行成功后显示效果为: 二、在VS中创建C#的windows窗体应用程序 三、在VS中连接到数据库 点击服务器资源管理器,右键选择数据连接,点击添加连接。(也可以在工具中选择连接数据库)。 输入数据库的名,在选择或输入数据库名称中选择刚刚创建好的NamePwd数据库。测试连接成功后,点击确定。 四、设计登录界面 选择工具箱窗口,组成界面form1。 五、设置注册界面 选择解决方案资源管理器,右键项目--添加--Windows窗体。创建第二个窗体form2. 通过工具箱对form2进行布局。 六、将form1的按钮和form2进行关联 双击form1的注册按钮,注册按钮代码如下: private void button2_Click(object sender, EventArgs e) { using (Form2 dlg = new Form2()) //caozuo是窗口类名,确保访问;后面的是构造函数 { dlg.ShowDialog(); } } 在运行之后,点击注册按钮可以弹出form2界面。 七、设置form2界面的注册按钮 form2注册按钮代码: private void button1_Click(object sender, EventArgs e) { string connectionStr = "Data Source=DESKTOP-785QN2F;Initial Catalog=NamePwd;Persist Security Info=True;User ID=sa;Password=123456dyy"; //创建连接对象 SqlConnection myConnection = new SqlConnection(connectionStr); //测试是否连接成功 string username = textBox1.Text; //获取用户名 string password = textBox2.Text; //获取密码 string myinsert = "insert into namepwd values('"+username+"','"+password+"')"; SqlCommand mycom = new SqlCommand(myinsert, myConnection); //定义对象并连接数据库 myConnection.Open();//打开数据库 mycom.ExecuteNonQuery(); //执行插入语句 myConnection.Close(); //关闭对象并释放所占内存空间 // myConnection.Dispose(); MessageBox.Show("注册成功,请前往登录界面登录!"); // Test f2 = new Test(); // this.Close(); // f2.Show(); } 注意:string connectionStr = "Data Source=*******;Initial Catalog=NamePwd;Persist Security Info=True;User ID=sa;Password=****";中的data source=数据库名称,password为SQL登录密码 八、form1的登录按钮设置 按钮代码如下: private void button1_Click(object sender, EventArgs e) { string name = textBox1.Text; string pwd = textBox2.Text; if (name.Equals("") || pwd.Equals(""))//用户名或密码为空 { MessageBox.Show("用户名或密码不能为空"); } else //到数据库中验证 { string str = "Data Source=DESKTOP-785QN2F;Initial Catalog=NamePwd;Persist Security Info=True;User ID=sa;Password=123456dyy"; string selectSql = "select count(*) from namepwd where Name='"+name+"' and pwd='"+pwd+"'"; SqlConnection con = new SqlConnection(str); //创建连接对象 SqlCommand mycom = new SqlCommand(selectSql, con); //定义对象并连接数据库 SqlCommand cmd = new SqlCommand(selectSql,con);//定义对象并连接数据库 cmd.CommandType = CommandType.Text; con.Open(); //打开连接 Console.WriteLine("数据库打开"); //正常打印说明没问题,否则会抛出异常 // SqlDataReader sqlDataReader = mycom.ExecuteReader(); if (Convert.ToInt64(cmd.ExecuteScalar())>0)//满足用户名与密码一致,进入下一个界面 { MessageBox.Show("登录成功!"); } else { MessageBox.Show("登录失败!\n"+"用户名或密码错误!"); } con.Close(); //关闭连接 } } 注意:string str = "Data Source=*******;Initial Catalog=NamePwd;Persist Security Info=True;User ID=sa;Password=****";中的data source=数据库名称,password为SQL登录密码 九、运行成果 点击运行,点击form1的注册界面。 可以在SQL数据中查询刚刚注册的用户信息。 select *from name select *from pwd 参考文章: https://blog.csdn.net/qq_36171287/article/details/83714547 https://blog.csdn.net/qq_38830964/article/details/84036635

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册