GraphQL基础知识与Spring for GraphQL使用教程

news2024/12/23 0:43:26

文章目录

    • 1、数据类型
      • 1.1、标量类型
      • 1.2. 高级数据类型
    • 基本操作
    • 2、Spring for GraphQL实例
      • 2.1、项目目录
      • 2.2、数据库表
      • 2.3、GraphQL的schema.graphql
      • 2.4、Java代码
    • 3、运行效果
      • 3.1、添加用户
      • 3.2、添加日志
      • 3.3、查询所有日志
      • 3.4、查询指定用户日志
      • 3.5、数据订阅
    • 4、总结

GraphQL是一种用于API开发的查询语言和运行时环境。它由Facebook开发并于2015年开源。GraphQL的主要目标是提供一种更高效、灵活和易于使用的方式来获取和操作数据。与传统的RESTful API相比,GraphQL允许客户端精确地指定需要的数据,并减少了不必要的网络传输和数据处理。
采用GraphQL,甚至不需要有任何的接口文档,在定义了Schema之后,服务端实现Schema,客户端可以查看Schema,然后构建出自己需要的查询请求来获得自己需要的数据。

1、数据类型

1.1、标量类型

  1. Int -32位整型数字;
  2. Float-双精度浮点型;
  3. String-UTF‐8 字符序列;
  4. Boolean-布尔型,true 或者 false;
  5. ID-标识类型,唯一标识符,注意此ID为字符,如果使用Mysql自增长id,也会自动转为对应的字符串;

1.2. 高级数据类型

  1. Object - 对象,用于描述层级或者树形数据结构。Object类型有一个类型名,以及类型包含的字段。
type Product {
    id: ID!
    info: String!
    price: Float
}

在此示例中,声明了Product对象类型,定义了3 个字段:
id:非空 ID 类型。
info:非空字符串类型。
price:浮点型。

  1. Interface-接口,用于描述多个类型的通用字;与 Object一样。
interface Product {
    id: ID!
    info: String!
    price: Float
}
  1. Union-联合类型,用于描述某个字段能够支持的所有返回类型以及具体请求真正的返回类型;
  2. Enum-枚举,用于表示可枚举数据结构的类型;
enum Status {
  Yes
  No
}
type Product {
    id: ID!
    info: String!
    price: Float
    stat: Status
}
  1. Input-输入类型input本质上也是一个type类型,是作为Mutation接口的输入参数。换言之,想要定义一个修改接口(add,update,delete)的输入参数对象,就必须定义一个input输入类型。
input BookInput {
    isbn: ID!
    title: String!
    pages: Int
    authorIdCardNo: String
}
  1. List -列表,任何用方括号 ([]) 括起来的类型都会成为 List 类型。
type Product {
    id: ID!
    info: String
    price: Float
    images: [String]
}
  1. Non-Null-不能为 Null,类型后边加!表示非空类型。例如,String 是一个可为空的字符串,而String!是必需的字符串。

基本操作

  • Query(只读操作)
#schema.graphqls定义操作
type Query {
    allBooks: [Book]!
    bookByIsbn(isbn: ID): Book
}

# 接口查询语法
query{
  allBooks {
    title
    author {
      name
      age
    }
  }
}
  • Mutation(可写操作)
#schema.graphqls定义操作
type Mutation {
    createBook(bookInput: BookInput): Book
    createAuthor(authorInput: AuthorInput): Author
}

# mutation{
#   createAuthor(authorInput:{ 
#     idCardNo: "341234567891234567",
#     name:"test1",
#     age:38
#   }
#   ){
#     name 
#     age
#   }
# }
  • Subscription(订阅操作)
type Subscription {
    greetings: String
}

2、Spring for GraphQL实例

GraphQL只是一种架构设计,具体的实现需要各个技术平台自己实现,目前主流的开发语言基本都已经有现成的类库可以使用,GraphQL Java就是Java平台的实现。
GraphQL Java虽然实现了GraphQL,但是只是一个执行GraphQL请求的引擎,用户在使用中需要创建自己的HTTP服务来提供服务。

Spring for GraphQL为基于GraphQL Java构建的Spring应用程序提供支持,来自 GraphQL Java 团队,它的目标是成为所有Spring、GraphQL应用程序的基础。

spring-graphql中定义的核心注解如下:

  • @GraphQlController:申明该类是GraphQL应用中的控制器
  • @QueryMapping:申明该类或方法使用GraphQL的query操作,等同于@SchemaMapping(typeName = “Query”),类似于@GetMapping
  • @Argument:申明该参数是GraphQL应用的入参
  • @MutationMapping:申明该类或方法使用GraphQL的mutation操作,等同于@SchemaMapping(typeName = “Mutation”)
  • @SubscriptionMapping:申明该类或方法使用GraphQL的subscription操作,等同于@SchemaMapping(typeName = “Subscription”)
  • @SchemaMapping:指定GraphQL操作类型的注解,类似@RequestMapping

2.1、项目目录

项目代码目录
在这里插入图片描述

2.2、数据库表

数据表结构,这里例子简单用了用户表和用户日志表

CREATE TABLE `admin_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4
    
CREATE TABLE `admin_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `visit_url` varchar(255) DEFAULT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4

2.3、GraphQL的schema.graphql

GraphQL对应的schema.graphql定义文件,注意GraphQL默认只支持标量类型,DateTime自定义类型使用graphql-java-extended-scalars:https://github.com/graphql-java/graphql-java-extended-scalars提供

scalar DateTime

type AdminUser{
    id: ID!
    name: String!
}

type AdminLog{
    id: ID!
    visitUrl: String
    user: AdminUser!
    createDate: DateTime
}

type Query {
    allLogs:[AdminLog]
    logByUser(userid: ID): [AdminLog]
}

type Mutation {
    createUser(adminUserInput: AdminUserInput): AdminUser
    createLog(adminLogInput: AdminLogInput): AdminLog
}


input AdminLogInput {
    userId: String!
    visitUrl: String
    createDate: DateTime
}

input AdminUserInput {
    name: String!
}

type Subscription {
    greetings: String
}

2.4、Java代码

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 https://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>3.0.10</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.penngo.example</groupId>
	<artifactId>graphql-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>graphql-app</name>
	<description>graphql-app project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
		<maven.compiler.source>17</maven.compiler.source>
		<maven.compiler.target>17</maven.compiler.target>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-graphql</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.23</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-java-extended-scalars -->
		<dependency>
			<groupId>com.graphql-java</groupId>
			<artifactId>graphql-java-extended-scalars</artifactId>
			<version>19.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</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>aliyun-plugin</id>
			<url>https://maven.aliyun.com/repository/public</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

</project>

对应的数据库实体类

package com.penngo.example.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.OffsetDateTime;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdminLog {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;
    private String userId;
    private String visitUrl;
    private OffsetDateTime createDate;
}

package com.penngo.example.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdminUser {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;
    private String name;
}

GraphQL对应的输入类

package com.penngo.example.entity;
import lombok.Data;
import java.time.OffsetDateTime;
@Data
public class AdminLogInput {
    private String userId;
    private String visitUrl;
    private OffsetDateTime createDate;

}

package com.penngo.example.entity;
import lombok.Data;
@Data
public class AdminUserInput {
    private String name;
}

对应的数据库操作类

package com.penngo.example.repository;
import com.penngo.example.entity.AdminUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AdminUserRepository  extends JpaRepository<AdminUser,Long> {
    AdminUser findById(String userId);
}

package com.penngo.example.repository;
import com.penngo.example.entity.AdminLog;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;

public interface AdminLogRepository  extends JpaRepository<AdminLog,Long> {
    List<AdminLog> findAllByUserId(String userId);
}

对外服务接口类

package com.penngo.example.controller;
import com.penngo.example.entity.*;
import com.penngo.example.repository.AdminLogRepository;
import com.penngo.example.repository.AdminUserRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
import java.util.List;

@Controller
public class AdminLogController {
    private final AdminUserRepository adminUserRepository;
    private final AdminLogRepository adminLogRepository;

    public AdminLogController(AdminUserRepository adminUserRepository, AdminLogRepository adminLogRepository){
        this.adminLogRepository = adminLogRepository;
        this.adminUserRepository = adminUserRepository;
    }
    @QueryMapping
    public List<AdminLog> allLogs(){
        List<AdminLog> logsList = adminLogRepository.findAll();
        return logsList;
    }
    @QueryMapping
    public List<AdminLog> logByUser(@Argument String userid){
        return adminLogRepository.findAllByUserId(userid);
    }

    @SchemaMapping(typeName = "AdminLog" ,field = "user")
    public AdminUser getAuthor(AdminLog adminLog){
        AdminUser adminUser = adminUserRepository.findById(adminLog.getUserId());
        return adminUser;
    }
    @MutationMapping
    public AdminLog createLog(@Argument AdminLogInput adminLogInput){
        AdminLog log = new AdminLog();
        BeanUtils.copyProperties(adminLogInput,log);
        return adminLogRepository.save(log);
    }
}

package com.penngo.example.controller;
import com.penngo.example.entity.*;
import com.penngo.example.repository.AdminLogRepository;
import com.penngo.example.repository.AdminUserRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import java.util.List;

@Controller
public class AdminUserController {
    private final AdminUserRepository adminUserRepository;
    private final AdminLogRepository adminLogRepository;

    public AdminUserController(AdminUserRepository adminUserRepository, AdminLogRepository adminLogRepository){
        this.adminLogRepository = adminLogRepository;
        this.adminUserRepository = adminUserRepository;
    }
    @QueryMapping
    public List<AdminLog> userById(@Argument String userid){
        return adminLogRepository.findAllByUserId(userid);
    }
    @MutationMapping
    public AdminUser createUser(@Argument AdminUserInput adminUserInput){
        AdminUser user = new AdminUser();
        BeanUtils.copyProperties(adminUserInput,user);
        return adminUserRepository.save(user);
    }
}

package com.penngo.example.controller;
import com.penngo.example.entity.AdminLog;
import com.penngo.example.repository.AdminLogRepository;
import com.penngo.example.repository.AdminUserRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.graphql.data.method.annotation.SubscriptionMapping;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.Flux;
import java.time.Duration;

@Controller
public class GreetingController {
   private final AdminUserRepository adminUserRepository;
   private final AdminLogRepository adminLogRepository;

   public GreetingController(AdminUserRepository adminUserRepository, AdminLogRepository adminLogRepository){
      this.adminLogRepository = adminLogRepository;
      this.adminUserRepository = adminUserRepository;
   }
   // 数据订阅,取最新的5条数据,每5秒发送一条给客户端,一共5次
   @SubscriptionMapping
   public Flux<AdminLog> greetings(){
      System.out.println("greetings====================");
      Page<AdminLog> logsList = adminLogRepository.findAll(PageRequest.of(0,5).withSort(Sort.Direction.DESC, "id"));
      return Flux.fromStream(logsList.stream())
              .delayElements(Duration.ofSeconds(5))
              .take(5);
   }
}

自定义日期数据类型DateTime

package com.penngo.example.component;
import graphql.scalars.ExtendedScalars;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;

@Configuration
public class CustomScalarType {
    @Bean
    public RuntimeWiringConfigurer runtimeWiringConfigurer() {
        return wiringBuilder -> wiringBuilder.scalar(ExtendedScalars.DateTime);
    }
}

服务启动类

package com.penngo.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GraphqlAppApplication {
	public static void main(String[] args) {
		SpringApplication.run(GraphqlAppApplication.class, args);
	}
}

3、运行效果

3.1、添加用户

添加用户

mutation{ 
  createUser(adminUserInput: { 
    name: "test1", 
  } ) 
  { 
    id 
    name 
  } }

在这里插入图片描述

3.2、添加日志

添加日志

mutation{
   createLog(adminLogInput: {
      userId: "1",
      visitUrl: "http://localhost:8080/method1"
      createDate: "2023-09-17T19:39:57+08:00"
   } )
   {
      id
      visitUrl
      createDate
   } }  

在这里插入图片描述

3.3、查询所有日志

查询所有日志

query{
  allLogs{
    id
    visitUrl
    user{
    	id
    	name
    }
    createDate
  }
}

在这里插入图片描述

3.4、查询指定用户日志

查询指定用户日志

query{
  logByUser(userid:"1") {
    id
    visitUrl
    user{
    	id
    	name
    }
    createDate
  }
}

在这里插入图片描述

3.5、数据订阅

数据订阅,订阅需要有websocket的支持。

subscription {
  greetings
}

在这里插入图片描述
在这里插入图片描述

4、总结

使用Spring for GraphQL试用了GraphQL后,它实现按需取数据的功能。服务器开发人员和前端开发人员可以通过schema.graphqls定义文件,协定好接口和数据,省掉写接口文档的工作。
缺点可能就是需要一点学习成本,虽然提供数据嵌套可以通过一个请求获取所有数据,但是嵌套复杂可能引起性能问题。

Spring for GraphQL官方参考:https://docs.spring.io/spring-graphql/docs/current/reference/html/#overview

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

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

相关文章

多输入多输出 | Matlab实现GWO-BP灰狼算法优化BP神经网络多输入多输出预测

多输入多输出 | Matlab实现GWO-BP灰狼算法优化BP神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现GWO-BP灰狼算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现GWO-BP灰狼算法优化BP神经网络…

python有限差分法求解一维热传导方程

​1、方程及其离散 1.1一维热传导方程 1.2离散化 设定步长&#xff0c;依据上述方程得到递推关系&#xff1a; 2、python求解实现 import numpy as np import matplotlib.pyplot as plth 0.1#空间步长 N 30#空间步数 dt 0.0001#时间步长 M 10000#时间的步数 A dt/(h**2)…

Oracle数据库体系结构(一)_概述

目录 1 Oracle系统框架 1.1 Orace SGA组成 1.2 Oracle后台进程 1.3 PGA服务进程 2 数据库与实例 2.1 数据库 2.2 实例 3 总结 Oracle公司&#xff08;甲骨文&#xff09;是全球最大的信息管理软件及服务供应商&#xff0c;成立于1977年&#xff0c;总部位于美国加…

关于rdkit 错误2w08_ligand: warning - O.co2 with non C.2 or S.o2 neighbor.

1 问题&#xff1a; 读取 PDBBindv2019的数据集&#xff0c;尝试把所有配体的mol2文件转换成对应smiles表达式。大约超过1千个出现问题。 主要问题就是‘warning - O.co2 with non C.2 or S.o2 neighbor’。 2 原因&#xff1a; Phosphate group - warning O.co2 with non C…

Rocky Linux 安装图解(替代centos)服务器+桌面

centos自从20年底转变为不稳定版本后&#xff0c;有很多替代方案 经过近3年的发展&#xff0c;rocky linux算是一个比较好的选择&#xff0c;一是依照red hat企业版来做&#xff0c;二是rocky的发起者也是centos的创始人 如果想安装debian&#xff0c;可以参考&#xff1a;deb…

微服务保护-初识Sentinel

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

【详细教程hexo博客搭建】2、Vercel部署并绑定自定义域名+安装Butterfly主题

2.Vercel部署与自定义域名 2.1 Vercel部署 Vercel简介&#xff1a;vercel是一个代码托管平台&#xff0c;它能够托管你的静态html界面&#xff0c;甚至能够托管你的node.js与Python服务端脚本&#xff0c;是不想买服务器的懒人的福音&#xff01; 使用Vercel部署Hexo项目步骤…

在openSUSE-Leap-15.5-DVD-x86_64中使用钉钉dingtalk_7.0.40.30829_amd64

在openSUSE-Leap-15.5-DVD-x86_64中使用钉钉dingtalk_7.0.40.30829_amd64 一、到官网下载钉钉Linux客户端 https://page.dingtalk.com/wow/z/dingtalk/simple/ddhomedownload#/ localhost:~ # ls -lh /home/suozhang/download/com.alibabainc.dingtalk_7.0.40.30829_amd64.d…

一篇文章学会正则表达式的语法

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ 正则表达式&#xff08;Regular Expression&#xff09;在代码中常常简写为regex。正则表达式通常被用来检索、替换那些符合某个规则的文本&#xff0c;它是一种强大而灵活…

1. 快速体验 VSCode 和 CMake 创建 C/C++项目

1. 快速体验 VSCode 和 CMake 创建 C/C项目 本章的全部代码和markdown文件地址: CMake_Tutorial&#xff0c;欢迎互相交流. 此次介绍的内容都是针对于 Linux 操作系统上的开发过程. 1.1 安装开发工具 VSCode: 自行下载安装, 然后安装插件 Cmake:在 Ubuntu 系统上, 可以采用 ap…

[k8s] pod的创建过程

pod的创建过程 定义 Pod 的规范&#xff1a; apiVersion: v1 kind: Pod metadata:name: my-pod spec:containers:- name: my-containerimage: nginx:latest创建 Pod 对象&#xff1a; 使用 kubectl 命令行工具或其他客户端工具创建 Pod 对象&#xff1a; kubectl create -f…

【JAVA-Day15】Java 的 do-while 循环语句

Java 的 do-while 循环语句 Java 的 do-while 循环语句摘要引言一、什么是 do-while 循环语句二、do-while 循环语句的语法三、do-while 循环的优势和使用场景优势使用场景 与其他方式相比优势劣势与while循环比较与for循环比较 建议四、总结参考资料 博主 默语带您 Go to New …

90 # 实现 express 请求处理

上一节构建 layer 和 route 的关系&#xff0c;这一节来实现 express 请求处理 application.js const http require("http"); const Router require("./router");function Application() {this._router new Router(); }Application.prototype.get fu…

【C语言】【数据存储】用%u打印char类型?用char存128?

1.题目一&#xff1a; #include <stdio.h> int main() {char a -128;printf("%u\n",a);return 0; }%u 是打印无符号整型 解题逻辑&#xff1a; 1. 原反补互换&#xff0c;截断 -128 原码&#xff1a;10000000…10000000 补码&#xff1a;11111111…10000000…

【初阶数据结构】树(tree)的基本概念——C语言

目录 一、树&#xff08;tree&#xff09; 1.1树的概念及结构 1.2树的相关概念 1.3树的表示 1.4树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 二、二叉树的概念及结构 2.1二叉树的概念 2.2现实中真正的二叉树 2.3特殊的二叉树 2.4二叉树的性质…

【iOS】ViewController的生命周期

文章目录 前言一、UIViewController生命周期有关函数二、执行顺序注意点loadview&#xff1a; 前言 在iOS开发中UIViewController扮演者非常重要的角色&#xff0c;它是视图view和数据model的桥梁&#xff0c;通过UIViewController的管理有条不紊的将数据展示在视图上。作为UI…

XML 和 JSON 学习笔记(基础)

XML Why XML 的出现背景&#xff1a;在实际开发中&#xff0c;不同语言&#xff08;如Java、JavaScript等&#xff09;的应用程序之间数据传递的格式不同&#xff0c;导致它们进行数据交换时很困难&#xff0c;XML就应运而生了&#xff01;&#xff08;XML 是一种通用的数据交…

视频分析【video analytics】的项目的关键因素 -- 如何选择合适的摄像头,存储设备,以及AI推理硬件?

文字大纲 参考指标摄像机存储设备AI 推理硬件参考文献与学习路径参考指标 摄像机 通常的做法是将视频视为一系列图像(帧),并使用仅在图像上训练的深度神经网络模型来执行视频上的相似分析任务。在这篇论文中,我们表明,这种在图像上运行良好的深度学习模型在视频上也会运行…

QT:使用普通按钮、网格布局管理器、标签、行编辑器、水平布局管理器、垂直布局管理器做一个小项目

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> //普通按钮 #include <QGridLayout> //网格布局管理器 #include <QLabel> //标签 #include <QLineEdit> //行编辑器 #include <QHBoxLayo…