SpringBoot相关组件配置

SpringBoot用某个组件,并自定义有关配置

【1】自定义ResetTemplate

【1】导入依赖

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--自定义resttemplate连接池时,依赖该jar-->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.6</version>
		</dependency>
	</dependencies>

【2】编写yml配置文件,有些硬编码可自行抽取

server:
  port: 8001
spring:
  application:
    name: consumer
resttemplate:
  maxTotalConnect: 20 #最大连接数
  maxConnectPerRoute: 20 #最大并发数
  getRequestTimeout: 2500 #获取连接的等待时间
  connectTimeout: 2000 #连接服务器的等待时间
  readTimeout: 1000 #等待服务器数据的时间

【3】配置类编写:总顺序:创建连接池,用连接池创建客户端对象,用客户端对象创建restTemplate对象

// Desc:自定义创建RestTemplate对象的配置类

@Configuration
@ConditionalOnClass(value = {RestTemplate.class, HttpClient.class})//如果这两个类存在该配置才会生效
public class RestConfig {

	//连接池最大连接数
	@Value("${resttemplate.maxTotalConnect}")
	private int maxTotalConnect;
	//最大并发数
	@Value("${resttemplate.maxConnectPerRoute}")
	private int maxConnectPerRoute;
	@Value("${resttemplate.connectTimeout}")
	private int connectTimeout;
	@Value("${resttemplate.readTimeout}")
	private int readTimeout;
	@Value("${resttemplate.getRequestTimeout}")
	private int getRequestTimeout;

	/**
	 * 创建RestTemplate对象
	 * @return
	 */
	@Bean
	@ConditionalOnMissingBean(RestTemplate.class)//IOC中不存在这个类型的bean才会创建自定义的bean
	public RestTemplate createtempLate() {
		//创建ClientHttpRequestFactory对象,作为参数传递给resttemplate
		RestTemplate restTemplate = new RestTemplate(this.createFactory());

		//设置默认的异常处理器
		restTemplate.setErrorHandler(new DefaultResponseErrorHandler());

		//创建一个内容转换器然后在set到resttemplate中
		List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
			//添加字符转换器
		messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
			//添加
		messageConverters.add(new FormHttpMessageConverter());
		messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
		messageConverters.add(new MappingJackson2HttpMessageConverter());
		//将内容转换器添加到resttemplate对象中
		restTemplate.setMessageConverters(messageConverters);

		return restTemplate;

		//另一种方式添加内容转换器,了解即可。获取resttemplate对象中的内容转换器,然后在内容转化器中添加
/*		List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
		HttpMessageConverter<?> converterTarget = null;
		for (HttpMessageConverter<?> item : converterList) {
			if (StringHttpMessageConverter.class == item.getClass()) {
				converterTarget = item;
				break;
			}
		}
		if (null != converterTarget) {
			converterList.remove(converterTarget);
		}
		converterList.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));*/
		//加入FastJson转换器 根据使用情况进行操作,此段注释,默认使用jackson
		//converterList.add(new FastJsonHttpMessageConverter4());
	}

	/** n
	 * 创建http客户端工厂
	 * @return 客户端工厂
	 */
	public ClientHttpRequestFactory createFactory() {
		//	最大连接数小于等于0,使用spring整合的默认resttemplate配置,底层使用jdk的HttpConnection,
		if (this.maxTotalConnect <= 0) {
			SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
			factory.setConnectTimeout(this.connectTimeout);
			factory.setReadTimeout(this.readTimeout);
			return factory;
		}

		//	大于0使用Apache的HttpClient,自定义连接池的相关属性
		//【1】创建连接池,并设置参数
			//设置长连接时间为30秒
		PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
			//设置整个连接池最大连接数
		connectionManager.setMaxTotal(maxTotalConnect);
			//最大并行数
		connectionManager.setDefaultMaxPerRoute(maxConnectPerRoute);

		//【2】创建HttpClient对象,并设置请求的参数,httpclient对象依赖连接池
		HttpClientBuilder builder = HttpClients.custom();
		
		RequestConfig config = RequestConfig.custom()
				//服务器返回数据(response)的时间,超过该时间抛出read timeout
				.setSocketTimeout(this.readTimeout)
				//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
				.setConnectTimeout(this.connectTimeout)
				//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException:
				// Timeout waiting for connection from pool
				.setConnectionRequestTimeout(this.getRequestTimeout)
				.build();

		List<Header> headers = new ArrayList<>();
		headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
		headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
		headers.add(new BasicHeader("Accept-Language", "zh-CN"));

		HttpClient httpClient = HttpClientBuilder.create()
				//添加连接池
				.setConnectionManager(connectionManager)
				//添加默认重试机制
				.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
				//添加长接连所需的请求头
				.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
				//添加请求配置
				.setDefaultRequestConfig(config)
				//设置请求头
				.setDefaultHeaders(headers)
				//建造对象
				.build();
		
		//【3】创建连接工厂,依赖httpClient对象
		HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
		
		return factory;
	}
}

【2】自定义RedisTemplate,并自定义Springboot Cache设置(使用redis作为缓存的设置)

package com.dist.xdata.dedms.infrastructure.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.MapPropertySource;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
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.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration

public class RedisConfig {

	@Value("${spring.redis.clusterNodes:}")
	private String clusterNodes;
	@Value("${spring.redis.host}")
	private String redisHost;
	@Value("${spring.redis.port}")
	private int redisPort;
	@Value("${spring.redis.password:}")
	private String redisPasswd;

	private int timeOut = 2000;
	private int redirects = 8;

	/**
	 * redis配置
	 * @return
	 */
	@Bean
	public RedisClusterConfiguration redisClusterConfiguration() {
		Map<String, Object> source = Maps.newHashMap();
		if (!StringUtils.isBlank(clusterNodes)) {
			source.put("spring.redis.cluster.nodes", clusterNodes);
		}
		source.put("spring.redis.cluster.timeout", timeOut);
		source.put("spring.redis.cluster.max-redirects", redirects);
		return new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));
	}

	/**
	 * redis连接
	 * @param redisClusterConfiguration
	 * @return
	 */
	@Bean
	public RedisConnectionFactory redisConnectionFactory(RedisClusterConfiguration redisClusterConfiguration) {
		JedisConnectionFactory cf;
		if (!StringUtils.isBlank(clusterNodes)) {
			cf = new JedisConnectionFactory(redisClusterConfiguration);
		} else {
			RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
			redisStandaloneConfiguration.setHostName(redisHost);
			redisStandaloneConfiguration.setPort(redisPort);
			redisStandaloneConfiguration.setPassword(RedisPassword.of(redisPasswd));
			cf = new JedisConnectionFactory(redisStandaloneConfiguration);
		}
		cf.afterPropertiesSet();
		return cf;
	}


	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
		RedisTemplate<String, Object> template = new RedisTemplate();
		template.setConnectionFactory(factory);
		// 定义key序列化方式
		RedisSerializer<String> keySerializer = new StringRedisSerializer();
		// 定义value的序列化方式
		Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer(Object.class);

		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		valueSerializer.setObjectMapper(om);

		template.setKeySerializer(keySerializer);
		template.setValueSerializer(valueSerializer);
		template.setHashKeySerializer(keySerializer);
		template.setHashValueSerializer(valueSerializer);
		template.afterPropertiesSet();
		return template;
	}

	/**
	 * 创建RedisCacheManager,替换默认的
	 * @param redisConnectionFactory redis的连接工厂1
	 * @return
	 */
	@Bean
	public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {

		RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);

		// 默认配置,过期时间指定是30分钟
		RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
		defaultCacheConfig.entryTtl(Duration.ofMinutes(30));

		// redisExpire1h cache配置,过期时间指定是1小时,缓存key的前缀指定成dist-_(存到redis的key会自动添加这个前缀)
		RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().
				entryTtl(Duration.ofHours(1)).prefixKeysWith("dist-");
		Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(8);
		redisCacheConfigurationMap.put("redisExpire1h", userCacheConfiguration);

		RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap);
		return cacheManager;
	}

}

【3】自定义@Scheduler定时任务注解设置

@Configuration
public class AsyncTaskConfig implements SchedulingConfigurer {
    //线程池线程数量,获取当前处理的的逻辑处理器数,本台电脑i7是12线程,得到是12
    private final static int corePoolSize = Runtime.getRuntime().availableProcessors() * 5;

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.initialize();// 初始化线程池
        scheduler.setPoolSize(corePoolSize);// 线程池容量
        scheduler.setDaemon(true);  // 设置守护线程
        return scheduler;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        //注册定时任务的线程池
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler());
    }
}

【4】自定义Filter的两种方式

1,使用注解@WebFilter
package com.dist.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(urlPattern = "*.txt")
public class TxtPreviewFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		if (httpServletRequest.getRequestURI().endsWith("txt")) {
			httpServletResponse.setHeader("Content-Type", "text/plain;charset=UTF-8");
		}
		chain.doFilter(httpServletRequest, httpServletResponse);
	}

	@Override
	public void destroy() {

	}
}
2,使用配置类添加自定义过滤器

2.1,实现一个Filter接口,然后在配置类中添加过滤器

package com.dist.web.config;
import com.dist.web.filter.AasWopiFilter;
import com.dist.web.filter.AppValidateFilter;
import com.dist.web.filter.TxtPreviewFilter;
import com.dist.web.filter.WopiFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class FilterConfig {

    /**
     * txt文件预览过滤器
     * @return
     */
    @Bean
    public FilterRegistrationBean txtPreviewFilterRegistrationBean() {
        //创建注册器
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        //new 过滤器对象
        TxtPreviewFilter txtPreviewFilter = new TxtPreviewFilter();

        //注册
        registrationBean.setFilter(txtPreviewFilter);

        //添加过滤规则
        List<String> urlPatterns = new ArrayList<>();
        urlPatterns.add("*.txt");
        registrationBean.setUrlPatterns(urlPatterns);

        // 数字越小,优先级越高
        registrationBean.setOrder(Integer.MAX_VALUE - 3);

        return registrationBean;
    }
}

【5】springboot中使用线程池

5.1,编写配置类,自定义一个线程池注册到容器中

@Configuration
public class ThreadConfig {

    //线程池线程数量
    private final static int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 5;

    // 最大线程数量
    private final static int MAX_POOL_SIZE = CORE_POOL_SIZE * 2;

    /**
     * 获取线程池
     * @return
     */
    @Bean(name = "threadExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置核心线程数量
        executor.setCorePoolSize(CORE_POOL_SIZE);
        //设置最大线程数
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        //设置线程名前缀
        executor.setThreadNamePrefix("web-thread-");
        //设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //设置线程活跃时间
        executor.setKeepAliveSeconds(60);
        //设置队列容量
        executor.setQueueCapacity(10);
        //初始化线程池
        executor.initialize();  
        //可以继续设置其它线程池相关配置,这里省略
        return executor;
    }
}

5.2、在主类中开启异步执行功能,使用@EnableAsync注解

5.3、在需要异步执行的方法上使用@Async注解。

5.4、注意点:异步执行需要返回值,见下例

	@Override
	@Async
	public ListenableFuture<String> asyncDoWithResult(String mark) {
		logger.info("开始执行任务,当前线程为: " + Thread.currentThread().getName());
		try {
			Thread.sleep(2000);
			if (!"yes".equals(mark)) {
				throw new IllegalArgumentException("参数错误");
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		logger.info("任务执行完成");
        //创建返回值,并设置回调接口
		AsyncResult<String> result = new AsyncResult<>("success");
		result.addCallback(new ListenableFutureCallback<String>() {
			@Override
			public void onFailure(Throwable ex) {
				logger.info("失败的回调接口:" + ex.getMessage());
			}

			@Override
			public void onSuccess(String result) {
				logger.info("成功的回调接口,结果为:" + result);
			}
		});
		return result;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值