Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

部分 IV. Spring Boot

目录

26. Spring Boot Quick start
26.1. 创建项目
26.2. pom.xml
26.3. Controller
26.4. Springboot with Maven
26.4.1. resource
26.4.2. Maven run
26.4.3. Spring Boot maven 插件 build-image
26.4.4. 生成项目信息
27. Spring 开发环境
27.1. Java 开发环境
27.2. 安装 Spring Tool Suite
27.3. Dashboard
27.4. Spring Initializr - Bootstrap your application
28. SpringApplication
28.1. 运行 Spring boot 项目
28.1.1. Linux systemd
28.1.2. 传统 init.d 脚本
28.1.3. 编译用于Tomcat的 War
28.2. @SpringBootApplication
28.2.1. 排除 @EnableAutoConfiguration 加载项
28.3. 获取 Resources 目录中的静态文件
28.4. @EnableAutoConfiguration
28.5. @ComponentScan
28.6. @EntityScan 实体扫描
28.7. @EnableJpaRepositories
28.8. 启动和销毁
28.9. 打印环境变量
28.10. CharacterEncodingFilter
28.11. 隐藏 Banner
28.12. 实体与仓库扫描
28.13. 列出 Beans
28.14. Tomcat 端口
28.15. 配置项设定
28.16. spring.profiles.active
28.17. @Profile("dev") / @ActiveProfiles("dev")
28.18. 设置默认时区
29. 如何优雅停止 Springboot 运行
29.1. 准备工作
29.2. kill 命令演示
29.3. 容器中如何优雅关闭 Springboot
29.4. 写入PID文件
30. Properties 配置文件
30.1. application.properties 配置文件
30.1.1. application.properties 参考
30.1.2. 启动指定参数
30.1.3. 加载排除
30.1.4. PID FILE
30.1.5. banner 关闭
30.1.6. server
30.1.7. logging
30.1.8. 内嵌 tomcat server
30.1.9. servlet
30.1.10. JSON 输出与日期格式化
30.1.11. SMTP 相关配置
30.1.12. Redis
30.1.13. MongoDB
30.1.14. MySQL
30.1.15. Oracle
30.1.16. default_schema
30.1.17. datasource
30.1.18. velocity
30.1.19. Security 相关配置
30.1.20. MVC 配置
30.1.21. Kafka 相关配置
30.2. Properties 文件
30.2.1. @Value 注解
30.2.2. @EnableConfigurationProperties 引用自定义 *.properties 配置文件
30.2.3. @PropertySource 注解载入 properties 文件
30.3. Environment 读取配置文件
30.4. 手工载入 *.properties 文件
30.4.1. 家在 resources 目录中的指定文件
30.4.2. 从 InputStreamReader 打开 application.properties
30.5. 命令行注入配置项
30.5.1. spring.profiles.active 参数切换配置文件
30.5.2. SpringApplicationBuilder.properties() 方法添加配置项
30.5.3. 禁用命令行注入环境变量
30.6. PropertyResolver 获取配置
30.7. 参数引用
30.8. 默认值
30.9. 产生随机数
30.9.1. 随机数
30.10. 多行字符串
30.11. 注入多值属性 arrays, list, set
30.12. List 列表类型
30.13. Map类型
30.14. Binder
30.15. 加密 application.properties 中的敏感内容
31. Spring boot with Logging
31.1. 配置日志文件
31.1.1. 日志输出级别
31.1.2. Spring boot 2.1 以后的版本不打印 Mapped 日志问题
31.1.3. 禁止控制台输出日志
31.1.4. 定制日志格式
31.1.5. 彩色输出
31.2. 日志切割
31.3. 彩色日志
31.4. 打印日志
31.4.1. lombok
31.5. logback 配置详解
31.5.1. 标准输出
31.5.2. 禁止 logback 日志输出
31.5.3. 指定Class过滤日志
31.5.4. configuration 属性配置
31.5.5. contextName 设置上下文名称
31.5.6. property 设置变量
31.5.7. encoder 日志格式设置
31.5.8. RollingFileAppender
31.5.9. 日志过滤
31.5.10. 标准输出
31.5.11. MDC
31.5.12. 日志写入 MongoDB
31.5.13. 日志发送给 logstash
31.5.14. fluentd
31.5.15. Loki4j Logback
31.6. Log4j2 + Gelf + Logstash
31.6.1. Maven 配置
31.6.2. log4j2.xml 配置
31.6.3. Java 测试代码
31.6.4. Logstash 配置
31.6.5. 测试结果
31.6.6. Log4j2 更多技巧
31.7. 日志报警
31.7.1. Logstash 配置
31.7.2. 监控 SpringBootApplication 的启动和退出
31.8. Spring boot with ELK(Elasticsearch + Logstash + Kibana)
31.8.1. TCP 方案
31.8.2. Redis 方案
31.8.3. Kafka 方案
31.8.4. Other
32. Springboot with Undertow / Jetty / http2
32.1. Spring boot with Undertow
32.1.1. Maven 依赖
32.1.2. Application
32.1.3. 相关配置
32.2. Spring boot with Jetty
32.3. Spring boot with HTTP2 SSL
32.3.1. 生成自签名证书
32.3.2. application.properties 配置文件
32.3.3. 启动 Spring boot
32.3.4. restTemplate 调用实例
32.3.5. HTTP2
33. Spring boot with MongoDB
33.1. Maven
33.2. Application
33.3. MongoTemplate
33.4. Repository
34. Spring boot with MySQL
34.1. Maven
34.2. Resource
34.3. Application
34.4. JdbcTemplate
34.5. CrudRepository
35. Spring boot with Oracle
35.1. Maven
35.2. application.properties
35.3. Application
35.4. CrudRepository
35.5. JdbcTemplate
35.6. Controller
36. Spring boot with PostgreSQL
36.1. pom.xml
36.2. application.properties
36.3. Application
36.4. CrudRepository
36.5. JdbcTemplate
36.6. Controller
36.7. Test
37. Spring boot with Elasticsearch
37.1. Maven
37.2. Application
37.3. application.properties
37.4. Domain
37.5. ElasticsearchRepository
38. Spring boot with Elasticsearch TransportClient
38.1. Maven
38.2. Application
38.3. application.properties
38.4. ElasticsearchConfiguration
38.5. RestController
39. Spring boot with Apache Hive
39.1. Maven
39.2. application.properties
39.3. Configuration
39.4. CURD 操作实例
40. Spring boot with Phoenix
40.1. Maven
40.2. application.properties
40.3. Configuration
41. Spring boot with Datasource
41.1. Master / Slave 主从数据库数据源配置
41.1.1. application.properties
41.1.2. 配置主从数据源
41.1.3. 选择数据源
41.2. 多数据源配置
41.3. JPA 多数据源
42. 连接池配置
42.1. org.apache.tomcat.jdbc.pool.DataSource
42.2. druid
42.2.1. 加密数据库密码
42.3. c3p0 - JDBC3 Connection and Statement Pooling
42.4. dbcp2
42.5. bonecp
42.6. HikariPool
43. Spring boot with Queue
43.1. Spring boot with RabbitMQ(AMQP)
43.1.1. maven
43.1.2. RabbitMQConfig
43.1.3. 生产者
43.1.4. 消费者
43.2. Spring boot with Apache Kafka
43.2.1. 安装 kafka
43.2.2. maven
43.2.3. Spring boot Application
43.2.4. EnableKafka
43.2.5. KafkaListener
43.2.6. 测试
43.2.7. 完整的发布订阅实例
43.2.8. Spring cloud with Kafka
44. Spring boot with Scheduling
44.1. 启用计划任务
44.1.1. Application.java
44.1.2. 配置
44.1.3. Component
44.2. 计划任务控制开关
44.3. @Scheduled 详解
44.3.1. fixedRate 案例
44.3.2. timeUnit
44.4. cron 表达式
44.4.1. 每3秒钟一运行一次
44.4.2. 凌晨23点运行
44.4.3. 周一 ~ 周五
44.5. Timer 例子
44.6. ScheduledExecutorService 例子
45. Spring boot with Swagger
45.1. Spring boot with Springdoc
45.1.1. WebMvc
45.1.2. Webflux
45.1.3. Swagger UI
45.1.4. 从 SpringFox 迁移到 Swagger3 注解变化
45.2. Spring boot with knife4j
45.2.1. maven
45.2.2. Knife4jConfiguration
45.2.3. application.properties
45.3. springfox
45.3.1. Swagger3
45.3.2. Swagger2
45.3.3. @Api() 资源定义
45.3.4. @ApiIgnore 忽律接口
45.3.5. @ApiOperation()
45.3.6. @ApiResponses
45.3.7. @ApiModel 实体类
46. Spring boot with lombok
46.1. @Builder
46.2. @Slf4j 注解
47. Spring boot with Container
47.1. Spring boot with Docker
47.1.1. 通过 Docker 命令构建镜像
47.1.2. 通过 Maven 构建 Docker 镜像
47.1.3. [ERROR] No plugin found for prefix 'dockerfile' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/Users/neo/.m2/repository), central (https://repo.maven.apache.org/maven2)] -> [Help 1]
47.1.4. curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to localhost:8888
47.2. Spring boot with Docker stack
47.2.1. 编译 Docker 镜像
47.2.2.
47.3. Spring boot with Kubernetes
47.3.1. Kubernetes 编排脚本
47.3.2. 部署镜像
48. Spring boot with command line
48.1. Maven
48.2. CommandLineRunner 例子
48.3. ApplicationRunner 例子
49. Spring Boot Actuator
49.1. Maven 依赖
49.2. 与 Spring Boot Actuator 有关的配置
49.2.1. 禁用HTTP端点
49.2.2. 安全配置
49.2.3. 修改 actuator 地址
49.2.4. 关机
49.3. actuator 接口
49.4. 健康状态
49.4.1. 健康状态
49.4.2. 自定义健康检查
49.5. info 配置信息
49.5.1. application.properties 配置静态信息
49.5.2. 动态信息
49.6. beans 信息
49.7. caches
49.8. conditions
49.9. configprops 配置文件
49.10. env 环境变量
49.11. logfile 日志
49.12. threaddump 线程信息
49.13. 计划任务
49.14. metrics
49.15. 控制器映射 URL
49.16. 自定义监控指标
50. SpringBootTest
50.1. Maven 依赖
50.2. 测试类
50.2.1. Junit基本注解介绍
50.3.
50.3.1. Assert.assertEquals 判断相等
50.3.2. Assert.assertTrue
50.4. JPA 测试
50.5. TestRestTemplate
50.6. Controller单元测试
50.7. WebTestClient
51. Spring boot with Aop
51.1. Aspect
51.1.1. Maven
51.1.2. Pojo 类
51.1.3. Service 类
51.1.4. Aspect 类
51.1.5. 控制器
51.1.6. Application
51.1.7. 测试
52. Spring boot with starter
52.1. 实现 starter
52.1.1. Maven pom.xml 依赖包
52.1.2. 配置文件处理
52.1.3. 自动配置文件
52.1.4. 启用 starter 的自定义注解
52.2. 引用 starter
52.2.1. Maven pom.xml 引入依赖
52.2.2. 通过注解配置 starter
52.2.3. 测试运行结果
53. Spring boot with Monitor
53.1. Spring boot with Grafana
53.1.1. Springboot 集成 InfluxDB
53.1.2. InfluxDB
53.2. Spring Boot with Prometheus
53.2.1. Maven 依赖
53.2.2. application.properties 配置文件
53.2.3. 启动类
53.2.4. 测试
53.2.5. 控制器监控
53.2.6. 自定义埋点监控
55. Spring boot with Git version
55.1. CommonRestController 公共控制器
55.2. VersionRestController 测试控制器
55.3. 创建 .gitattributes 文件
56. Spring boot with Session share
56.1. Redis
56.1.1. Maven
56.1.2. application.properties
56.1.3. Application
56.2. 测试 Session
56.3. JDBC
56.4. Springboot 2.1
57. Spring boot with Caching
57.1. maven
57.1.1. Redis
57.2. 启用缓存 @EnableCaching
57.3. 设置缓存 @Cacheable
57.3.1. 多参数处理
57.3.2. 对象参数
57.3.3.
57.3.4. 参数索引
57.3.5. 自动生成 key
57.3.6. SpEL表达式
57.3.7. 排除 null 结果
57.3.8. 排除 empty
57.4. 更新缓存 @CachePut
57.5. 删除缓存 @CacheEvict
57.6. 组合操作 @Caching
57.7. 解决Expire 和 TTL 过期时间
57.8. Cannot serialize
58. Spring boot with Email
58.1. Maven
58.2. Resource
58.3. POJO
58.4. RestController
58.5. Test
59. Spring boot with Hessian
59.1. Maven
59.2. Application
59.3. HessianServiceExporter
59.4. Service
59.5. RestController
60. Spring boot with Async
60.1. Callable 实现异步
60.2. WebAsyncTask 实现异步
60.3. DeferredResult 实现异步返回结果
60.4. 带有返回值的异步任务
60.4.1. Future
60.4.2. CompletableFuture
60.5. 默认简单线程池 SimpleAsyncTaskExecutor
60.5.1. 配置线程池
60.5.2. @Service/@Component 中异步执行
60.5.3. applicationTaskExecutor
60.6. ThreadPoolTaskExecutor 自定义线程池
60.6.1. 最简单的配置
60.6.2. 队列
60.6.3. 定义多个线程池
60.6.4. 实现 AsyncConfigurer 接口方式创建自定义连接池
60.6.5. 继承 AsyncConfigurerSupport 创建自定义连接池
60.6.6. 生产环境完整代码 @Bean 注入方式
60.6.7. 通过 @Bean 覆盖掉 SimpleAsyncTaskExecutor
60.7. 自定义线程池 ThreadPoolExecutor
60.7.1. ThreadPoolExecutor
60.7.2. 注入自定义线程池bean
60.8. 设置线程名称
60.9. 线程池监控
60.10. 注意事项
61. Springboot with Ethereum (web3j)
61.1. Maven
61.2. application.properties
61.3. TestRestController
61.4. 测试
62. Java Record 新特性
62.1. Record 替代 POJO 类
62.2. Record 作为 Properties
62.3. Record 作为实体类
62.4. Record 作为 Service
62.5. Record 作为 Controller
63. Spring boot with Retryable
63.1. @EnableResilientMethods
63.1.1. @ConcurrencyLimit 限流
63.1.2. @Retryable 重试
63.2. spring-retry
63.2.1. spring-retry 依赖
63.2.2. @EnableRetry 启用重试
63.2.3.
63.2.4. 高级用法
64. Spring Boot 4 + OpenTelemetry
64.1. 依赖配置
64.2. 定义 Span
64.3. 日志追踪

1. Spring boot with Redis

1.1. Spring boot with Redis

1.1.1. maven

				
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>			
				
			

1.1.2. application.properties

				
spring.redis.database=10
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=0
				
			

1.1.3. JUnit

				
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTests {
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	@Test
	public void test() throws Exception {
		// 保存字符串
		stringRedisTemplate.opsForValue().set("neo", "chen");
		Assert.assertEquals("chen", stringRedisTemplate.opsForValue().get("neo"));
    }
}				
				
			

1.1.4. Controller

stringRedisTemplate模板用于存储key,value为字符串的数据

				
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@RequestMapping("/test")
	@ResponseBody
	public String test() {
		String message = "";
		stringRedisTemplate.opsForValue().set("hello", "world");
		message = stringRedisTemplate.opsForValue().get("hello");
		return message;
	}
				
			

等同于

				
	@Autowired
	private RedisTemplate<String, String> redisTemplate;
				
			

例 8. RedisTemplate

					
	@Autowired
	private RedisTemplate<String, String> redisTemplate;
	
	public List<Protocol> getProtocol() {
		List<Protocol> protocols = new ArrayList<Protocol>();
		Gson gson = new Gson();
		Type type = new TypeToken<List<Protocol>>(){}.getType();
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(new StringRedisSerializer());
		
		String cacheKey = String.format("%s:%s", this.getClass().getName(), Thread.currentThread().getStackTrace()[1].getMethodName());
		long expireTime = 5;
		
		if(redisTemplate.hasKey(cacheKey)){
			String cacheValue = redisTemplate.opsForValue().get(cacheKey);
			System.out.println(cacheValue);
			protocols = gson.fromJson(cacheValue, type);
		}else{
			Protocol protocol = new Protocol();
			protocol.setRequest(new Date().toString());
			protocols.add(protocol);
			
			String jsonString = gson.toJson(protocols, type);
	        System.out.println( jsonString );
			
			redisTemplate.opsForValue().set(cacheKey, jsonString);
			redisTemplate.expire(cacheKey, expireTime, TimeUnit.SECONDS);
		}
		return protocols;
	}
					
				

1.2. Redis Pub/Sub

1.2.1. Redis配置类

				
package cn.netkiller.wallet.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

import cn.netkiller.wallet.redis.RedisMessageSubscriber;

@Configuration
public class RedisConfig {

	public RedisConfig() {
	}

	@Bean
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
		StringRedisTemplate redisTemplate = new StringRedisTemplate();
		redisTemplate.setConnectionFactory(connectionFactory);
		return redisTemplate;
	}

	@Bean
	public MessageListenerAdapter messageListener() {
		return new MessageListenerAdapter(new RedisMessageSubscriber());
	}

	@Bean
	public ChannelTopic topic() {
		return new ChannelTopic("demo");
	}

	@Bean
	public RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory, MessageListenerAdapter messageListener) {
		RedisMessageListenerContainer container = new RedisMessageListenerContainer();

		container.setConnectionFactory(connectionFactory);
		container.addMessageListener(messageListener(), topic());
		container.addMessageListener(messageListener(), new ChannelTopic("test"));
		return container;
	}

}

				
			

1.2.2. 订阅类

				
package cn.netkiller.wallet.redis;

import java.nio.charset.StandardCharsets;

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;

public class RedisMessageSubscriber implements MessageListener {
	public void onMessage(final Message message, final byte[] pattern) {
		System.out.println("Topic : " + new String(message.getChannel(), StandardCharsets.UTF_8));
		System.out.println("Message : " + message.toString());
	}
}

				
			

1.2.3. 发布类

				
package cn.netkiller.wallet.redis;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;

public class RedisMessagePublisher {

	private final StringRedisTemplate redisTemplate;

	private final ChannelTopic topic;

	public RedisMessagePublisher(StringRedisTemplate redisTemplate, ChannelTopic topic) {
		this.redisTemplate = redisTemplate;
		this.topic = topic;
	}

	public void publish(String message) {
		redisTemplate.convertAndSend(topic.getTopic(), message);
	}
}
								
				
			

1.2.4. 消息发布演示

				
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@GetMapping("/pub/demo")
	public String pub() {

		RedisMessagePublisher publisher = new RedisMessagePublisher(stringRedisTemplate, new ChannelTopic("demo"));
		String message = "Message " + UUID.randomUUID();
		publisher.publish(message);
		return message;
	}

	@GetMapping("/pub/test")
	public String pub(@RequestParam String message) {

		RedisMessagePublisher publisher = new RedisMessagePublisher(stringRedisTemplate, new ChannelTopic("test"));
		publisher.publish(message);
		return message;
	}				
				
			

1.3. Sprint boot with Redisson

1.3.1. Springboot 3.x

		

		
			

1.3.2. Springboot 2.1

注意:排除 redisson-spring-data-23,引用 redisson-spring-data-21

		
 		<dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.14.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.redisson</groupId>
                    <artifactId>redisson-spring-data-23</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-data-21</artifactId>
            <version>3.14.0</version>
        </dependency>