gRPC Java、Go、PHP使用例子

news2024/11/24 20:53:36

文章目录

    • 1、Protocol Buffers定义接口
      • 1.1、编写接口服务
      • 1.2、Protobuf基础数据类型
    • 2、服务器端实现
      • 2.1、生成gRPC服务类
      • 2.2、Java服务器端实现
    • 3、java、go、php客户端实现
      • 3.1、Java客户端实现
      • 3.2、Go客户端实现
      • 3.3、PHP客户端实现
    • 4、运行效果

本文例子是在Window平台测试,Java编写的gRPC服务器端,同时使用Java、Go、PHP编写客户端调用。

1、Protocol Buffers定义接口

1.1、编写接口服务

// 定义protocol buffers版本(proto3)
syntax = "proto3";

// 定义包名,避免协议消息类型之间的命名冲突。
package helloworld;

// 定义java格式
option java_multiple_files = true;
option java_package = "com.penngo.grpc";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

// 服务接口定义
service Greeter { 
  // 方法1定义
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // 方法2定义
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// HelloRequest消息类型格式定义,
message HelloRequest {
  // name为定义字段名,1为消息传输中的字段编号,使用后,不应该改编号。
  string name = 1;
}

// HelloReply消息类型格式定义,
message HelloReply {
  // message为定义字段名,1为消息传输中的字段编号,使用后,不应该改编号。
  string message = 1;
}

1.2、Protobuf基础数据类型

    <th>C++</th>
    <th>Java/Kotlin</th>
    <th>Python</th>
    <th>Go</th>
    <th>Ruby</th>
    <th>C#</th>
    <th>PHP</th>
    <th>Dart</th>
</tr>
<tr>
    <td>double</td>
    
    <td>double</td>
    <td>double</td>
    <td>float</td>
    <td>float64</td>
    <td>Float</td>
    <td>double</td>
    <td>float</td>
    <td>double</td>
</tr>
<tr>
    <td>float</td>
   
    <td>float</td>
    <td>float</td>
    <td>float</td>
    <td>float32</td>
    <td>Float</td>
    <td>float</td>
    <td>float</td>
    <td>double</td>
</tr>
<tr>
    <td>int32</td>
  
    <td>int32</td>
    <td>int</td>
    <td>int</td>
    <td>int32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>int</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>int64</td>

    <td>int64</td>
    <td>long</td>
    <td>int/long<sup>[4]</sup></td>
    <td>int64</td>
    <td>Bignum</td>
    <td>long</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>uint32</td>
   
    <td>uint32</td>
    <td>int<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>uint</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>uint64</td>
 
    <td>uint64</td>
    <td>long<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint64</td>
    <td>Bignum</td>
    <td>ulong</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>sint32</td>
   
    <td>int32</td>
    <td>int</td>
    <td>int</td>
    <td>int32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>int</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>sint64</td>
    
    <td>int64</td>
    <td>long</td>
    <td>int/long<sup>[4]</sup></td>
    <td>int64</td>
    <td>Bignum</td>
    <td>long</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>fixed32</td>
  
    <td>uint32</td>
    <td>int<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>uint</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>fixed64</td>
  
    <td>uint64</td>
    <td>long<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint64</td>
    <td>Bignum</td>
    <td>ulong</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>sfixed32</td>
   
    <td>int32</td>
    <td>int</td>
    <td>int</td>
    <td>int32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>int</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>sfixed64</td>
   
    <td>int64</td>
    <td>long</td>
    <td>int/long<sup>[4]</sup></td>
    <td>int64</td>
    <td>Bignum</td>
    <td>long</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>bool</td>
   
    <td>bool</td>
    <td>boolean</td>
    <td>bool</td>
    <td>bool</td>
    <td>TrueClass/FalseClass</td>
    <td>bool</td>
    <td>boolean</td>
    <td>bool</td>
</tr>
<tr>
    <td>string</td>
    
    <td>string</td>
    <td>String</td>
    <td>str/unicode<sup>[5]</sup></td>
    <td>string</td>
    <td>String (UTF-8)</td>
    <td>string</td>
    <td>string</td>
    <td>String</td>
</tr>
<tr>
    <td>bytes</td>
    
    <td>string</td>
    <td>ByteString</td>
    <td>str (Python 2)<br>bytes (Python 3)</td>
    <td>[]byte</td>
    <td>String (ASCII-8BIT)</td>
    <td>ByteString</td>
    <td>string</td>
    <td>List
        <int></int>
    </td>
</tr>
</tbody>
.proto

https://protobuf.dev/programming-guides/proto3/

2、服务器端实现

服务器端实例使用java编写

2.1、生成gRPC服务类

pom.xml

<?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>

    <groupId>com.penngo</groupId>
    <artifactId>grpc-helloworld</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.59.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.59.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.59.0</version>
        </dependency>
        <dependency> <!-- necessary for Java 9+ -->
            <groupId>org.apache.tomcat</groupId>
            <artifactId>annotations-api</artifactId>
            <version>6.0.53</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.7.1</version>
            </extension>
        </extensions>
        <plugins>
            <!-- grpc代码生成插件 -->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.24.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.59.0:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>alimaven</id>
            <name>Maven Aliyun Mirror</name>
            <url>https://maven.aliyun.com/repository/central</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

命令行下执行gRPC的java代码

mvn compile

自动扫描代码目中src/main/proto/helloworld.proto下的proto文件,自动生成gRPC相关代码到target/generated-sources/protobuf目录下。
在这里插入图片描述

2.2、Java服务器端实现

HelloServer.java

package com.penngo;

import com.penngo.grpc.GreeterGrpc;
import com.penngo.grpc.HelloReply;
import com.penngo.grpc.HelloRequest;
import io.grpc.Grpc;
import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
import io.grpc.stub.StreamObserver;
import java.io.IOException;

public class HelloServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        int port = 50051;
        Server server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
                .addService(new GreeterImpl())
                .build()
                .start();

        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            System.err.println("*** shutting down gRPC server since JVM is shutting down");
            stopServer(server);
            System.err.println("*** server shut down");
        }));
        server.awaitTermination();
    }

    private static void stopServer(Server server) {
        if (server != null) {
            server.shutdown();
        }
    }

    static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
        @Override
        public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
            System.out.println("收到客户端消息:" + req.getName());
            String msg = "我是Java Server";
            System.out.println("回复客户端消息:" + msg);
            HelloReply reply = HelloReply.newBuilder().setMessage("你好!" + msg).build();
            responseObserver.onNext(reply);
            responseObserver.onCompleted();
        }

        @Override
        public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
            System.out.println("再次收到客户端消息:" + req.getName());
            String msg = "我是Java Server2";
            System.out.println("再次回复客户端消息:" + msg);
            HelloReply reply = HelloReply.newBuilder().setMessage(msg).build();
            responseObserver.onNext(reply);
            responseObserver.onCompleted();
        }
    }
}

https://github.com/protocolbuffers/protobuf/releases

3、java、go、php客户端实现

3.1、Java客户端实现

HelloClient.java

package com.penngo;

import com.penngo.grpc.GreeterGrpc;
import com.penngo.grpc.HelloReply;
import com.penngo.grpc.HelloRequest;
import io.grpc.Grpc;
import io.grpc.InsecureChannelCredentials;
import io.grpc.ManagedChannel;

import java.util.concurrent.TimeUnit;

public class HelloClient {
    public static void main(String[] args) throws InterruptedException {
        String host = "localhost";
        int port = 50051;
        ManagedChannel managedChannel = Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create()).build();
        GreeterGrpc.GreeterBlockingStub blockingStub = GreeterGrpc.newBlockingStub(managedChannel);
        String msg1 = "我是java client";
        System.out.println("向服务器端发送消息:" + msg1);
        HelloRequest helloRequest1 = HelloRequest.newBuilder().setName(msg1).build();
        HelloReply reply1 = blockingStub.sayHello(helloRequest1);
        System.out.println("收到服务器端消息:" + reply1.getMessage());

        String msg2 = "我是java client2";
        System.out.println("再次向服务器端发送消息:" + msg2);
        HelloRequest helloRequest2 = HelloRequest.newBuilder().setName(msg2).build();
        HelloReply reply2 = blockingStub.sayHelloAgain(helloRequest2);
        System.out.println("再次收到服务器端消息:" + reply2.getMessage());


        managedChannel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
    }

}

3.2、Go客户端实现

Go的代码生成需要使用protoc.exe来编译helloworld.proto服务文件,生成对应的服务调用代码
下载地址:https://github.com/protocolbuffers/protobuf/releases,当前最新版本为protoc-25.1-win64.zip
解压到目录D:\Program Files\protoc-25.1-win64\bin,需要把这个目录添加到环境变量PATH当中。

安装protocol编译器的Go插件

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

执行下边命令生成Go的gRPC代码

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto

在这里插入图片描述

编写客户端实现代码

package main

import (
	"context"
	"flag"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	pb "grpctest/helloworld"
	"log"
	"time"
)

var (
	addr = flag.String("addr", "localhost:50051", "the address to connect to")
)

func main() {
	flag.Parse()

	// Set up a connection to the server.
	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	// Contact the server and print out its response.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	msg1 := "我是go client"
	log.Printf("向服务器端发送消息: %s", msg1)
	r1, err1 := c.SayHello(ctx, &pb.HelloRequest{Name: msg1})
	if err1 != nil {
		log.Fatalf("could not greet: %v", err1)
	}
	log.Printf("收到服务器端消息:%s", r1.GetMessage())

	msg2 := "我是go client2"
	log.Printf("再次向服务器端发送消息: %s", msg1)
	r2, err2 := c.SayHelloAgain(ctx, &pb.HelloRequest{Name: msg2})

	if err2 != nil {
		log.Fatalf("could not greet: %v", err2)
	}
	log.Printf("再次收到服务器端消息: %s", r2.GetMessage())
}

3.3、PHP客户端实现

安装gRPC的PHP扩展https://pecl.php.net/package/gRPC
当前测试php版本7.3,下载php_grpc-1.42.0-7.3-nts-vc15-x64.zip
php.ini这个文件加入

extension=php_grpc.dll

新建composer.json

{
  "name": "xxs/grpc",
  "require": {
    "grpc/grpc": "^v1.4.0",
    "google/protobuf": "^v3.3.0"
  },
  "autoload":{
    "psr-4":{
      "GPBMetadata\\":"GPBMetadata/",
      "Helloworld\\":"Helloworld/"
    }
  }
}

在composer.json相同目录下执行命令下载依赖库

composer install

安装grpc的php插件,https://github.com/lifenglsf/grpc_for_windows
解压复制到项目下grpc_for_windows/x64/grpc_php_plugin.exe

执行命令生成gRPC代码

protoc --proto_path=. --php_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_for_windows/x64/grpc_php_plugin.exe ./helloworld.proto

在这里插入图片描述

client.php实现

<?php
require dirname(__FILE__) . '/vendor/autoload.php';
//echo dirname(__FILE__) . '/vendor/autoload.php';
function greet($hostname)
{

    $client = new Helloworld\GreeterClient($hostname, [
        'credentials' => Grpc\ChannelCredentials::createInsecure(),
    ]);
    $request = new Helloworld\HelloRequest();

    $msg1 = "我是PHP client";
    $request->setName($msg1);
    echo "向服务器端发送消息: $msg1". PHP_EOL;
    list($response, $status) = $client->SayHello($request)->wait();
    if ($status->code !== Grpc\STATUS_OK) {
        echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;
        exit(1);
    }
    echo "收到服务器端消息:".$response->getMessage() . PHP_EOL;

    $msg2 = "我是PHP client2";
    $request->setName($msg2);
    echo "再次向服务器端发送消息: $msg2". PHP_EOL;
    list($response, $status) = $client->SayHelloAgain($request)->wait();
    if ($status->code !== Grpc\STATUS_OK) {
        echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;
        exit(1);
    }
    echo "再次收到服务器端发送消息:".$response->getMessage() . PHP_EOL;

    $client->close();
}

$hostname = !empty($argv[2]) ? $argv[2] : 'localhost:50051';
greet($hostname);

4、运行效果

服务器端

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1265487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从 0 到 1 开发一个 node 命令行工具

G2 5.0 推出了服务端渲染的能力&#xff0c;为了让开发者更快捷得使用这部分能力&#xff0c;最写了一个 node 命令行工具 g2-ssr-node&#xff1a;用于把 G2 的 spec 转换成 png、jpeg 或者 pdf 等。基本的使用如下&#xff1a; $ g2-ssr-node g2png -i ./bar.json -o ./bar.…

【Intel FPGA】D5005 使用笔记

项目总目标&#xff0c;在AFU中实现xx算法DDR 1.FPGA device &#xff1a;1SX280HN2F43E2VG 2 .硬件架构图 3.DDR信息 4.FIM &#xff08;FPAG Interface Manager&#xff09; The FIM contains the FPGA logic to support the accelerators, including the PCIe IP core, …

UE5、CesiumForUnreal实现加载GeoJson绘制多面(MultiPolygon)功能(支持点选高亮)

文章目录 1.实现目标2.实现过程2.1 数据与预处理2.2 GeoJson解析2.3 Mesh构建与属性存储2.4 核心代码2.5 材质2.6 蓝图应用测试3.参考资料1.实现目标 在之前的文章中,基于GeoJson数据加载,实现了绘制单面功能,但只支持单个要素Feature。本文这里实现对Geojson内所有面要素的…

【CVE-2023-49103】ownCloud graphapi信息泄露漏洞(2023年11月发布)

漏洞简介 ownCloud owncloud/graphapi 0.2.x在0.2.1之前和0.3.x在0.3.1之前存在漏洞。graphapi应用程序依赖于提供URL的第三方GetPhpInfo.php库。当访问此URL时&#xff0c;会显示PHP环境的配置详细信息&#xff08;phpinfo&#xff09;。此信息包括Web服务器的所有环境变量&a…

Python字典类型

目录 目标 版本 官方文档 简介 实战 创建 循环 常用方法 目标 掌握字典类型的使用方法&#xff0c;包括&#xff1a;创建、循环、常用方法等操作。 版本 Python 3.12.0 官方文档 Mapping Types — dicthttps://docs.python.org/3/library/stdtypes.html#mapping-type…

工具及方法 - 如何阅读epub文件:使用Adobe Digital Editions

EPUB&#xff08;Electronic Publication的缩写&#xff0c;电子出版&#xff09;是一种电子图书标准&#xff0c;由国际数字出版论坛&#xff08;IDPF&#xff09;提出&#xff1b;其中包括3种文件格式标准&#xff08;文件的扩展名为.epub&#xff09;&#xff0c;这个格式已…

[操作系统] 面试宝典之~死锁连环系列

文章目录 2.22 什么是死锁2.24 解决死锁的方法死锁的预防死锁的避免死锁的检测死锁的解除 2.22 什么是死锁 在多道程序环境下&#xff0c;多个进程可以竞争有限数量的资源。当一个进程申请资源时&#xff0c;如果这时没有可用资源&#xff0c;那么这个进程进入等待状态。有时&…

Linux ps命令详解:如何查看进程的PID、占用的CPU和内存使用率、虚拟内存大小等信息(附实例教程和注意事项)

Linux ps命令介绍 Linux ps命令&#xff0c;全称为process status&#xff0c;是一个非常实用的命令&#xff0c;用于显示当前进程的状态。它的功能类似于Windows的任务管理器。通过ps命令&#xff0c;我们可以查看到进程的PID、占用的CPU和内存使用率、虚拟内存大小、实际内存…

numpy知识库:np.random.randint()用法及其使用场景举例

randint函数解析 import numpy as np# 【随机】返回[0,5)范围内的一个整数 # [0, 5) --> 左闭右开区间 int_a np.random.randint(5) # int_a 可能为 0、1、2、3、4 int_a np.random.randint(low5) # int_a 可能为 0、1、2、3、4# 【随机】返回[1,5)范围内的一个整数 int_…

【闲读 1】量子论引出对认知的思考

文章目录 一、物理学的两朵乌云故事量子力学的世界 二、 波粒二象性三、量子不确定性四、感知尺度 混沌学院课程《【物理学思维】第四节 量子论》&#xff0c;观后感。 一、物理学的两朵乌云故事 19世纪末&#xff0c;著名的物理学家开尔文爵士&#xff08;温度单位命民&…

Git分支管理--Bug分支

愿所有美好如期而遇 我们现在正在dev4分支上进行开发&#xff0c;但是在我们开发过程中&#xff0c;并且我们还未提交&#xff0c;master分支上出现了bug&#xff0c;需要我们修复&#xff0c;我们先来看情景 我们添加一行代码并且不提交充作开发&#xff0c;模拟正在进行开发时…

SpringBoot快速体验

场景&#xff1a;浏览器发送/hello请求&#xff0c;返回"Hello,Spring Boot 3!" 1. 开发流程 1. 创建项目 maven 项目 <!-- 所有springboot项目都必须继承自 spring-boot-starter-parent --><parent><groupId>org.springframework.boot<…

基于SSM的社区团购系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

PWM占空比原理是什么,几个实例带你进一步了解

PWM : 即脉冲宽度调制(Pulse Width Modulation) 脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术&#xff0c;广泛应用在从测量、通信到功率控制与变换及嵌入式领域的许多领域中。 PWM控制技术以其控制简单&#xff0c;灵活和动态响应好的优点而…

11月28日作业

提示并输入一个字符串&#xff0c;统计该字符中大写&#xff0c;小写字母个数&#xff0c;数字个数&#xff0c;空格个数以及其他字符个数&#xff0c;要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {string str;int A0,a0,num0,backspac…

TiDB 在咪咕云原生场景下的实践

导读 咪咕是中国移动旗下的视频科技公司&#xff0c;门户系统是其核心业务之一。 为满足用户的多样化需求&#xff0c;咪咕计划对其数据库进行升级。 经过对中国主流国产数据库的测试评估后&#xff0c;咪咕选择了 TiDB&#xff0c;并成功将其落地于门户系统云化项目。 TiDB 为…

《尚品甄选》:后台系统——权限管理之分类和品牌管理,使用EasyExcel导入导出数据(debug一遍)

文章目录 一、分类管理1.1 表结构介绍1.2 分类列表查询 二、EasyExcel使用2.1 EasyExcel简介2.2 导出功能2.3 导入功能 三、品牌管理3.1 表结构介绍3.2 列表查询3.3 添加品牌3.4 修改品牌3.5 删除品牌 一、分类管理 分类管理就是对商品的分类数据进行维护。 1.1 表结构介绍 分…

蓝桥杯day02——第三大的数

题目 给你一个非空数组&#xff0c;返回此数组中 第三大的数 。如果不存在&#xff0c;则返回数组中最大的数。 示例 1&#xff1a; 输入&#xff1a;[3, 2, 1] 输出&#xff1a;1 解释&#xff1a;第三大的数是 1 。 示例 2&#xff1a; 输入&#xff1a;[1, 2] 输出&…

Day41 使用listwidget制作简易图片播放器

1.简介 使用QlistWidget实现简易图片播放器&#xff0c;可以打开一个图片序列&#xff0c;通过item的单击事件实现图片的切换&#xff0c;通过设置list的各种属性实现图片预览的显示&#xff0c;美化滚动条即可实现一个简易图片播放器。 2.效果 3.实现步骤&#xff1a; 1.初始…

Python缺失值处理实现

在数据处理相关工作中&#xff0c;读取的数据中常常会有缺失值的情况&#xff0c;为顺利进行后续的操作&#xff0c;需要首先对缺失值进行处理&#xff0c;处理的方式一般为删除或填充&#xff0c;Python中提供了专门的工具包&#xff0c;可以方便地进行实现。读取操作可以由pa…