springboot组件

一、springboot 事件监听

1.1  事件发布与监听

1. 事件定义
public class MyMessageEvent extends ApplicationEvent {

    private String type;
    private Object mqMessage;

    public MyMessageEvent(Object source, String type, Object mqMessage) {
        super(source);
        this.type = type;
        this.mqMessage = mqMessage;
    }

    public String getType() {
        return type;
    }

    public Object getMqMessage() {
        return mqMessage;
    }
}

2. 事件发布

@Slf4j
@Component
public class EventAlarmMessageListener extends EvoEventMessageHandler<EvoAlarmMessage> {

    @Autowired
    private ApplicationEventPublisher publisher;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    protected EvoAlarmMessage parseData(EvoEventMessage messageBody) {
        System.out.println(JSON.toJSONString(messageBody));
        logger.info("【Alarm message】 {}", JSON.toJSONString(messageBody));
        publisher.publishEvent(new MyMessageEvent(this, messageBody.getMethod(), messageBody));
        return null;
    }

    @Override
    protected void process(String method, EvoAlarmMessage data) {

    }
}

3. 事件监听

    @EventListener(condition = "'alarm.msg'.equals(#messageEvent.type)")
    public void actTimeAttendanceListener(MyMessageEvent messageEvent) {
        EvoEventMessage eventMessage = (EvoEventMessage) messageEvent.getMqMessage();
        String str = JSONObject.toJSONString(eventMessage.getInfo());
        JSONObject jsonObject = JSONObject.parseObject(str);
        AlarmMessage.Info info = jsonObject.toJavaObject(AlarmMessage.Info.class);
}

二、配置文件读取

参考:SpringBoot读取配置文件的6种方式_springboot 读取配置文件-CSDN博客

2.1  使用@Value注解读取单个配置

(1)编写application.yml文件配置:

student:
  name: 张三
  age: 20

(2)使用@Value读取配置:

@SpringBootTest
@Slf4j
public class ValueTest {
    @Value("${student.name}")
    private String name;
 
    @Value("${student.age}")
    private Integer age;
 
    @Test
    public void test() {
    log.info("@Value 配置获取 name:{},age:{}",name,age);
    }
 
}


@Value注意事项:

@Value 注解只能读取单个配置进行赋值,无法读取整个配置文件批量赋值。当使用@Value注解读取配置时,确保配置在yml中存在,否则启动程序时就会报错。注解中属性名引用方式如下:
    @Value("${一级属性名.二级属性名...}")

当使用 @Value 注解引用属性时,可以在属性名称后面使用冒号(: default-value )的形式添加默认值。这样,如果在配置文件中找不到对应的属性,就会使用默认值。如果在配置文件中找到了属性,其值将会覆盖默认值。

@Value 注解只能用于被Spring管理的Bean中使用,,如使用 @Component 、 @Service 、 @Controller 等注解修饰的类,或者使用Java配置编写的 @Configuration 类中。
@Value 注解可以用于字段、构造函数参数、方法参数和方法上。当将它放在方法上时,Spring容器初始化时会调用该方法,并将配置属性的值作为方法的参数传递进去。
 

//可以使用各种类型的默认值,包括字符串、数字、布尔值等
@Value("${student.name:aopmin}")
private String name;
 
@Value("${student.age:18}")
private Integer age;

//表示一个空字符串作为默认值
@Value("${student.name:}")
private String name;

Spring支持多种数据类型的属性注入,对于每种类型,都可以设置默认值。以下是一些常见的数据类型及其默认值设置示例:

1. 字符串类型
@Value("${app.name:MyApp}")
private String appName;

如果配置文件中未定义app.name,那么appName将会被赋值为"MyApp"。

2. 整数类型
@Value("${app.port:8080}")
private int port;
如果配置文件中未定义app.port,那么ports将会被赋值为8080。

3. 布尔类型
@Value("${eature.enabled:false}")
private Boolean featureEnabled;
如果配置文件中未定义feature.enabled,那么featureEnabled将会被赋值为false。

4. 浮点类型
@Value("${threshold.value:0.5}")
private Double thresholdValue;
如果配置文件中未定义threshold.value,那么thresholdValue将会被赋值为0.5。

5. 列表类型
对于列表类型的值,你可以使用逗号分隔的形式来定义默认值。
@Value("${app.tags:tag1,tag2,tag3}")
private List<String> appTags;
如果配置文件中未定义appTags,那么servers列表将包含"tag1"、"tag2"、"tag3"。

6. 数组类型
对于列表类型的值,你可以使用逗号分隔的形式来定义默认值。
@Value("${app.tags:tag1,tag2,tag3}")
private String[] appTags;
如果配置文件中未定义appTags,那么servers列表将包含"tag1"、"tag2"、"tag3"。

7. Map类型:
@Value("#{${app.properties:{key1:'value1', key2:'value2'}}}")
private Map<String, String> appProperties;

2.2  使用@ConfigurationProperties注解批量绑定

package cn.hk.pojo;
 
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
/**
 * 参数配置类   (需要提供setter方法)
 */
 
//将这个类与配置文件前缀为student的配置绑定,然后把yml、properties中关于student的配置信息注入到当前类的成员变量中
@Component
@Data
@ConfigurationProperties(prefix = "student")
public class StudentProperties {
    private String name;
 
}
  1. @ConfigurationProperties注意事项:
  2. 确保添加了@EnableConfigurationProperties注解:为了使@ConfigurationProperties生效,需要在主配置类上添加@EnableConfigurationProperties(value=xxxxProperties.class)注解,开启@ConfigurationProperties注解自动装配功能。
  3. 配置文件中的属性名与类字段名的映射规则:默认情况下,@ConfigurationProperties会将配置文件中的属性名与类字段名进行映射。例如,配置文件中的属性student.name会自动映射到类字段name上。如果配置文件中的属性名与类字段名不一致,可以使用@Value注解或通过setter方法来指定映射关系。
  4. 类必须是Spring管理的Bean:被@ConfigurationProperties注解标记的类必须是由Spring容器管理的Bean,因此需要确保该类被@Component或其他相关注解标记,以便Spring能够扫描并创建该类的实例。
  5. 支持类型转换:@ConfigurationProperties支持自动类型转换,将配置文件中的字符串值转换为目标字段的类型。例如,将字符串转换为整数、布尔值等。如果无法进行类型转换,会抛出异常。
  6. 默认值和可选属性:可以为@ConfigurationProperties注解的字段设置默认值,以防止配置文件中缺少对应的属性。可以使用":“符号指定默认值,例如@Value(”${my.property:default-value}")。另外,可以使用required属性来指定某个属性是否为必需的。
  7. 配置项的验证和校验:可以使用JSR-303/349规范的注解对@ConfigurationProperties注解的字段进行验证和校验。例如,使用@NotBlank、@Min、@Max等注解来限制属性值的有效性。

三、springboot-kafka

参考地址:spring boot 集成kafka生产者消费者_springboot集成kafka生产者工具类-CSDN博客

四、springboot 多数据源

参考地址:SpringBoot整合mysql、postgres、sqlserver实现多数据源配置案例_spring boot 项目集成mysql和sqlserver-CSDN博客

五、接口参数校验

    @PostMapping("/orgMove")
    public RestResult orgMove(@Validated(AddGroup.class) @RequestBody OrgMoveParam param, HttpServletRequest request) {
	
	@Data
@JsonIgnoreProperties(ignoreUnknown=true)
public class OrgMoveParam {

    /**
     * 旧组织编码
     */
    @NotEmpty(message = "旧组织编码为空",groups = {AddGroup.class})
    private String oldOrgCode;
	
	
	public interface AddGroup {
}

六、springboot 多线程

 第一钟


import com.dahua.evo.event.common.constant.BusinessConstant;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.*;

/**
 * The type Spring executor.
 *
 * @author 234271
 * @version 1.0   全局线程池配置类
 * @since 2023 /2/6 16:46
 */
@Configuration
public class SpringExecutor extends BaseConfig{

	@Override
	public String getConfigPrefix(){
		return "spring.execute.";
	}

    /**
     * Alarm msg executor executor.
     *
     * @return the executor
     */
    @Bean(name = "alarmMsgExecutor")
	public Executor alarmMsgExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(Integer.parseInt(getPropertyResolver().getProperty("alarm.msg.corePoolSize")));
		executor.setMaxPoolSize(Integer.parseInt(getPropertyResolver().getProperty("alarm.msg.maxPoolSize")));
		executor.setQueueCapacity(Integer.parseInt(getPropertyResolver().getProperty("alarm.msg.queueCapacity")));
		executor.setKeepAliveSeconds(Integer.parseInt(getPropertyResolver().getProperty("alarm.msg.keepAliveSeconds")));
		executor.setThreadNamePrefix("alarmMsgExecutor-");

		executor.setRejectedExecutionHandler(new AlarmPolicy());
		executor.initialize();
		return executor;
	}

    /**
     * Alarm log executor executor.
     *
     * @return the executor
     */
    @Bean(name = "alarmDbExecutor")
	public Executor alarmLogExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(Integer.parseInt(getPropertyResolver().getProperty("alarm.db.corePoolSize")));
		executor.setMaxPoolSize(Integer.parseInt(getPropertyResolver().getProperty("alarm.db.maxPoolSize")));
		executor.setQueueCapacity(Integer.parseInt(getPropertyResolver().getProperty("alarm.db.queueCapacity")));
		executor.setKeepAliveSeconds(Integer.parseInt(getPropertyResolver().getProperty("alarm.db.keepAliveSeconds")));
		executor.setThreadNamePrefix("alarmDbExecutor-");

		executor.setRejectedExecutionHandler(new AlarmPolicy());
		executor.initialize();
		return executor;
	}

    /**
     * 针对事件总线 rrb 的 Executor
     *
     * @return java.util.concurrent.Executor 返回对象
     * @author 234271
     * @since V5.0.6 2023/7/5 15:14
     */
    @Bean(name = "rrbExecutor")
	public Executor rrbExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(Integer.parseInt(getPropertyResolver().getProperty("rrb.corePoolSize")));
		executor.setMaxPoolSize(Integer.parseInt(getPropertyResolver().getProperty("rrb.maxPoolSize")));
		executor.setQueueCapacity(Integer.parseInt(getPropertyResolver().getProperty("rrb.queueCapacity")));
		executor.setKeepAliveSeconds(Integer.parseInt(getPropertyResolver().getProperty("rrb.keepAliveSeconds")));
		executor.setThreadNamePrefix("EventExecutor-RRB-");

		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}

    /**
     * 针对事件推送总线 rrb 的 Executor
     *
     * @return java.util.concurrent.Executor 返回对象
     * @author 234271
     * @since V5.0.6 2023/7/5 15:14
     */
    @Bean(name = "rrbSendExecutor")
	public Executor rrbSendExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(Integer.parseInt(getPropertyResolver().getProperty("send.rrb.corePoolSize")));
		executor.setMaxPoolSize(Integer.parseInt(getPropertyResolver().getProperty("send.rrb.maxPoolSize")));
		executor.setQueueCapacity(Integer.parseInt(getPropertyResolver().getProperty("send.rrb.queueCapacity")));
		executor.setKeepAliveSeconds(Integer.parseInt(getPropertyResolver().getProperty("send.rrb.keepAliveSeconds")));
		executor.setThreadNamePrefix("EventExecutor-RRB-Send-");

		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}

    /**
     * Container redis message listener container.
     *
     * @param connectionFactory      the connection factory
     * @param redisSubscribeListener the redis subscribe listener
     * @return the redis message listener container
     */
    @Bean
	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
	                                        RedisSubscribeListener redisSubscribeListener){

		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.setSubscriptionExecutor(Executors.newSingleThreadExecutor());
		container.setTaskExecutor(Executors.newSingleThreadExecutor());
		container.addMessageListener(redisSubscribeListener, new PatternTopic(BusinessConstant.EVENT_REDIS_SUBSCRIBE));
		return container;
	}

    /**
     * Get application event multicaster application event multicaster.
     *
     * @return the application event multicaster
     */
    @Bean("applicationEventMulticaster")
	public ApplicationEventMulticaster getApplicationEventMulticaster(){
		SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
		int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
		ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("applicationEventMulticaster-pool-%d").build();
		ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, corePoolSize, 60L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(1000),namedThreadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
		simpleApplicationEventMulticaster.setTaskExecutor(executor);
		return simpleApplicationEventMulticaster;
	}


	/**
	 *
	 *  增加公共线程池配置
	 * @since V5.0.14 2023/8/8 17:10
	 * @return java.util.concurrent.Executor 返回对象
	 * @author 234271
	 */
	@Bean(name = "eventCommonExecutor")
	public Executor eventCommonExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(Integer.parseInt(getPropertyResolver().getProperty("common.corePoolSize")));
		executor.setMaxPoolSize(Integer.parseInt(getPropertyResolver().getProperty("common.maxPoolSize")));
		executor.setQueueCapacity(Integer.parseInt(getPropertyResolver().getProperty("common.queueCapacity")));
		executor.setKeepAliveSeconds(Integer.parseInt(getPropertyResolver().getProperty("common.keepAliveSeconds")));
		executor.setThreadNamePrefix("AlarmExecutor-eventCommonExecutor-");

		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}

	/**
	 *
	 *  增加公共线程池配置
	 * @since V5.0.14 2023/8/8 17:10
	 * @return java.util.concurrent.Executor 返回对象
	 * @author 234271
	 */
	@Bean(name = "batchInsertThirdAlarmExecutor")
	public Executor batchInsertThirdAlarmExecutor(){
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(Integer.parseInt(getPropertyResolver().getProperty("common.corePoolSize")));
		executor.setMaxPoolSize(Integer.parseInt(getPropertyResolver().getProperty("common.maxPoolSize")));
		executor.setQueueCapacity(Integer.parseInt(getPropertyResolver().getProperty("common.queueCapacity")));
		executor.setKeepAliveSeconds(Integer.parseInt(getPropertyResolver().getProperty("common.keepAliveSeconds")));
		executor.setThreadNamePrefix("BatchInsertThirdAlarmExecutor-eventCommonExecutor-");

		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}
}
    @Resource(name = "batchInsertThirdAlarmExecutor")
    private Executor executor;

        if (CollUtil.isNotEmpty(insertList)) {
            log.info("thirdAlarmInfoServiceImpl.batchAdd.insertList:{}", JSONObject.toJSONString(insertList));
            executor.execute(()->{
                  thirdAlarmInfoMapper.insertBatch(insertList);
            });
@Configuration
public class ThreadPoolsConfiguration {

    //线程池的核心线程数量
    private static final int HANDLER_CORE_POOL_SIZE = 2;
    //线程池的最大线程数
    private static final int HANDLER_MAX_POOL_SIZE = 10;
    //阻塞队列的容量
    private static final int HANDLER_QUEUE_CAPACITY = 5000;
    //当线程数大于核心线程数时,多余的空闲线程存活的最长时间()
    private static final int HANDLER_KEEP_ALIVE_TIME = 1;

    @Bean(name = {"cardRecordSyncExecutor"})
    public Executor cardRecordSyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(HANDLER_CORE_POOL_SIZE);
        executor.setMaxPoolSize(HANDLER_MAX_POOL_SIZE);
        executor.setQueueCapacity(HANDLER_QUEUE_CAPACITY);
        executor.setKeepAliveSeconds(HANDLER_KEEP_ALIVE_TIME);
        executor.setThreadNamePrefix("cardRecordSyncExecutor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        executor.initialize();
        return executor;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值