first commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 异步调用线程配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021-09-02 20:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class AsyncConfig {
|
||||
|
||||
/**
|
||||
* 线程池 配置bean名称
|
||||
*/
|
||||
public static final String ASYNC_EXECUTOR_THREAD_NAME = "smart-admin-async-executor";
|
||||
|
||||
/**
|
||||
* 配置线程池
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = ASYNC_EXECUTOR_THREAD_NAME)
|
||||
public AsyncTaskExecutor executor() {
|
||||
int processors = Runtime.getRuntime().availableProcessors();
|
||||
int threadCount = Math.max(1, processors - 1);
|
||||
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
|
||||
// 核心线程数量
|
||||
taskExecutor.setCorePoolSize(threadCount);
|
||||
// 最大线程数量
|
||||
taskExecutor.setMaxPoolSize(threadCount);
|
||||
taskExecutor.setThreadNamePrefix(ASYNC_EXECUTOR_THREAD_NAME);
|
||||
taskExecutor.initialize();
|
||||
return taskExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* spring 异步任务 异常配置
|
||||
*/
|
||||
@Configuration
|
||||
public static class AsyncExceptionConfig implements AsyncConfigurer {
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return new AsyncExceptionHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义异常处理
|
||||
*/
|
||||
public static class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
|
||||
@Override
|
||||
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
|
||||
log.error("异步任务发生异常:{}, 参数:{}, ", method.getDeclaringClass().getSimpleName() + "." + method.getName(), Arrays.toString(objects), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2021/11/15 20:38
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsFilterConfig {
|
||||
|
||||
@Value("${access-control-allow-origin}")
|
||||
private String accessControlAllowOrigin;
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public CorsFilter corsFilter () {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowCredentials(true);
|
||||
// 设置访问源地址
|
||||
config.addAllowedOriginPattern(accessControlAllowOrigin);
|
||||
// 设置访问源请求头
|
||||
config.addAllowedHeader("*");
|
||||
// 设置访问源请求方法
|
||||
config.addAllowedMethod("*");
|
||||
// 对接口配置跨域设置
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import com.alibaba.druid.filter.Filter;
|
||||
import com.alibaba.druid.filter.stat.StatFilter;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.support.http.StatViewServlet;
|
||||
import com.alibaba.druid.support.http.WebStatFilter;
|
||||
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.lab1024.sa.common.common.domain.DataScopePlugin;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2017-11-28 15:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class DataSourceConfig {
|
||||
|
||||
@Value("${spring.datasource.driver-class-name}")
|
||||
String driver;
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
String url;
|
||||
|
||||
@Value("${spring.datasource.username}")
|
||||
String username;
|
||||
|
||||
@Value("${spring.datasource.password}")
|
||||
String password;
|
||||
|
||||
@Value("${spring.datasource.initial-size}")
|
||||
int initialSize;
|
||||
|
||||
@Value("${spring.datasource.min-idle}")
|
||||
int minIdle;
|
||||
|
||||
@Value("${spring.datasource.max-active}")
|
||||
int maxActive;
|
||||
|
||||
@Value("${spring.datasource.max-wait}")
|
||||
long maxWait;
|
||||
|
||||
@Value("${spring.datasource.time-between-eviction-runs-millis}")
|
||||
long timeBetweenEvictionRunsMillis;
|
||||
|
||||
@Value("${spring.datasource.min-evictable-idle-time-millis}")
|
||||
long minEvictableIdleTimeMillis;
|
||||
|
||||
@Value("${spring.datasource.filters}")
|
||||
String filters;
|
||||
|
||||
@Value("${spring.datasource.druid.username}")
|
||||
String druidUserName;
|
||||
|
||||
@Value("${spring.datasource.druid.password}")
|
||||
String druidPassword;
|
||||
|
||||
@Value("${spring.datasource.druid.login.enabled}")
|
||||
boolean druidLoginEnable;
|
||||
@Value("${spring.datasource.druid.method.pointcut}")
|
||||
String methodPointcut;
|
||||
|
||||
@Autowired
|
||||
private MybatisPlusInterceptor paginationInterceptor;
|
||||
|
||||
@Autowired(required = false)
|
||||
private DataScopePlugin dataScopePlugin;
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public DataSource druidDataSource() {
|
||||
DruidDataSource druidDataSource = new DruidDataSource();
|
||||
druidDataSource.setDbType(DbType.MYSQL.getDb());
|
||||
druidDataSource.setDriverClassName(driver);
|
||||
druidDataSource.setUrl(url);
|
||||
druidDataSource.setUsername(username);
|
||||
druidDataSource.setPassword(password);
|
||||
druidDataSource.setInitialSize(initialSize);
|
||||
druidDataSource.setMinIdle(minIdle);
|
||||
druidDataSource.setMaxActive(maxActive);
|
||||
druidDataSource.setMaxWait(maxWait);
|
||||
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||
druidDataSource.setValidationQuery("SELECT 1");
|
||||
try {
|
||||
druidDataSource.setFilters(filters);
|
||||
ArrayList<Filter> arrayList = new ArrayList<>();
|
||||
StatFilter statFilter = new StatFilter();
|
||||
statFilter.setMergeSql(true);
|
||||
statFilter.setSlowSqlMillis(500);
|
||||
statFilter.setLogSlowSql(true);
|
||||
arrayList.add(statFilter);
|
||||
druidDataSource.setProxyFilters(arrayList);
|
||||
druidDataSource.init();
|
||||
} catch (SQLException e) {
|
||||
log.error("初始化数据源出错", e);
|
||||
}
|
||||
|
||||
return druidDataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactory() throws Exception {
|
||||
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
|
||||
factoryBean.setDataSource(druidDataSource());
|
||||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
||||
Resource[] resources = resolver.getResources("classpath*:/mapper/**/*.xml");
|
||||
factoryBean.setMapperLocations(resources);
|
||||
|
||||
// 设置 MyBatis-Plus 分页插件 注意此处myBatisPlugin一定要放在后面
|
||||
List<Interceptor> pluginsList = new ArrayList<>();
|
||||
pluginsList.add(paginationInterceptor);
|
||||
if (dataScopePlugin != null) {
|
||||
pluginsList.add(dataScopePlugin);
|
||||
}
|
||||
factoryBean.setPlugins(pluginsList.toArray(new Interceptor[pluginsList.size()]));
|
||||
|
||||
return factoryBean.getObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 非正式环境 才加载
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Conditional(SystemEnvironmentConfig.class)
|
||||
@Bean
|
||||
public ServletRegistrationBean<StatViewServlet> druidServlet() {
|
||||
ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>();
|
||||
servletRegistrationBean.setServlet(new StatViewServlet());
|
||||
servletRegistrationBean.addUrlMappings("/druid/*");
|
||||
Map<String, String> initParameters = new HashMap<String, String>();
|
||||
//不设置用户名密码可以直接通过druid/index.html访问
|
||||
if (druidLoginEnable) {
|
||||
initParameters.put("loginUsername", druidUserName);
|
||||
initParameters.put("loginPassword", druidPassword);
|
||||
}
|
||||
initParameters.put("resetEnable", "false");
|
||||
servletRegistrationBean.setInitParameters(initParameters);
|
||||
return servletRegistrationBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<WebStatFilter> filterRegistrationBean() {
|
||||
FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<WebStatFilter>();
|
||||
filterRegistrationBean.setFilter(new WebStatFilter());
|
||||
filterRegistrationBean.addUrlPatterns("/*");
|
||||
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/*");
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JdkRegexpMethodPointcut jdkRegexpMethodPointcut() {
|
||||
JdkRegexpMethodPointcut jdkRegexpMethodPointcut = new JdkRegexpMethodPointcut();
|
||||
jdkRegexpMethodPointcut.setPatterns(methodPointcut);
|
||||
return jdkRegexpMethodPointcut;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
|
||||
DefaultPointcutAdvisor pointcutAdvisor = new DefaultPointcutAdvisor();
|
||||
pointcutAdvisor.setPointcut(jdkRegexpMethodPointcut());
|
||||
pointcutAdvisor.setAdvice(new DruidStatInterceptor());
|
||||
return pointcutAdvisor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
/**
|
||||
* java8 localDate 时间类格式化配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2017-11-28 15:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class DateConfig {
|
||||
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer customizer() {
|
||||
return builder -> {
|
||||
builder.deserializers(new LocalDateDeserializer(DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter()));
|
||||
builder.deserializers(new LocalDateTimeDeserializer(DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter()));
|
||||
builder.serializers(new LocalDateSerializer(DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter()));
|
||||
builder.serializers(new LocalDateTimeSerializer(DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter()));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* string 转为 LocalDateTime 配置类
|
||||
*
|
||||
* @author 卓大
|
||||
*/
|
||||
@Configuration
|
||||
public static class StringToLocalDateTime implements Converter<String, LocalDateTime> {
|
||||
|
||||
@Override
|
||||
public LocalDateTime convert(String str) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return null;
|
||||
}
|
||||
LocalDateTime localDateTime;
|
||||
try {
|
||||
localDateTime = LocalDateTimeUtil.parse(str, DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter());
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new RuntimeException("请输入正确的日期格式:yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
return localDateTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* string 转为 LocalDate 配置类
|
||||
*
|
||||
* @author 卓大
|
||||
*/
|
||||
@Configuration
|
||||
public static class StringToLocalDate implements Converter<String, LocalDate> {
|
||||
|
||||
@Override
|
||||
public LocalDate convert(String str) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return null;
|
||||
}
|
||||
LocalDate localDate;
|
||||
try {
|
||||
localDate = LocalDateTimeUtil.parseDate(str, DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter());
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new RuntimeException("请输入正确的日期格式:yyyy-MM-dd");
|
||||
}
|
||||
return localDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import com.amazonaws.ClientConfiguration;
|
||||
import com.amazonaws.Protocol;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import lombok.Data;
|
||||
import net.lab1024.sa.common.module.support.file.service.FileStorageCloudServiceImpl;
|
||||
import net.lab1024.sa.common.module.support.file.service.FileStorageLocalServiceImpl;
|
||||
import net.lab1024.sa.common.module.support.file.service.IFileStorageService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 文件上传 配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2019-09-02 23:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
public class FileCloudConfig {
|
||||
|
||||
@Value("${file.storage.cloud.region}")
|
||||
private String region;
|
||||
|
||||
@Value("${file.storage.cloud.endpoint}")
|
||||
private String endpoint;
|
||||
|
||||
@Value("${file.storage.cloud.bucket-name}")
|
||||
private String bucketName;
|
||||
|
||||
@Value("${file.storage.cloud.access-key}")
|
||||
private String accessKey;
|
||||
|
||||
@Value("${file.storage.cloud.secret-key}")
|
||||
private String secretKey;
|
||||
|
||||
@Value("${file.storage.cloud.url.expire}")
|
||||
private Long urlExpire;
|
||||
|
||||
@Value("${file.storage.cloud.url.public}")
|
||||
private String publicUrl;
|
||||
|
||||
/**
|
||||
* 初始化 云oss client 配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "cloud")
|
||||
public AmazonS3 initAmazonS3() {
|
||||
ClientConfiguration clientConfig = new ClientConfiguration();
|
||||
clientConfig.setProtocol(Protocol.HTTPS);
|
||||
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
|
||||
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
|
||||
.withClientConfiguration(clientConfig)
|
||||
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region))
|
||||
.withPathStyleAccessEnabled(false)
|
||||
.build();
|
||||
return s3Client;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "cloud")
|
||||
public IFileStorageService initCloudFileService() {
|
||||
return new FileStorageCloudServiceImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "local")
|
||||
public IFileStorageService initLocalFileService() {
|
||||
return new FileStorageLocalServiceImpl();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import net.lab1024.sa.common.module.support.heartbeat.core.HeartBeatManager;
|
||||
import net.lab1024.sa.common.module.support.heartbeat.core.IHeartBeatRecordHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 心跳配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2018/10/9 18:47
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class HeartBeatConfig {
|
||||
|
||||
/**
|
||||
* 间隔时间
|
||||
*/
|
||||
@Value("${heart-beat.interval-seconds}")
|
||||
private Long intervalSeconds;
|
||||
|
||||
@Autowired
|
||||
private IHeartBeatRecordHandler heartBeatRecordHandler;
|
||||
|
||||
@Bean
|
||||
public HeartBeatManager heartBeatManager() {
|
||||
return new HeartBeatManager(intervalSeconds * 1000L, heartBeatRecordHandler);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import net.lab1024.sa.common.common.interceptor.AbstractInterceptor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* web相关配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021-09-02 20:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class MvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<HandlerInterceptor> interceptorList;
|
||||
|
||||
@Override
|
||||
public void addInterceptors (InterceptorRegistry registry) {
|
||||
if (CollectionUtils.isEmpty(interceptorList)) {
|
||||
return;
|
||||
}
|
||||
interceptorList.forEach(e->{
|
||||
registry.addInterceptor(e).addPathPatterns("/**");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/preview/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/druidMonitor").setViewName("redirect:druid/index.html");
|
||||
registry.addViewController("/swaggerApi").setViewName("redirect:swagger-ui.html");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* mp 插件
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021-09-02 20:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@EnableTransactionManagement
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor paginationInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* yaml 读取配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2022-05-30 21:22:12
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class PostProcessorConfig implements EnvironmentPostProcessor {
|
||||
|
||||
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
this.loadProperty(propertySources);
|
||||
}
|
||||
|
||||
private void loadProperty(MutablePropertySources propertySources) {
|
||||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
||||
try {
|
||||
Resource[] resources = resolver.getResources("classpath*:sa-*.yaml");
|
||||
if (resources.length < 1) {
|
||||
return;
|
||||
}
|
||||
for (Resource resource : resources) {
|
||||
log.info("初始化系统配置:{}", resource.getFilename());
|
||||
List<PropertySource<?>> load = loader.load(resource.getFilename(), resource);
|
||||
load.forEach(propertySources::addLast);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.*;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* redis配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021-09-02 20:21:10
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
//@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Autowired
|
||||
private RedisConnectionFactory factory;
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
jackson2JsonRedisSerializer.setObjectMapper(om);
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
|
||||
template.setConnectionFactory(factory);
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
template.setHashKeySerializer(jackson2JsonRedisSerializer);
|
||||
template.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
template.setDefaultSerializer(new StringRedisSerializer());
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForHash();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
|
||||
return redisTemplate.opsForValue();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForList();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForSet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForZSet();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.lab1024.sa.common.module.support.reload.ReloadCommand;
|
||||
import net.lab1024.sa.common.module.support.reload.core.SmartReloadManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* reload配置
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021/9/1 21:40
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class ReloadConfig {
|
||||
|
||||
/**
|
||||
* 间隔时间
|
||||
*/
|
||||
@Value("${reload.interval-seconds}")
|
||||
private Integer intervalSeconds;
|
||||
|
||||
@Autowired
|
||||
private ReloadCommand reloadCommand;
|
||||
|
||||
@Bean
|
||||
public SmartReloadManager initSmartReloadManager() {
|
||||
// 创建 Reload Manager 调度器
|
||||
return new SmartReloadManager(reloadCommand,intervalSeconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import net.lab1024.sa.common.common.constant.StringConst;
|
||||
import net.lab1024.sa.common.common.util.SmartRequestUtil;
|
||||
import net.lab1024.sa.common.module.support.repeatsubmit.RepeatSubmitAspect;
|
||||
import net.lab1024.sa.common.module.support.repeatsubmit.ticket.RepeatSubmitCaffeineTicket;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 重复提交配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2021/10/9 18:47
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class RepeatSubmitConfig {
|
||||
|
||||
@Bean
|
||||
public RepeatSubmitAspect repeatSubmitAspect() {
|
||||
RepeatSubmitCaffeineTicket caffeineTicket = new RepeatSubmitCaffeineTicket(this::ticket);
|
||||
return new RepeatSubmitAspect(caffeineTicket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指明某个用户的凭证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String ticket(String servletPath) {
|
||||
Long userId = SmartRequestUtil.getRequestUserId();
|
||||
if (null == userId) {
|
||||
return StringConst.EMPTY;
|
||||
}
|
||||
return servletPath + "_" + userId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* http请求配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2022-05-30 21:22:12
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Value("${http.pool.max-total}")
|
||||
private Integer maxTotal;
|
||||
|
||||
@Value("${http.pool.connect-timeout}")
|
||||
private Integer connectTimeout;
|
||||
|
||||
@Value("${http.pool.read-timeout}")
|
||||
private Integer readTimeout;
|
||||
|
||||
@Value("${http.pool.write-timeout}")
|
||||
private Integer writeTimeout;
|
||||
|
||||
@Value("${http.pool.keep-alive}")
|
||||
private Integer keepAlive;
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setRequestFactory(this.clientHttpRequestFactory());
|
||||
List<HttpMessageConverter<?>> messageConverterList = restTemplate.getMessageConverters();
|
||||
messageConverterList.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
|
||||
messageConverterList.addAll(this.converters());
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
public List<HttpMessageConverter<?>> converters() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<>();
|
||||
HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
|
||||
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
|
||||
List<MediaType> fastMediaTypes = new ArrayList<>();
|
||||
fastMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
fastMediaTypes.add(MediaType.APPLICATION_JSON);
|
||||
fastConverter.setSupportedMediaTypes(fastMediaTypes);
|
||||
converters.add(converter);
|
||||
converters.add(fastConverter);
|
||||
return converters;
|
||||
}
|
||||
|
||||
|
||||
public OkHttp3ClientHttpRequestFactory clientHttpRequestFactory() {
|
||||
return new OkHttp3ClientHttpRequestFactory(httpClientBuilder());
|
||||
}
|
||||
|
||||
public OkHttpClient httpClientBuilder() {
|
||||
return new OkHttpClient.Builder()
|
||||
.retryOnConnectionFailure(true)
|
||||
.connectionPool(this.pool())
|
||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
|
||||
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
|
||||
.writeTimeout(writeTimeout, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
public ConnectionPool pool() {
|
||||
return new ConnectionPool(maxTotal, keepAlive, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public X509TrustManager x509TrustManager() {
|
||||
return new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SSLSocketFactory sslSocketFactory() {
|
||||
try {
|
||||
//信任任何链接
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
|
||||
return sslContext.getSocketFactory();
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
import org.springframework.scheduling.config.Task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 定时任务调度 配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2022-05-30 21:22:12
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class ScheduleConfig implements SchedulingConfigurer {
|
||||
|
||||
private ScheduledTaskRegistrar taskRegistrar;
|
||||
|
||||
@Override
|
||||
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||
this.taskRegistrar = taskRegistrar;
|
||||
}
|
||||
|
||||
public String destroy() {
|
||||
List<Task> taskList = new ArrayList<>();
|
||||
taskList.addAll(taskRegistrar.getCronTaskList());
|
||||
taskList.addAll(taskRegistrar.getTriggerTaskList());
|
||||
taskList.addAll(taskRegistrar.getFixedDelayTaskList());
|
||||
taskList.addAll(taskRegistrar.getFixedRateTaskList());
|
||||
|
||||
taskRegistrar.destroy();
|
||||
|
||||
List<String> taskNameList = taskList.stream().map(Task::toString).collect(Collectors.toList());
|
||||
return "已关闭 @Scheduled定时任务:" + taskNameList.size() + "个!";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.lab1024.sa.common.common.constant.RequestHeaderConst;
|
||||
import net.lab1024.sa.common.common.swagger.SwaggerApiModelPropertyEnumPlugin;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import springfox.documentation.RequestHandler;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ParameterBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.service.Parameter;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger.common.SwaggerPluginSupport;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 根据SwaggerTagConst内部类动态生成Swagger group
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2020-03-25 22:54:46
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Slf4j
|
||||
@EnableSwagger2
|
||||
@Configuration
|
||||
@Conditional(SystemEnvironmentConfig.class)
|
||||
public class SwaggerConfig implements EnvironmentAware, BeanDefinitionRegistryPostProcessor {
|
||||
|
||||
/**
|
||||
* 文档标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 文档描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* api版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* service url
|
||||
*/
|
||||
private String teamUrl;
|
||||
|
||||
/**
|
||||
* host
|
||||
*/
|
||||
private String host;
|
||||
|
||||
private String tagClass;
|
||||
|
||||
@Bean
|
||||
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
|
||||
public SwaggerApiModelPropertyEnumPlugin swaggerEnum() {
|
||||
return new SwaggerApiModelPropertyEnumPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.title = environment.getProperty("swagger.title");
|
||||
this.description = environment.getProperty("swagger.description");
|
||||
this.version = environment.getProperty("swagger.version");
|
||||
this.host = environment.getProperty("swagger.host");
|
||||
this.tagClass = environment.getProperty("swagger.tag-class");
|
||||
this.teamUrl = environment.getProperty("swagger.team-url");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
|
||||
Map<String, List<String>> groupMap = this.buildGroup();
|
||||
for (Map.Entry<String, List<String>> entry : groupMap.entrySet()) {
|
||||
String group = entry.getKey();
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Docket.class, () -> this.baseDocket(group, entry.getValue()));
|
||||
BeanDefinition beanDefinition = builder.getRawBeanDefinition();
|
||||
registry.registerBeanDefinition(group + "Api", beanDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private Map<String, List<String>> buildGroup() {
|
||||
Class<?> clazz = Class.forName(tagClass);
|
||||
Class<?>[] innerClazz = clazz.getClasses();
|
||||
Map<String, List<String>> groupMap = new HashMap<>(16);
|
||||
for (Class<?> cls : innerClazz) {
|
||||
String group = cls.getSimpleName();
|
||||
List<String> apiTags = Lists.newArrayList();
|
||||
Field[] fields = cls.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
boolean isFinal = Modifier.isFinal(field.getModifiers());
|
||||
if (isFinal) {
|
||||
apiTags.add(field.get(null).toString());
|
||||
}
|
||||
}
|
||||
groupMap.put(group, apiTags);
|
||||
}
|
||||
return groupMap;
|
||||
}
|
||||
|
||||
private Docket baseDocket(String groupName, List<String> apiTagList) {
|
||||
// 配置全局参数
|
||||
List<Parameter> parameterList = this.generateParameter();
|
||||
|
||||
Docket docket = new Docket(DocumentationType.SWAGGER_2).groupName(groupName)
|
||||
.forCodeGeneration(true)
|
||||
.select()
|
||||
// 过滤规则
|
||||
.apis(this.getControllerPredicate(apiTagList))
|
||||
// 与 过滤规则 controller 包路径 二选一
|
||||
// .apis(RequestHandlerSelectors.basePackage(packAge))
|
||||
.paths(PathSelectors.any())
|
||||
.build().apiInfo(this.apiInfo())
|
||||
.globalOperationParameters(parameterList);
|
||||
if (StringUtils.isNotBlank(host)) {
|
||||
docket = docket.host(host);
|
||||
}
|
||||
return docket;
|
||||
}
|
||||
|
||||
private Predicate<RequestHandler> getControllerPredicate(List<String> apiTagList) {
|
||||
Predicate<RequestHandler> methodPredicate = (input) -> {
|
||||
Api api = null;
|
||||
Optional<Api> apiOptional = input.findControllerAnnotation(Api.class);
|
||||
if (apiOptional.isPresent()) {
|
||||
api = apiOptional.get();
|
||||
}
|
||||
if (api == null) {
|
||||
return false;
|
||||
}
|
||||
List<String> tags = Arrays.asList(api.tags());
|
||||
if (apiTagList.containsAll(tags)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Predicate controllerPredicate = Predicates.or(RequestHandlerSelectors.withClassAnnotation(RestController.class), RequestHandlerSelectors.withClassAnnotation(Controller.class));
|
||||
return Predicates.and(controllerPredicate, methodPredicate);
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder().title(title)
|
||||
.description(description)
|
||||
.version(version)
|
||||
.termsOfServiceUrl(teamUrl)
|
||||
.contact(new Contact("", teamUrl, ""))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成共用请求参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<Parameter> generateParameter() {
|
||||
// 配置全局参数 token
|
||||
Parameter token = new ParameterBuilder().name(RequestHeaderConst.TOKEN)
|
||||
.description("token")
|
||||
.modelRef(new ModelRef("string"))
|
||||
.parameterType("header").defaultValue("1")
|
||||
.required(false)
|
||||
.build();
|
||||
return Lists.newArrayList(token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import net.lab1024.sa.common.common.domain.SystemEnvironment;
|
||||
import net.lab1024.sa.common.common.enumeration.SystemEnvironmentEnum;
|
||||
import net.lab1024.sa.common.common.util.SmartEnumUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* 系统环境
|
||||
*
|
||||
* @Author 1024创新实验室-主任: 卓大
|
||||
* @Date 2021/08/13 18:56
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
public class SystemEnvironmentConfig implements Condition {
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String systemEnvironment;
|
||||
|
||||
@Value("${project.name}")
|
||||
private String projectName;
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
|
||||
String property = conditionContext.getEnvironment().getProperty("spring.profiles.active");
|
||||
return StringUtils.isNotBlank(property) && !SystemEnvironmentEnum.PROD.equalsValue(property);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SystemEnvironment initEnvironment() {
|
||||
SystemEnvironmentEnum currentEnvironment = SmartEnumUtil.getEnumByValue(systemEnvironment, SystemEnvironmentEnum.class);
|
||||
if (currentEnvironment == null) {
|
||||
throw new ExceptionInInitializerError("无法获取当前环境!请在 application.yaml 配置参数:spring.profiles.active");
|
||||
}
|
||||
if (StringUtils.isBlank(projectName)) {
|
||||
throw new ExceptionInInitializerError("无法获取当前项目名称!请在 application.yaml 配置参数:project.name");
|
||||
}
|
||||
return new SystemEnvironment(currentEnvironment == SystemEnvironmentEnum.PROD, projectName, currentEnvironment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package net.lab1024.sa.common.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.lab1024.sa.common.common.annoation.NoNeedLogin;
|
||||
import net.lab1024.sa.common.common.annoation.SaAuth;
|
||||
import net.lab1024.sa.common.common.domain.RequestUrlVO;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* url配置
|
||||
*
|
||||
* @Author 1024创新实验室: 罗伊
|
||||
* @Date 2022-05-30 21:22:12
|
||||
* @Wechat zhuoda1024
|
||||
* @Email lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net )
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class UrlConfig {
|
||||
@Autowired
|
||||
private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||
|
||||
|
||||
/**
|
||||
* 获取每个方法的请求路径
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Map<Method, Set<String>> methodUrlMap() {
|
||||
Map<Method, Set<String>> methodUrlMap = Maps.newHashMap();
|
||||
//获取url与类和方法的对应信息
|
||||
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : map.entrySet()) {
|
||||
RequestMappingInfo requestMappingInfo = entry.getKey();
|
||||
|
||||
Set<String> urls = requestMappingInfo.getPatternsCondition().getPatterns();
|
||||
if (CollectionUtils.isEmpty(urls)) {
|
||||
continue;
|
||||
}
|
||||
HandlerMethod handlerMethod = entry.getValue();
|
||||
methodUrlMap.put(handlerMethod.getMethod(), urls);
|
||||
}
|
||||
return methodUrlMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要进行url权限校验的方法
|
||||
*
|
||||
* @param methodUrlMap
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public List<RequestUrlVO> authUrl(Map<Method, Set<String>> methodUrlMap) {
|
||||
List<RequestUrlVO> authUrlList = Lists.newArrayList();
|
||||
for (Map.Entry<Method, Set<String>> entry : methodUrlMap.entrySet()) {
|
||||
Method method = entry.getKey();
|
||||
SaAuth saAuth = method.getAnnotation(SaAuth.class);
|
||||
if (null == saAuth) {
|
||||
continue;
|
||||
}
|
||||
List<RequestUrlVO> requestUrlList = this.buildRequestUrl(method, entry.getValue());
|
||||
authUrlList.addAll(requestUrlList);
|
||||
}
|
||||
log.info("需要权限校验的URL:{}", authUrlList.stream().map(e -> e.getUrl()).collect(Collectors.toList()));
|
||||
return authUrlList;
|
||||
}
|
||||
|
||||
private List<RequestUrlVO> buildRequestUrl(Method method, Set<String> urlSet) {
|
||||
List<RequestUrlVO> requestUrlList = Lists.newArrayList();
|
||||
if (CollectionUtils.isEmpty(urlSet)) {
|
||||
return requestUrlList;
|
||||
}
|
||||
//url对应的方法名称
|
||||
String className = method.getDeclaringClass().getName();
|
||||
String methodName = method.getName();
|
||||
List<String> list = StrUtil.split(className, ".");
|
||||
String controllerName = list.get(list.size() - 1);
|
||||
String name = controllerName + "." + methodName;
|
||||
//swagger 说明信息
|
||||
String methodComment = null;
|
||||
ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
|
||||
if (apiOperation != null) {
|
||||
methodComment = apiOperation.value();
|
||||
}
|
||||
for (String url : urlSet) {
|
||||
RequestUrlVO requestUrlVO = new RequestUrlVO();
|
||||
requestUrlVO.setUrl(url);
|
||||
requestUrlVO.setName(name);
|
||||
requestUrlVO.setComment(methodComment);
|
||||
requestUrlList.add(requestUrlVO);
|
||||
}
|
||||
return requestUrlList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取无需登录可以匿名访问的url信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public List<String> noNeedLoginUrlList(Map<Method, Set<String>> methodUrlMap) {
|
||||
List<String> noNeedLoginUrlList = Lists.newArrayList();
|
||||
for (Map.Entry<Method, Set<String>> entry : methodUrlMap.entrySet()) {
|
||||
Method method = entry.getKey();
|
||||
NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class);
|
||||
if (null == noNeedLogin) {
|
||||
continue;
|
||||
}
|
||||
noNeedLoginUrlList.addAll(entry.getValue());
|
||||
}
|
||||
log.info("不需要登录的URL:{}", noNeedLoginUrlList);
|
||||
return noNeedLoginUrlList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取忽略的url信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public List<String> ignoreUrlList() {
|
||||
List<String> ignoreUrlList = Lists.newArrayList();
|
||||
ignoreUrlList.add("/swagger-ui.html");
|
||||
ignoreUrlList.add("/swagger-resources/**");
|
||||
ignoreUrlList.add("/webjars/**");
|
||||
ignoreUrlList.add("/druid/**");
|
||||
ignoreUrlList.add("/*/api-docs");
|
||||
return ignoreUrlList;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user