Spring使用总结

2022-01-05

测试时动态设置property/env

@DynamicPropertySource

@SpringJUnitConfig(...)
   @Testcontainers
   class ExampleIntegrationTests {
  
       @Container
       static RedisContainer redis = new RedisContainer();
  
       // ...
  
       @DynamicPropertySource
       static void redisProperties(DynamicPropertyRegistry registry) {
           registry.add("redis.host", redis::getContainerIpAddress);
           registry.add("redis.port", redis::getMappedPort);
       }
  
   }

2021-11-30

springboot command line arguments
https://www.baeldung.com/spring-boot-command-line-arguments

2021-10-06

打包信息(可依赖注入)

BuildProperties buildProperties;

自定义json格式

  • 在字段上添加注解
@JsonFormat(shape = JsonFormat.Shape.STRING)
private BigDecimal decimal = BigDecimal.valueOf(100.01);
  • 使用全局配置
@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.modules(modules())
        // 自定义过滤器的方式,需要在类上添加注解@JsonFilter("myFilter")
        						 .filters(new SimpleFilterProvider().addFilter("myFilter", new CurrencyPropertyFilter()))
                                 .failOnUnknownProperties(false)
                                 .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
                                 .serializationInclusion(JsonInclude.Include.NON_EMPTY)
                                 .featuresToEnable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)
                ;
    }

    public List<Module> modules() {
    	// 改写数据格式的方式
        SimpleModule bigDecimalModule = new SimpleModule(PackageVersion.VERSION){
            @Override
            public void setupModule(SetupContext context) {
                super.setupModule(context);
                context.configOverride(BigDecimal.class)
                        .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
            }
        };
		// 自定义序列化器的方式
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addDeserializer(LocalDateTime.class, new ZLocalDateTimeDeserializer());

        timeModule.addSerializer(LocalDateTime.class, new ZLocalDateTimeSerializer());
        return Lists.newArrayList(bigDecimalModule, timeModule);
    }

}
  • 自定义过滤器的方式拦截处理
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;

public class CurrencyPropertyFilter extends SimpleBeanPropertyFilter {
    private static final DecimalFormat FORMAT = new DecimalFormat("0.00000000");

    @Override
    public void serializeAsField(Object pojo, JsonGenerator jgen,
                                 SerializerProvider provider, PropertyWriter writer) throws Exception {
        CurrencyJson currencyJson = writer.findAnnotation(CurrencyJson.class);
        if (currencyJson != null) {
            Currency currency = null;
            // retrieve currency
            String unitCode = currencyJson.unitCode();
            if (StringUtils.isNotBlank(unitCode)) {
                currency = Currency.resolve(unitCode);
            } else {
                String unitFieldName = currencyJson.unitFieldName();
                Field currencyField = ReflectionUtils.findField(pojo.getClass(), unitFieldName);
                if (currencyField != null) {
                    currencyField.setAccessible(true);
                    currency = (Currency) currencyField.get(pojo);
                }
            }

            if (currency != null) {
                String writerFieldName = writer.getName();
                Field writerField = ReflectionUtils.findField(pojo.getClass(), writerFieldName);
                if (writerField != null) {
                    writerField.setAccessible(true);
                    BigDecimal amount = (BigDecimal) writerField.get(pojo);

                    if (currency == VirtualCurrency.DIAMOND || currency == VirtualCurrency.XP) {
                        jgen.writeNumberField(writerFieldName, amount.intValue());
                    } else {
                        jgen.writeStringField(writerFieldName, FORMAT.format(amount));
                    }
                    return;
                }
            }
        }

        super.serializeAsField(pojo, jgen, provider, writer);
    }
}

2021-09-07

spring泛型解析(工具)

public interface AppRepository extends JpaRepository<App, UUID>, JpaSpecificationExecutor<App> {}
@Nullable
private ResolvableType[] getRequiredTypeInfo(Class<?> converterClass, Class<?> genericIfc) {
	ResolvableType resolvableType = ResolvableType.forClass(converterClass).as(genericIfc);
	ResolvableType[] generics = resolvableType.getGenerics();
	if (generics.length < 2) {
		return null;
	}
	Class<?> sourceType = generics[0].resolve();
	Class<?> targetType = generics[1].resolve();
	if (sourceType == null || targetType == null) {
		return null;
	}
	return generics;
}
public static void main(String[] args) {
        ResolvableType resolvableType = ResolvableType.forClass(AppRepository.class).as(JpaRepository.class);
        ResolvableType[] generics = resolvableType.getGenerics();
        if (generics.length < 2) {
//            return null;
        }
        Class<?> sourceType = generics[0].resolve();
        Class<?> targetType = generics[1].resolve();
//        if (sourceType == null || targetType == null) {
//            return null;
//        }
//        return generics;
        System.out.println(sourceType);
    }

2021-09-02

Cache

https://www.baeldung.com/spring-cache-tutorial
https://www.baeldung.com/spring-boot-evict-cache

2021-07-23

@Profile

  • 支持简单的 &(与) |(或) i(非) 运算
  • 不要让逻辑运算结果不明确,(尴尬的没记录,印象中是逻辑运算与括号混合使用情况下容易出现)
  • 底层原理如下代码所示,主要是依赖Predicate的test方法,每次传入表达式的部分进行比较
public static void main(String[] args) {
        Profiles profiles = Profiles.of("(spring | framework)");

        boolean res = profiles.matches(activeProfiles("test"));
        System.out.println("haha" + res);
    }

    private static Predicate<String> activeProfiles(String... profiles) {
        return new MockActiveProfiles(profiles);
    }

    private static class MockActiveProfiles implements Predicate<String> {

        private final List<String> activeProfiles;

        MockActiveProfiles(String[] activeProfiles) {
            this.activeProfiles = Arrays.asList(activeProfiles);
        }

        @Override
        public boolean test(String profile) {
            // The following if-condition (which basically mimics
            // AbstractEnvironment#validateProfile(String)) is necessary in order
            // to ensure that the Profiles implementation returned by Profiles.of()
            // never passes an invalid (parsed) profile name to the active profiles
            // predicate supplied to Profiles#matches(Predicate<String>).
            if (!StringUtils.hasText(profile) || profile.charAt(0) == '!') {
                throw new IllegalArgumentException("Invalid profile [" + profile + "]");
            }
            return this.activeProfiles.contains(profile);
        }

    }

@Conditional

  • @ConditionalOnProperty
    判断environment中是否有指定属性变量,
    在springboot中大量使用
    在这里插入图片描述

  • @ConditionalOnExpression
    根据SpEL表达式计算条件是否满足
    表达式的返回值必须时 TRUE 或者 FALSE

@ConditionalOnExpression("!'${flyway.locations}'.isEmpty()")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值