Spring Boot 数据访问与数据库集成

Spring Boot 数据访问与数据库集成

Spring Boot 数据访问与数据库集成

在这里插入图片描述
18.1 学习目标与重点提示

学习目标:掌握Spring Boot数据访问与数据库集成的核心概念与使用方法,包括Spring Boot数据访问的基本方法、Spring Boot与MySQL的集成、Spring Boot与H2的集成、Spring Boot与MyBatis的集成、Spring Boot与JPA的集成、Spring Boot的事务管理、Spring Boot的实际应用场景,学会在实际开发中处理数据库访问问题。
重点:Spring Boot数据访问的基本方法Spring Boot与MySQL的集成Spring Boot与H2的集成Spring Boot与MyBatis的集成Spring Boot与JPA的集成Spring Boot的事务管理Spring Boot的实际应用场景

18.2 Spring Boot数据访问概述

Spring Boot数据访问是指使用Spring Boot进行数据库操作的方法。

18.2.1 数据访问的定义

定义:数据访问是指使用Spring Boot进行数据库操作的方法。
作用

  • 实现数据库的增删改查。
  • 实现事务管理。
  • 实现数据的持久化。

✅ 结论:数据访问是指使用Spring Boot进行数据库操作的方法,作用是实现数据库的增删改查、事务管理、数据的持久化。

18.2.2 数据访问的常用组件

定义:数据访问的常用组件是指Spring Boot提供的数据访问组件。
组件

  • JdbcTemplate:用于JDBC操作。
  • JPA:用于JPA操作。
  • MyBatis:用于MyBatis操作。
  • Hibernate:用于Hibernate操作。

✅ 结论:数据访问的常用组件包括JdbcTemplate、JPA、MyBatis、Hibernate。

18.3 Spring Boot与MySQL的集成

Spring Boot与MySQL的集成是最常用的数据访问方法之一。

18.3.1 集成MySQL的步骤

定义:集成MySQL的步骤是指使用Spring Boot与MySQL集成的方法。
步骤

  1. 在pom.xml文件中添加MySQL依赖。
  2. 在application.properties或application.yml文件中配置MySQL连接信息。
  3. 创建实体类。
  4. 创建Repository接口。
  5. 创建控制器类。
  6. 测试应用。

示例
pom.xml文件中的MySQL依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MySQL依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的MySQL连接信息:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=123456 # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true 

实体类:

importjavax.persistence.*;@Entity@Table(name ="product")publicclassProduct{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}

Repository接口:

importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;importjava.util.List;@RepositorypublicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{List<Product>findBySalesGreaterThan(int sales);}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.List;@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductRepository productRepository;@GetMapping("/")publicList<Product>getAllProducts(){return productRepository.findAll();}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productRepository.save(product);}@GetMapping("/top-selling")publicList<Product>getTopSellingProducts(@RequestParamint topN){List<Product> products = productRepository.findBySalesGreaterThan(0); products.sort((p1, p2)-> p2.getSales()- p1.getSales());if(products.size()> topN){return products.subList(0, topN);}return products;}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importjava.util.List;importstaticorg.junit.jupiter.api.Assertions.assertEquals;@SpringBootTestclassProductApplicationTests{@AutowiredprivateProductController productController;@TestvoidcontextLoads(){}@TestvoidtestGetAllProducts(){List<Product> products = productController.getAllProducts();assertEquals(5, products.size());}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product addedProduct = productController.addProduct(product);assertEquals("P006", addedProduct.getProductId());}@TestvoidtestGetTopSellingProducts(){List<Product> topSellingProducts = productController.getTopSellingProducts(3);assertEquals(3, topSellingProducts.size());assertEquals("P004", topSellingProducts.get(0).getProductId());assertEquals("P005", topSellingProducts.get(1).getProductId());assertEquals("P001", topSellingProducts.get(2).getProductId());}}

✅ 结论:集成MySQL的步骤包括添加MySQL依赖、配置MySQL连接信息、创建实体类、创建Repository接口、创建控制器类、测试应用。

18.4 Spring Boot与H2的集成

Spring Boot与H2的集成是用于开发和测试的常用方法之一。

18.4.1 集成H2的步骤

定义:集成H2的步骤是指使用Spring Boot与H2集成的方法。
步骤

  1. 在pom.xml文件中添加H2依赖。
  2. 在application.properties或application.yml文件中配置H2连接信息。
  3. 创建实体类。
  4. 创建Repository接口。
  5. 创建控制器类。
  6. 测试应用。

示例
pom.xml文件中的H2依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的H2连接信息:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console 

实体类、Repository接口、控制器类、测试类与集成MySQL的示例相同。

✅ 结论:集成H2的步骤包括添加H2依赖、配置H2连接信息、创建实体类、创建Repository接口、创建控制器类、测试应用。

18.5 Spring Boot与MyBatis的集成

Spring Boot与MyBatis的集成是常用的数据访问方法之一。

18.5.1 集成MyBatis的步骤

定义:集成MyBatis的步骤是指使用Spring Boot与MyBatis集成的方法。
步骤

  1. 在pom.xml文件中添加MyBatis依赖。
  2. 在application.properties或application.yml文件中配置MyBatis连接信息。
  3. 创建实体类。
  4. 创建Mapper接口。
  5. 创建Mapper XML文件。
  6. 创建控制器类。
  7. 测试应用。

示例
pom.xml文件中的MyBatis依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis依赖 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.0</version></dependency><!-- MySQL依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的MyBatis连接信息:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=123456 # MyBatis配置 mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.example.demo.entity 

实体类:

publicclassProduct{privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}

Mapper接口:

importorg.apache.ibatis.annotations.Mapper;importjava.util.List;@MapperpublicinterfaceProductMapper{List<Product>findAll();intinsert(Product product);List<Product>findBySalesGreaterThan(int sales);}

Mapper XML文件(src/main/resources/mapper/ProductMapper.xml):

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.example.demo.mapper.ProductMapper"><resultMapid="ProductResultMap"type="com.example.demo.entity.Product"><idproperty="id"column="id"/><resultproperty="productId"column="product_id"/><resultproperty="productName"column="product_name"/><resultproperty="price"column="price"/><resultproperty="sales"column="sales"/></resultMap><selectid="findAll"resultMap="ProductResultMap"> SELECT * FROM product </select><insertid="insert"parameterType="com.example.demo.entity.Product"> INSERT INTO product (product_id, product_name, price, sales) VALUES (#{productId}, #{productName}, #{price}, #{sales}) </insert><selectid="findBySalesGreaterThan"parameterType="int"resultMap="ProductResultMap"> SELECT * FROM product WHERE sales > #{sales} </select></mapper>

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.List;@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductMapper productMapper;@GetMapping("/")publicList<Product>getAllProducts(){return productMapper.findAll();}@PostMapping("/")publicintaddProduct(@RequestBodyProduct product){return productMapper.insert(product);}@GetMapping("/top-selling")publicList<Product>getTopSellingProducts(@RequestParamint topN){List<Product> products = productMapper.findBySalesGreaterThan(0); products.sort((p1, p2)-> p2.getSales()- p1.getSales());if(products.size()> topN){return products.subList(0, topN);}return products;}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importjava.util.List;importstaticorg.junit.jupiter.api.Assertions.assertEquals;@SpringBootTestclassProductApplicationTests{@AutowiredprivateProductController productController;@TestvoidcontextLoads(){}@TestvoidtestGetAllProducts(){List<Product> products = productController.getAllProducts();assertEquals(5, products.size());}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);int count = productController.addProduct(product);assertEquals(1, count);}@TestvoidtestGetTopSellingProducts(){List<Product> topSellingProducts = productController.getTopSellingProducts(3);assertEquals(3, topSellingProducts.size());assertEquals("P004", topSellingProducts.get(0).getProductId());assertEquals("P005", topSellingProducts.get(1).getProductId());assertEquals("P001", topSellingProducts.get(2).getProductId());}}

✅ 结论:集成MyBatis的步骤包括添加MyBatis依赖、配置MyBatis连接信息、创建实体类、创建Mapper接口、创建Mapper XML文件、创建控制器类、测试应用。

18.6 Spring Boot与JPA的集成

Spring Boot与JPA的集成是常用的数据访问方法之一。

18.6.1 集成JPA的步骤

定义:集成JPA的步骤是指使用Spring Boot与JPA集成的方法。
步骤

  1. 在pom.xml文件中添加JPA依赖。
  2. 在application.properties或application.yml文件中配置JPA连接信息。
  3. 创建实体类。
  4. 创建Repository接口。
  5. 创建控制器类。
  6. 测试应用。

示例
pom.xml文件中的JPA依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MySQL依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的JPA连接信息:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=123456 # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true 

实体类、Repository接口、控制器类、测试类与集成MySQL的示例相同。

✅ 结论:集成JPA的步骤包括添加JPA依赖、配置JPA连接信息、创建实体类、创建Repository接口、创建控制器类、测试应用。

18.7 Spring Boot的事务管理

Spring Boot的事务管理是数据访问的重要组件。

18.7.1 事务管理的定义

定义:事务管理是指使用Spring Boot进行事务处理的方法。
作用

  • 保证数据的一致性。
  • 保证数据的完整性。
  • 保证数据的原子性。

常用注解

  • @Transactional:标记方法或类为事务方法。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@TransactionalpublicvoidaddProduct(Product product){ productRepository.save(product);}@TransactionalpublicvoidupdateProduct(Product product){ productRepository.save(product);}@TransactionalpublicvoiddeleteProduct(Long id){ productRepository.deleteById(id);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}@Transactional(readOnly =true)publicList<Product>getTopSellingProducts(int topN){List<Product> products = productRepository.findBySalesGreaterThan(0); products.sort((p1, p2)-> p2.getSales()- p1.getSales());if(products.size()> topN){return products.subList(0, topN);}return products;}}

✅ 结论:事务管理是指使用Spring Boot进行事务处理的方法,常用注解包括@Transactional。

18.8 Spring Boot的实际应用场景

在实际开发中,Spring Boot数据访问与数据库集成的应用场景非常广泛,如:

  • 实现商品的展示与购买。
  • 实现订单的管理。
  • 实现用户的管理。
  • 实现博客的发布与管理。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importorg.springframework.web.bind.annotation.*;importjavax.persistence.*;importjava.util.List;// 产品类@Entity@Table(name ="product")publicclassProduct{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}// 产品Repository@RepositorypublicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{List<Product>findBySalesGreaterThan(int sales);}// 产品Service@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@TransactionalpublicvoidaddProduct(Product product){ productRepository.save(product);}@TransactionalpublicvoidupdateProduct(Product product){ productRepository.save(product);}@TransactionalpublicvoiddeleteProduct(Long id){ productRepository.deleteById(id);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}@Transactional(readOnly =true)publicList<Product>getTopSellingProducts(int topN){List<Product> products = productRepository.findBySalesGreaterThan(0); products.sort((p1, p2)-> p2.getSales()- p1.getSales());if(products.size()> topN){return products.subList(0, topN);}return products;}}// 产品控制器@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductService productService;@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}@PostMapping("/")publicvoidaddProduct(@RequestBodyProduct product){ productService.addProduct(product);}@PutMapping("/{id}")publicvoidupdateProduct(@PathVariableLong id,@RequestBodyProduct product){ product.setId(id); productService.updateProduct(product);}@DeleteMapping("/{id}")publicvoiddeleteProduct(@PathVariableLong id){ productService.deleteProduct(id);}@GetMapping("/top-selling")publicList<Product>getTopSellingProducts(@RequestParamint topN){return productService.getTopSellingProducts(topN);}}// 应用启动类@SpringBootApplicationpublicclassProductApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ProductApplication.class, args);}@AutowiredprivateProductService productService;publicvoidrun(String... args){// 初始化数据 productService.addProduct(newProduct("P001","手机",1000.0,100)); productService.addProduct(newProduct("P002","电脑",5000.0,50)); productService.addProduct(newProduct("P003","电视",3000.0,80)); productService.addProduct(newProduct("P004","手表",500.0,200)); productService.addProduct(newProduct("P005","耳机",300.0,150));}}// 测试类@SpringBootTestclassProductApplicationTests{@AutowiredprivateProductController productController;@TestvoidcontextLoads(){}@TestvoidtestGetAllProducts(){List<Product> products = productController.getAllProducts();assertEquals(5, products.size());}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70); productController.addProduct(product);List<Product> products = productController.getAllProducts();assertEquals(6, products.size());}@TestvoidtestUpdateProduct(){Product product =newProduct("P001","手机",1500.0,120); productController.updateProduct(1L, product);List<Product> products = productController.getAllProducts();assertEquals(1500.0, products.get(0).getPrice());}@TestvoidtestDeleteProduct(){ productController.deleteProduct(2L);List<Product> products = productController.getAllProducts();assertEquals(4, products.size());}@TestvoidtestGetTopSellingProducts(){List<Product> topSellingProducts = productController.getTopSellingProducts(3);assertEquals(3, topSellingProducts.size());assertEquals("P004", topSellingProducts.get(0).getProductId());assertEquals("P005", topSellingProducts.get(1).getProductId());assertEquals("P001", topSellingProducts.get(2).getProductId());}}

输出结果

访问http://localhost:8080/api/products/top-selling?topN=3:

[{"id":4,"productId":"P004","productName":"手表","price":500.0,"sales":200},{"id":5,"productId":"P005","productName":"耳机","price":300.0,"sales":150},{"id":1,"productId":"P001","productName":"手机","price":1500.0,"sales":120}]

访问http://localhost:8080/api/products/:

[{"id":1,"productId":"P001","productName":"手机","price":1500.0,"sales":120},{"id":3,"productId":"P003","productName":"电视","price":3000.0,"sales":80},{"id":4,"productId":"P004","productName":"手表","price":500.0,"sales":200},{"id":5,"productId":"P005","productName":"耳机","price":300.0,"sales":150},{"id":6,"productId":"P006","productName":"平板","price":2000.0,"sales":70}]

✅ 结论:在实际开发中,Spring Boot数据访问与数据库集成的应用场景非常广泛,需要根据实际问题选择合适的数据访问方法。

总结

本章我们学习了Spring Boot数据访问与数据库集成,包括Spring Boot数据访问的基本方法、Spring Boot与MySQL的集成、Spring Boot与H2的集成、Spring Boot与MyBatis的集成、Spring Boot与JPA的集成、Spring Boot的事务管理、Spring Boot的实际应用场景,学会了在实际开发中处理数据库访问问题。其中,Spring Boot数据访问的基本方法、Spring Boot与MySQL的集成、Spring Boot与H2的集成、Spring Boot与MyBatis的集成、Spring Boot与JPA的集成、Spring Boot的事务管理、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

Read more

快速学习GO语言总结

快速学习GO语言总结

干货分享,感谢您的阅读!备注:本博客将自己初步学习GO的总结进行分享,希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力,如有错误请留言指正,谢谢!(持续更新) 一、初步了解Go语言 (一)Go语言诞生的主要问题和目标 1. 多核硬件架构: 随着计算机硬件的发展,多核处理器成为主流,使得并行计算变得普遍。然而,传统的编程语言在处理多核并行性时可能面临困难,因为它们缺乏合适的原生支持。Go语言通过引入轻量级的协程(goroutine)和通道(channel)机制,使得并发编程变得更加容易。开发者可以轻松地创建数千个并发执行的协程,而无需担心线程管理的复杂性。 2. 超大规模分布式计算集群: 随着云计算和分布式系统的崛起,构建和维护超大规模的分布式计算集群变得越来越常见。这些集群需要能够高效处理大量的请求、数据共享和协调。Go语言的并发特性和通道机制使得编写分布式系统变得更加容易,开发者可以使用协程和通道来处理并发任务、消息传递和协调工作。 3. Web模式导致的开发规模和更新速度增加: Web应用的兴起带来了前所未有的开发规模和持续更新的需求。传统的编程语言在

Xiaomusic 让小爱音箱解锁本地曲库,内网穿透更能远程点歌

Xiaomusic 让小爱音箱解锁本地曲库,内网穿透更能远程点歌

Xiaomusic 是一款专为小爱音箱打造的本地音乐管理工具,核心功能是绑定小米账号后让小爱音箱直接读取 NAS 中的音乐文件,支持语音点播、随机播放、循环歌单等基础操作,适配所有能运行 Docker 的设备,无论是家用 NAS(极空间、群晖等)还是普通电脑都能部署。它的适用人群主要是有本地音乐收藏习惯、不想被音乐平台会员限制的用户,尤其是家中有小爱音箱且配备 NAS 的家庭用户,优点在于部署门槛低,无需编程基础,轻量化占用资源少,还能通过网页端可视化管理歌单和设备,操作简单易上手。 使用 Xiaomusic 时能明显感受到本地音乐调用的便捷性,比如喊一声 “播放收藏的经典老歌” 就能秒响应,但也有需要注意的地方:小米账号绑定后建议定期检查登录状态,避免因账号安全设置导致连接失效;NAS 中的音乐文件最好按统一格式整理,否则可能出现语音点播识别不准确的情况;另外部署时要确保存储路径设置正确,不然会出现音乐文件无法读取的问题。 不过仅在局域网内使用 Xiaomusic 会有明显的局限性,比如人在公司想给家里的老人点播戏曲,却因为不在同一网络无法操作;出门旅游时想远程调整家中小爱音箱的

Trae CN IDE 中 PHP 开发的具体流程和配置指南

以下是 Trae CN IDE 中 PHP 开发的具体流程和配置指南,结合知识库内容和实际开发需求整理,并附实例说明: 一、安装与初始配置 1. 下载与安装 Trae IDE * 访问 Trae 官网 下载 macOS 或 Windows 版本。 * 安装完成后,启动 Trae,首次运行会进入初始化向导。 2. 初始设置 * 主题与语言:选择暗色/亮色主题,语言设为简体中文。 * 导入配置:从 VS Code 或 Cursor 导入插件、快捷键(保留原有习惯)。 * 登录账号:注册 GitHub/邮箱账号,解锁 AI 功能(如

OpenClaw gateway start 报 401 Invalid API key?一个环境变量的坑

今天折腾了半小时,终于搞明白为什么 openclaw gateway start 一直报 HTTP 401: Invalid API key,而 openclaw gateway run 却能正常工作。 记录一下,免得以后又踩。 问题现象 用 openclaw gateway run 前台运行,一切正常,能正常对话。 但换成 openclaw gateway start(systemd 后台服务),就报错: HTTP 401: Invalid API key 明明配置文件里 API key 写得好好的,为什么会这样? 原因分析 run 和 start 的区别: * run — 前台运行,