1.6 资源管理最佳实践
1.6.1 多环境资源配置策略(企业级方案)
Profile机制深度解析:
多维度配置方案:
# application.yml(公共配置)
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
---
# 开发环境配置
spring:
profiles: dev
datasource:
url: jdbc:mysql://dev-db:3306/app?useSSL=false
username: dev_user
password: dev123
hikari:
maximum-pool-size: 5
---
# 生产环境配置
spring:
profiles: prod
datasource:
url: jdbc:mysql://prod-cluster:3306/app?useSSL=true
username: ${DB_PROD_USER}
password: ${DB_PROD_PASS}
hikari:
maximum-pool-size: 20
connection-timeout: 3000
Profile激活策略:
// 1. 启动参数指定
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setAdditionalProfiles("prod", "azure");
app.run(args);
}
}
// 2. 条件化Bean配置
@Configuration
@Profile("cloud")
public class CloudConfig {
@Bean
public CloudService cloudService() {
return new AzureCloudService();
}
}
// 3. 测试环境专用配置
@TestConfiguration
@Profile("test")
public class MockConfig {
@Bean
@Primary
public PaymentService mockPaymentService() {
return new MockPaymentService();
}
}
1.6.2 加密配置安全处理方案(金融级安全)
Jasypt集成全流程:
<!-- Maven依赖 -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
// 加密工具类
public class ConfigEncryptor {
public static void main(String[] args) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(System.getenv("CONFIG_SECRET"));
String plainText = "sensitive_data";
String encrypted = encryptor.encrypt(plainText);
System.out.println("ENC(" + encrypted + ")");
}
}
安全配置实践:
# application-secure.properties
spring.datasource.password=ENC(4Bv7dsf8sKjeiT9sLkja8W2xzlpT4r4T)
# 启动参数设置密钥
java -jar app.jar --jasypt.encryptor.password=${CONFIG_SECRET_KEY}
Kubernetes密钥管理方案:
# Kubernetes部署文件
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
db-password: NkJ2N2RzZjhzS2plaVQ5c0xramE4VzJ4emxwVDRyNFQK
api-key: VGhpcyBpcyBhIHNlY3JldCBrZXkK
// 动态获取K8s密钥
@Value("${secrets.db-password}")
private String decodedDbPassword;
1.6.3 国际化消息资源高级用法(多语言电商系统)
消息资源配置架构:
resources/
├─ messages/
│ ├─ messages.properties(默认)
│ ├─ messages_en_US.properties
│ ├─ messages_zh_CN.properties
│ └─ messages_ja_JP.properties
└─ application.yml
动态消息加载实现:
@Configuration
public class I18nConfig {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource =
new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages/messages");
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheMillis(5000); // 5秒刷新
return messageSource;
}
@Bean
public LocalResolver localeResolver() {
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
return resolver;
}
}
// 业务层使用示例
@Service
public class ProductService {
private final MessageSource messageSource;
public String getLocalizedMessage(String code, Locale locale, Object... args) {
return messageSource.getMessage(code, args, locale);
}
public void showError(HttpServletRequest request) {
Locale locale = LocaleContextHolder.getLocale();
String message = messageSource.getMessage("error.insufficient_stock",
new Object[]{product.getName()}, locale);
throw new BusinessException(message);
}
}
Thymeleaf多语言集成:
<!-- 前端页面示例 -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{page.title}"></title>
</head>
<body>
<h1 th:text="#{welcome.message(${user.name})}"></h1>
<!-- 语言切换 -->
<div>
<a th:href="@{/?lang=en}">English</a>
<a th:href="@{/?lang=zh_CN}">中文</a>
<a th:href="@{/?lang=ja_JP}">日本語</a>
</div>
</body>
</html>
动态消息更新方案:
// 消息热更新端点
@RestController
@RequiredArgsConstructor
public class MessageReloadController {
private final ReloadableResourceBundleMessageSource messageSource;
@PostMapping("/admin/i18n/reload")
public ResponseEntity<String> reloadMessages() {
messageSource.clearCache();
return ResponseEntity.ok("Messages reloaded at " + new Date());
}
@PostMapping("/admin/i18n/update")
public ResponseEntity<String> updateMessage(
@RequestParam String code,
@RequestParam String value,
@RequestParam String lang) throws IOException {
String fileName = "messages_" + lang + ".properties";
Path filePath = Paths.get("src/main/resources/messages/" + fileName);
Properties props = new Properties();
try (InputStream in = Files.newInputStream(filePath)) {
props.load(in);
}
props.setProperty(code, value);
try (OutputStream out = Files.newOutputStream(filePath)) {
props.store(out, "Updated at " + new Date());
}
return ResponseEntity.ok("Message updated");
}
}
1.6.4 资源监控与防护(生产环境必备)
连接池监控配置:
@Configuration
public class DataSourceConfig {
@Bean
public HikariDataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/app");
config.setUsername("root");
config.setPassword("securepass");
config.setMaximumPoolSize(20);
config.setMetricRegistry(Metrics.globalRegistry);
return new HikariDataSource(config);
}
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config()
.commonTags("application", "order-service");
}
}
资源防护策略:
@Configuration
public class ResourceProtectionConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 静态资源防护
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new EncodedResourceResolver())
.addTransformer(new CssLinkResourceTransformer());
// 敏感文件屏蔽
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/public/")
.setUseLastModified(true)
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath,
Resource location) throws IOException {
if (resourcePath.endsWith(".gitignore")) {
return null;
}
return super.getResource(resourcePath, location);
}
});
}
}