跳转至

通用工具封装

restTemplate封装

package org.example.config;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * @author dkw
 * RestTemplate bean,访问 RESTful 服务的客户端工具
 * RestTemplate性能低,通过连接池复用连接,减少 TCP 握手和 SSL 开销,提升请求响应速度。
 */
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory){
        return new RestTemplate(requestFactory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        return new HttpComponentsClientHttpRequestFactory(httpClient());
//        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//        factory.setReadTimeout(1000);
//        factory.setConnectTimeout(1000);
//        return factory;
    }

    @Bean
    public HttpClient httpClient(){
        // 1. 注册HTTP和HTTPS协议的Socket工厂
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

        // 连接池最大是500个连接
        connectionManager.setMaxTotal(500);
        // MaxPerRoute是对maxtotal的细分,每个主机的并发最大是300,route是指域名
        connectionManager.setDefaultMaxPerRoute(300);

        RequestConfig requestConfig = RequestConfig.custom()
                // 返回数据的超时时间
                .setSocketTimeout(20000)
                // 连接上服务器的超时时间
                .setConnectTimeout(10000)
                // 从连接池中获取连接的超时时间
                .setConnectionRequestTimeout(1000)
                .build();

        CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();

        return closeableHttpClient;
    }
}

线程池配置:线程池配置和上面的http连接池配置都适用于提高qps

package org.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 */
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {

    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){

        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 设置核心线程数,线程池维护线程的最少数量,即使没有任务需要执行,也会一直存在
        threadPoolTaskExecutor.setCorePoolSize(8);
        // 阻塞队列的最大值,核心线程满时,可创建的阻塞线程的最大值
        threadPoolTaskExecutor.setQueueCapacity(1024);
        // 最大线程池数量,当线程数>=CorePoolSize,且任务队列已满时,线程池会创建出新线程来处理任务
        // 任务队列已满时,且当线程数 = MaxPoolSize,线程池会拒绝处理任务而抛出异常
        threadPoolTaskExecutor.setMaxPoolSize(64);
        // 线程的存活时长,当线程空闲时,允许现成的空闲时间最长为30s,超过30s就会自动销毁
        threadPoolTaskExecutor.setKeepAliveSeconds(30);

        threadPoolTaskExecutor.setThreadNamePrefix("自定义线程池");

        //拒绝策略
        // CallerRunsPolicy:由调用者线程处理任务(适用于不允许丢失任务的场景)。
        // DiscardOldestPolicy:丢弃队列中最旧的任务,尝试处理新任务(适用于允许部分任务超时的场景)。
        // DiscardPolicy:静默丢弃任务(谨慎使用,可能导致数据丢失)。
        //AbortPolicy,线程池的默认策略,会直接丢掉任务并且抛出RejectExecutionException异常
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // 初始化线程池(必须调用,否则配置不生效)
        threadPoolTaskExecutor.initialize();

        return threadPoolTaskExecutor;
    }
}

redisconfig配置,进行序列化和反序列化配置的时候注意,别踩坑。简单的字符串可以直接使用StringRedisTemplate。

package org.example.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisTemplateConfiguration {

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

    @Bean
    // RedisConnectionFactory:连接工厂,由 Spring 自动配置(如 Lettuce 或 Jedis 实现),用于创建 Redis 连接。
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //配置序列化规则,Jackson2JsonRedisSerializer:将 Value 序列化为 JSON 格式,支持复杂对象的序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        // 允许序列化/反序列化所有属性(包括私有字段)
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //设置key-value序列化规则,Redis 存储数据时需将对象序列化为字节数组,代码中配置了两种序列化方式:
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        //设置hash-value序列化规则
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        return redisTemplate;
    }
}