Skip to content

Commit

Permalink
@value 使用姿势
Browse files Browse the repository at this point in the history
  • Loading branch information
liuyueyi committed Jun 2, 2021
1 parent d6fb8d6 commit 94be1ac
Show file tree
Hide file tree
Showing 15 changed files with 362 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.git.hui.boot.bind.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
import org.springframework.validation.annotation.Validated;

import javax.annotation.PostConstruct;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.util.List;
Expand Down Expand Up @@ -31,4 +34,17 @@ public class BindConfig {
private Pwd mainPwd;

private Jwt jwt;

/**
* fixme 对于列表这种嵌套的方式,生成的 spring-configuration-metadata.json 无法友好的支持它; 即IDEA中,在yml文件中,配置对应的属性时,无法直接定位到 Jwt#token
*/
private List<Jwt> tokens;

@Autowired
private Environment environment;

@PostConstruct
public void init() {
System.out.println(tokens);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ hhui:
user: 一灰灰blog
pwd: yihuihui
code: 9
Jwt: '{"token": "11111111123", "timestamp": 1610880489123}'
Jwt: '{"token": "11111111123", "timestamp": 1610880489123}'
tokens:
- token: 123
timestamp: 1111111
- token: abc
timestamp: 2222222
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@ spring:
profiles:
active: bind


val:
inj:
- a: 1
b: 2
c: 3
- z: 10
zz: 11
zzz: 12
4 changes: 4 additions & 0 deletions spring-boot/002-properties-value/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.*
target/*
*.iml
!.gitignore
15 changes: 15 additions & 0 deletions spring-boot/002-properties-value/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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">
<parent>
<artifactId>spring-boot</artifactId>
<groupId>com.git.hui.boot</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>002-properties-value</artifactId>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.git.hui.boot.properties.value;

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

/**
* @author yihui
* @date 2021/6/2
*/
@SpringBootApplication
public class Application {


public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.git.hui.boot.properties.value;

import com.git.hui.boot.properties.value.model.Jwt;
import com.git.hui.boot.properties.value.parse.JwtConverter;
import com.git.hui.boot.properties.value.parse.JwtEditor;
import com.git.hui.boot.properties.value.parse.JwtFormatter;
import org.springframework.beans.factory.config.CustomEditorConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;

import java.util.Collections;

/**
* @author yihui
* @date 2021/6/2
*/
@Configuration
public class AutoConfiguration {
/**
* 注册自定义的 propertyEditor
*
* @return
*/
// @Bean
public CustomEditorConfigurer editorConfigurer() {
CustomEditorConfigurer editorConfigurer = new CustomEditorConfigurer();
editorConfigurer.setCustomEditors(Collections.singletonMap(Jwt.class, JwtEditor.class));
return editorConfigurer;
}

/**
* 注册自定义的converter
*
* @return
*/
@Bean("conversionService")
public ConversionServiceFactoryBean conversionService() {
ConversionServiceFactoryBean factoryBean = new ConversionServiceFactoryBean();
factoryBean.setConverters(Collections.singleton(new JwtConverter()));
return factoryBean;
}

// @Bean("conversionService")
public FormattingConversionServiceFactoryBean conversionService2() {
FormattingConversionServiceFactoryBean factoryBean = new FormattingConversionServiceFactoryBean();
factoryBean.setConverters(Collections.singleton(new JwtConverter()));
factoryBean.setFormatters(Collections.singleton(new JwtFormatter()));
return factoryBean;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.git.hui.boot.properties.value.config;

import com.git.hui.boot.properties.value.model.Jwt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.List;

/**
* @author yihui
* @date 2021/6/2
*/
@Component
public class ConfigProperties {

@Value("${auth.jwt.token}")
private String token;

@Value("${auth.jwt.expire}")
private Long expire;

/**
* 不存在,使用默认值
*/
@Value("${auth.jwt.no:default_no:111}")
private String no;

/**
* 英文逗号分隔,转列表
*/
@Value("${auth.jwt.whiteList}")
private List<Long> whiteList;

/**
* yml数组,无法转换过来,只能根据 "auth.jwt.blackList[0]", "auth.jwt.blackList[1]" 来取对应的值
*/
@Value("${auth.jwt.blackList:10,11,12}")
private String[] blackList;

/**
* 借助 PropertyEditor 来实现字符串转对象
*/
@Value("${auth.jwt.tt}")
private Jwt tt;

@Autowired
private Environment environment;

@PostConstruct
public void init() {
System.out.println("token: " + token + "\nexpire:" + expire + "\nno:" + no + "\nwhiteList:" + whiteList +
"\nblackList:" + Arrays.asList(blackList) + "\ntt:" + tt);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.git.hui.boot.properties.value.config;

import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Primary;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/**
* @author yihui
* @date 2021/6/2
*/
@Primary
@Component
public class MyPropertySourcesPlaceHolderConfigure extends PropertySourcesPlaceholderConfigurer {
@Autowired
protected Environment environment;

/**
* {@code PropertySources} from the given {@link Environment}
* will be searched when replacing ${...} placeholders.
*
* @see #setPropertySources
* @see #postProcessBeanFactory
*/
@Override
public void setEnvironment(Environment environment) {
super.setEnvironment(environment);
this.environment = environment;
}

@SneakyThrows
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, ConfigurablePropertyResolver propertyResolver) throws BeansException {
Field field = propertyResolver.getClass().getDeclaredField("propertySources");
boolean access = field.isAccessible();
field.setAccessible(true);
MutablePropertySources propertySource = (MutablePropertySources) field.get(propertyResolver);
field.setAccessible(access);
PropertySource source = new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
@Override
@Nullable
public String getProperty(String key) {
// 对数组进行兼容
String ans = this.source.getProperty(key);
if (ans != null) {
return ans;
}

StringBuilder builder = new StringBuilder();
String prefix = key.contains(":") ? key.substring(key.indexOf(":")) : key;
int i = 0;
while (true) {
String subKey = prefix + "[" + i + "]";
ans = this.source.getProperty(subKey);
if (ans == null) {
return i == 0 ? null : builder.toString();
}

if (i > 0) {
builder.append(",");
}
builder.append(ans);
++i;
}
}
};
propertySource.addLast(source);
super.processProperties(beanFactoryToProcess, propertyResolver);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.git.hui.boot.properties.value.model;

import lombok.Data;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
* @author yihui
* @date 2021/6/2
*/
@Data
public class Jwt {
private String source;
private String token;
private Long expire;

public static Jwt parse(String text, String source) {
String[] kvs = StringUtils.split(text, ";");
Map<String, String> map = new HashMap<>(8);
for (String kv : kvs) {
String[] items = StringUtils.split(kv, ":");
if (items.length != 2) {
continue;
}
map.put(items[0].trim().toLowerCase(), items[1].trim());
}
Jwt jwt = new Jwt();
jwt.setSource(source);
jwt.setToken(map.get("token"));
jwt.setExpire(Long.valueOf(map.getOrDefault("expire", "0")));
return jwt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.git.hui.boot.properties.value.parse;

import com.git.hui.boot.properties.value.model.Jwt;
import org.springframework.core.convert.converter.Converter;

/**
* convert 优先级大于 propertyEditor
*
* @author yihui
* @date 2021/6/2
*/
public class JwtConverter implements Converter<String, Jwt> {
@Override
public Jwt convert(String s) {
return Jwt.parse(s, "JwtConverter");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.git.hui.boot.properties.value.parse;

import com.git.hui.boot.properties.value.model.Jwt;

import java.beans.PropertyEditorSupport;

/**
* 当Editor 与 PODO 放在同一个包路径下时,不需要主动注册,就会被Spring识别到
*
* @author yihui
* @date 2021/6/2
*/
public class JwtEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(Jwt.parse(text, "JwtEditor"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.git.hui.boot.properties.value.parse;

import com.alibaba.fastjson.JSONObject;
import com.git.hui.boot.properties.value.model.Jwt;
import org.springframework.format.Formatter;

import java.text.ParseException;
import java.util.Locale;

/**
* @author yihui
* @date 2021/6/2
*/
public class JwtFormatter implements Formatter<Jwt> {
@Override
public Jwt parse(String text, Locale locale) throws ParseException {
return Jwt.parse(text, "JwtFormatter");
}

@Override
public String print(Jwt object, Locale locale) {
return JSONObject.toJSONString(object);
}
}
Loading

0 comments on commit 94be1ac

Please sign in to comment.