1.Springboot、Springcloud、SpringCloudAlibaba
现在的Spring Cloud Alibaba由于没有纳入到Spring Cloud的主版本管理中,所以我们需要自己去引入其版本信息;
springboot:
主要特点
自动配置:根据依赖自动配置 Spring 应用。
内嵌服务器:支持内嵌 Tomcat、Jetty 等服务器,无需单独部署。
简化依赖管理:通过
starter
依赖简化 Maven/Gradle 配置。监控和管理:提供 Actuator 模块,支持应用监控和管理。
作用
Spring Boot 主要用于快速开发单体应用或微服务应用中的单个服务。
SpringCloud:
Spring Cloud 是一个基于 Spring Boot 的 微服务架构解决方案,提供了一系列工具和框架,用于构建分布式系统中的常见模式(如配置管理、服务发现、熔断器、负载均衡等)。
主要组件
服务发现:Eureka、Consul、Zookeeper。
配置中心:Spring Cloud Config。
负载均衡:Ribbon、LoadBalancer。
熔断器:Hystrix、Resilience4j。
API 网关:Zuul、Spring Cloud Gateway。
分布式追踪:Sleuth、Zipkin。
作用
Spring Cloud 主要用于解决微服务架构中的 分布式系统问题,例如服务之间的通信、配置管理、容错处理等。
SpringCloudAlibaba:
Spring Cloud Alibaba 是 Spring Cloud 的一个子项目,由阿里巴巴开源,提供了一系列基于阿里巴巴生态的微服务解决方案。它是 Spring Cloud 的扩展,集成了阿里巴巴的中间件和工具。
主要组件
服务发现与配置管理:Nacos。
熔断与限流:Sentinel。
分布式事务:Seata。
消息队列:RocketMQ。
分布式任务调度:SchedulerX。
作用
Spring Cloud Alibaba 主要用于在 Spring Cloud 的基础上,提供 阿里巴巴生态的集成支持,特别适合国内企业和开发者使用。
1. Spring Boot 是基础
Spring Boot 是 Spring Cloud 和 Spring Cloud Alibaba 的基础。
Spring Boot 提供了快速开发单个微服务的能力,而 Spring Cloud 和 Spring Cloud Alibaba 则是在此基础上解决分布式系统的问题。
2. Spring Cloud 是扩展
Spring Cloud 基于 Spring Boot,提供了一套完整的微服务解决方案。
它解决了分布式系统中的常见问题,如服务发现、配置管理、负载均衡等。
3. Spring Cloud Alibaba 是增强
Spring Cloud Alibaba 是 Spring Cloud 的扩展,集成了阿里巴巴的中间件和工具。
它在 Spring Cloud 的基础上,提供了更适合国内开发者的解决方案(如 Nacos、Sentinel、Seata 等)。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
而不是像以往使用Spring Cloud的时候,直接引入Spring Cloud的主版本(Dalston、Edgware、Finchley、Greenwich这些)就可以的。我们需要像上面的例子那样,单独的引入spring-cloud-alibaba-dependencies
来管理Spring Cloud Alibaba下的组件版本。
由于Spring Cloud基于Spring Boot构建,而Spring Cloud Alibaba又基于Spring Cloud Common的规范实现,所以当我们使用Spring Cloud Alibaba来构建微服务应用的时候,需要知道这三者之间的版本关系。
下表整理了目前Spring Cloud Alibaba的版本与Spring Boot、Spring Cloud版本的兼容关系:
Spring Boot | Spring Cloud | Spring Cloud Alibaba |
---|---|---|
2.1.x | Greenwich | 0.9.x |
2.0.x | Finchley | 0.2.x |
1.5.x | Edgware | 0.1.x |
1.5.x | Dalston | 0.1.x |
2.工程结构
my-spring-boot-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ ├── MySpringBootApplication.java # 启动类
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # 控制器层
│ │ │ ├── service/ # 服务层
│ │ │ ├── repository/ # 数据访问层
│ │ │ ├── model/ # 实体类
│ │ │ ├── dto/ # 数据传输对象
│ │ │ ├── exception/ # 自定义异常
│ │ │ └── util/ # 工具类
│ │ ├── resources/
│ │ │ ├── static/ # 静态资源(CSS、JS、图片等)
│ │ │ ├── templates/ # 模板文件(如 Thymeleaf)
│ │ │ ├── application.yml # 主配置文件
│ │ │ ├── application-dev.yml # 开发环境配置文件
│ │ │ ├── application-prod.yml # 生产环境配置文件
│ │ │ └── logback-spring.xml # 日志配置文件
│ │ └── webapp/ # Web 资源(可选)
│ └── test/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ ├── MySpringBootApplicationTests.java # 测试类
│ │ ├── controller/ # 控制器测试
│ │ ├── service/ # 服务层测试
│ │ └── repository/ # 数据访问层测试
│ └── resources/
│ └── application-test.yml # 测试环境配置文件
├── target/ # 构建输出目录
├── pom.xml # Maven 配置文件
├── Dockerfile # Docker 镜像构建文件
├── .gitignore # Git 忽略文件
└── README.md # 项目说明文档
3.配置文件
3.1自定义参数:
book.name=SpringCloudInAction
book.author=nihao
@Component
public class Book {
@Value("${book.name}")
private String name;
@Value("${book.author}")
private String author;
// 省略getter和setter
}
3.2命令行参数
java -jar xxx.jar --server.port=8888
3.3 多环境配置
开发、测试、生产环境中,其中每个环境的数据库地址、服务器端口等等配置都会不同,如果在为不同环境打包时都要频繁修改配置文件的话,那必将是个非常繁琐且容易发生错误的事。
在Spring Boot中多环境配置文件名需要满足application-{profile}.properties
的格式,其中{profile}
对应你的环境标识,比如:
application-dev.properties
:开发环境application-test.properties
:测试环境application-prod.properties
:生产环境
至于哪个具体的配置文件会被加载,需要在application.properties
文件中通过spring.profiles.active
属性来设置,其值对应配置文件中的{profile}
值。如:spring.profiles.active=test
就会加载application-test.properties
配置文件内容。
List类型
在properties文件中使用[]
来定位列表类型,比如:
spring.my-example.url[0]=http://example.com
spring.my-example.url[1]=http://spring.io
也支持使用逗号分割的配置方式,上面与下面的配置是等价的:
spring.my-example.url=http://example.com,http://spring.io
而在yaml文件中使用可以使用如下配置:
spring:
my-example:
url:
- http://example.com
- http://spring.io
也支持逗号分割的方式:
spring:
my-example:
url: http://example.com, http://spring.io
Map类型
Map类型在properties和yaml中的标准配置方式如下:
- properties格式:
spring.my-example.foo=bar
spring.my-example.hello=world
- yaml格式:
spring:
my-example:
foo: bar
hello: world
注意:如果Map类型的key包含非字母数字和-
的字符,需要用[]
括起来,比如:
spring:
my-example:
'[foo.baz]': bar
指定环境启动
java -jar myapp.jar -Dspring.profiles.active=dev
4. API
Swagger2
<!-- SpringDoc OpenAPI -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>
# 启用 Swagger UI
springdoc.swagger-ui.enabled=true
# 配置 API 文档信息
springdoc.info.title=AI大模型调用接口文档
springdoc.info.description=AI大模型调用的相关接口文档
springdoc.info.version=1.0
各参数配置含义如下:
swagger.title
:标题swagger.description
:描述swagger.version
:版本
@RestController
@RequestMapping("/api/ai")
@Tag(name = "AI大模型调用接口", description = "AI大模型调用的相关接口文档")
@Operation(summary = "获取文章摘要", description = "根据输入的文本生成文章摘要")
@PostMapping("/abstract")
public Result getAbstract(
@Parameter(description = "输入的文本", required = true) @RequestBody String text) {
try {
CompletableFuture<String> future = aiProofAbstractService.proofabstractBigStr(text);
String abstractResult = future.join();
return new Result(AppConstants.SUCCESS_CODE, abstractResult);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
JSR-303
JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
第一步:在要校验的字段上添加上@NotNull
注解,具体如下:
@Data
@ApiModel(description="用户实体")
public class User {
@ApiModelProperty("用户编号")
private Long id;
@NotNull
@ApiModelProperty("用户姓名")
private String name;
@NotNull
@ApiModelProperty("用户年龄")
private Integer age;
}
第二步:在需要校验的参数实体前添加@Valid
注解,具体如下:
@PostMapping("/")
@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
public String postUser(@Valid @RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
尝试一些其他校验
在完成了上面的例子之后,我们还可以增加一些校验规则,比如:校验字符串的长度、校验数字的大小、校验字符串格式是否为邮箱等。下面我们就来定义一些复杂的校验定义,比如:
@Data
@ApiModel(description="用户实体")
public class User {
@ApiModelProperty("用户编号")
private Long id;
@NotNull
@Size(min = 2, max = 5)
@ApiModelProperty("用户姓名")
private String name;
@NotNull
@Max(100)
@Min(10)
@ApiModelProperty("用户年龄")
private Integer age;
@NotNull
@Email
@ApiModelProperty("用户邮箱")
private String email;
}
JSON Schema
JSON Schema 是一种用于定义 JSON 数据格式、内容和语义的规范,可用于校验 JSON 数据是否符合特定的结构和约束要求。以下是关于 JSON Schema 校验的一些基本信息:
<dependency>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-schema-validator</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"username": {
"type": "string",
"minLength": 3,
"maxLength": 20
},
"email": {
"type": "string",
"format": "email"
},
"password": {
"type": "string",
"minLength": 8
}
},
"required": ["username", "email", "password"],
"additionalProperties": false
}
import org.everit.json.schema.Schema;
import org.everit.json.schema.ValidationException;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.json.JSONTokener;
public class JsonSchemaValidator {
// 加载 JSON Schema
private static Schema loadSchema(String schemaPath) {
JSONObject rawSchema = new JSONObject(new JSONTokener(JsonSchemaValidator.class.getResourceAsStream(schemaPath)));
return SchemaLoader.load(rawSchema);
}
// 验证 JSON 数据
public static void validateJson(Schema schema, String jsonData) {
try {
JSONObject jsonObject = new JSONObject(jsonData);
schema.validate(jsonObject);
System.out.println("JSON 数据验证通过!");
} catch (ValidationException e) {
System.err.println("JSON 数据验证失败:" + e.getMessage());
e.getCausingExceptions().stream()
.map(ValidationException::getMessage)
.forEach(System.err::println);
}
}
public static void main(String[] args) {
// 加载 Schema
Schema schema = loadSchema("/schema/user-registration-schema.json");
// 测试 JSON 数据
String validJson = "{ \"username\": \"john_doe\", \"email\": \"[email protected]\", \"password\": \"password123\" }";
String invalidJson = "{ \"username\": \"jd\", \"email\": \"invalid-email\", \"password\": \"123\" }";
// 验证 JSON 数据
validateJson(schema, validJson); // 验证通过
validateJson(schema, invalidJson); // 验证失败
}
}
5.数据访问
数据源配置
在我们访问数据库的时候,需要先配置一个数据源,下面分别介绍一下几种不同的数据库配置方式。
首先,为了连接数据库需要引入jdbc支持,在pom.xml
中引入如下配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
#嵌入式数据库支持
嵌入式数据库通常用于开发和测试环境,不推荐用于生产环境。Spring Boot提供自动配置的嵌入式数据库有H2、HSQL、Derby,你不需要提供任何连接配置就能使用。
比如,我们可以在pom.xml
中引入如下配置使用HSQL
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
#连接生产数据源
以MySQL数据库为例,先引入MySQL连接的依赖包,在pom.xml
中加入:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
在src/main/resources/application.properties
中配置数据源信息
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
注意:因为Spring Boot 2.1.x默认使用了MySQL 8.0的驱动,所以这里采用com.mysql.cj.jdbc.Driver
,而不是老的com.mysql.jdbc.Driver
。
#JPA
#依赖
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- Lombok (可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
properity配置文件
# 数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword
# JPA 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
#定义实体
package com.example.demo.entity;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false)
private String password;
}
#数据操作层
package com.example.demo.repository;
import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
// 自定义查询方法
User findByEmail(String email);
}
#controller和service层
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
// 创建用户
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
// 获取所有用户
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
// 根据邮箱获取用户
@GetMapping("/{email}")
public User getUserByEmail(@PathVariable String email) {
return userService.getUserByEmail(email);
}
}
===============================================================
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 保存用户
public User saveUser(User user) {
return userRepository.save(user);
}
// 查询所有用户
public List<User> getAllUsers() {
return userRepository.findAll();
}
// 根据邮箱查询用户
public User getUserByEmail(String email) {
return userRepository.findByEmail(email);
}
}
多数据源的配置
jdbc多数据源
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
- 多数据源配置的时候,与单数据源不同点在于
spring.datasource
之后多设置一个数据源名称primary
和secondary
来区分不同的数据源配置,这个前缀将在后续初始化数据源的时候用到。
完成多数据源的配置信息之后,就来创建个配置类来加载这些配置信息,初始化数据源,以及初始化每个数据源要用的JdbcTemplate。你只需要在你的Spring Boot应用下添加下面的这个配置类即可完成!
@Configuration
public class DataSourceConfiguration {
@Primary
@Bean
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
return new JdbcTemplate(primaryDataSource);
}
@Bean
public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
return new JdbcTemplate(secondaryDataSource);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter37ApplicationTests {
@Autowired
protected JdbcTemplate primaryJdbcTemplate;
@Autowired
protected JdbcTemplate secondaryJdbcTemplate;
@Before
public void setUp() {
primaryJdbcTemplate.update("DELETE FROM USER ");
secondaryJdbcTemplate.update("DELETE FROM USER ");
}
@Test
public void test() throws Exception {
// 往第一个数据源中插入 2 条数据
primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "aaa", 20);
primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "bbb", 30);
// 往第二个数据源中插入 1 条数据,若插入的是第一个数据源,则会主键冲突报错
secondaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "ccc", 20);
// 查一下第一个数据源中是否有 2 条数据,验证插入是否成功
Assert.assertEquals("2", primaryJdbcTemplate.queryForObject("select count(1) from user", String.class));
// 查一下第一个数据源中是否有 1 条数据,验证插入是否成功
Assert.assertEquals("1", secondaryJdbcTemplate.queryForObject("select count(1) from user", String.class));
}
}
Spring Data JPA的多数据源配置
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
# 日志打印执行的SQL
spring.jpa.show-sql=true
# Hibernate的DDL策略
spring.jpa.hibernate.ddl-auto=create-drop
@Configuration
public class DataSourceConfiguration {
@Primary
@Bean
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
通过@ConfigurationProperties
可以知道这两个数据源分别加载了spring.datasource.primary.*
和spring.datasource.secondary.*
的配置。@Primary
注解指定了主数据源,就是当我们不特别指定哪个数据源的时候,就会使用这个Bean真正差异部分在下面的JPA配置上。
分别创建两个数据源的JPA配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryPrimary",
transactionManagerRef="transactionManagerPrimary",
basePackages= { "com.didispace.chapter38.p" }) //设置Repository所在位置
public class PrimaryConfig {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
private Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
@Primary
@Bean(name = "entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "entityManagerFactoryPrimary")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource)
.packages("com.didispace.chapter38.p") //设置实体类所在位置
.persistenceUnit("primaryPersistenceUnit")
.properties(getVendorProperties())
.build();
}
@Primary
@Bean(name = "transactionManagerPrimary")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
==================================================================================================================================================================================
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactorySecondary",
transactionManagerRef="transactionManagerSecondary",
basePackages= { "com.didispace.chapter38.s" }) //设置Repository所在位置
public class SecondaryConfig {
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
private Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondaryDataSource)
.packages("com.didispace.chapter38.s") //设置实体类所在位置
.persistenceUnit("secondaryPersistenceUnit")
.properties(getVendorProperties())
.build();
}
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
MyBatis的多数据源配置
spring:
# datasource 数据源配置内容
datasource:
# 订单数据源配置
orders:
url: jdbc:mysql://127.0.0.1:3306/test_orders?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password:
type: com.alibaba.druid.pool.DruidDataSource # 设置类型为 DruidDataSource
# Druid 自定义配置,对应 DruidDataSource 中的 setting 方法的属性
min-idle: 0 # 池中维护的最小空闲连接数,默认为 0 个。
max-active: 20 # 池中最大连接数,包括闲置和使用中的连接,默认为 8 个。
# 用户数据源配置
users:
url: jdbc:mysql://127.0.0.1:3306/test_users?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password:
type: com.alibaba.druid.pool.DruidDataSource # 设置类型为 DruidDataSource
# Druid 自定义配置,对应 DruidDataSource 中的 setting 方法的属性
min-idle: 0 # 池中维护的最小空闲连接数,默认为 0 个。
max-active: 20 # 池中最大连接数,包括闲置和使用中的连接,默认为 8 个。
# Druid 自定已配置
druid:
# 过滤器配置
filter:
stat: # 配置 StatFilter ,对应文档 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatFilter
log-slow-sql: true # 开启慢查询记录
slow-sql-millis: 5000 # 慢 SQL 的标准,单位:毫秒
# StatViewServlet 配置
stat-view-servlet: # 配置 StatViewServlet ,对应文档 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatViewServlet%E9%85%8D%E7%BD%AE
enabled: true # 是否开启 StatViewServlet
login-username: admin # 账号
login-password: 123456 # 密码
// DataSourceConfig.java
@Configuration
public class DataSourceConfig {
/**
* 创建 orders 数据源
*/
@Primary
@Bean(name = "ordersDataSource")
@ConfigurationProperties(prefix = "spring.datasource.orders") // 读取 spring.datasource.orders 配置到 HikariDataSource 对象
public DataSource ordersDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 创建 users 数据源
*/
@Bean(name = "usersDataSource")
@ConfigurationProperties(prefix = "spring.datasource.users")
public DataSource usersDataSource() {
return DruidDataSourceBuilder.create().build();
}
}
6 缓存
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
// 创建一个基于 ConcurrentMap 的缓存管理器
return new ConcurrentMapCacheManager(
Arrays.asList("myCache") // 定义缓存名称
);
}
}
- 使用缓存:在需要缓存的方法上添加
@Cacheable
注解。
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class YourService {
@Cacheable(value = "myCache", key = "#id") // 使用名为 myCache 的缓存,key 为方法参数 id
public String getSomeData(int id) {
// 模拟从数据库或其他数据源获取数据
System.out.println("Fetching data from source for id: " + id);
return "Data for id " + id;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class YourController {
@Autowired
private YourService yourService;
@GetMapping("/data/{id}")
public String getData(@PathVariable int id) {
return yourService.getSomeData(id);
}
}
redis注解
<?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>org.example</groupId>
<artifactId>redisCache</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.3</version>
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.1.3</version>
</dependency>
<!-- Spring Boot 缓存启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>3.1.3</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</project>
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
@Data
@TableName("user")
public class User implements Serializable {
@TableId
private Long id;
private String name;
private Integer age;
}
@Service
@CacheConfig(cacheNames = "users") // 指定缓存名称为 users
public class UserService {
@Autowired
private UserMapper userMapper;
@Cacheable(key = "#id") // 使用方法参数 id 作为缓存的 key
public User getUserById(Long id) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", id);
return userMapper.selectOne(queryWrapper);
}
}
@SpringBootApplication
@EnableCaching // 启用缓存功能
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
# MySQL 配置
spring.datasource.url=jdbc:mysql://localhost:3306/user?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Redis 配置
spring.data.redis.host=localhost
spring.data.redis.port=6379
# 缓存类型使用 Redis
spring.cache.type=redis
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.org.springframework.cache=DEBUG
第一次会有日志出现,之后都从缓存中取,没有日志出现