局域网minio配套服务

This commit is contained in:
liangwen 2023-12-16 16:02:50 +08:00
commit c9108cd74a
27 changed files with 4229 additions and 0 deletions

95
README.md Normal file
View File

@ -0,0 +1,95 @@
# Spring-minio
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口非常适合于存储大容量非结构化的数据例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等而一个对象文件可以是任意大小从几kb到最大5T不等。
本项目集成Minio的java客户端SDK对Minio文件服务器进行读写将操作封装为MinioUtil工具直接在项目中可以复用。其操作主要包括
- 上传文件
- 下载文件
- 读取桶列表
- 读取桶中的文件列表
- 删除桶
- 删除文件
### 著作权
#### 匠心巨制,震撼上市
![输入图片说明](https://gitee.com/shenzhanwang/Spring-elastic_search/raw/master/pic/mmexport1680185330486.jpg)
|购买地址|
|--|
|![输入图片说明](https://gitee.com/shenzhanwang/RuoYi-activiti/raw/ruoyi-activiti/pic/%E8%B4%AD%E4%B9%B0.jpg)|
### 专利文章
| | 标题 | 技术领域 |
|---|----|------|
| 1 | [一种基于微服务架构的车联网大数据分析系统](https://mp.weixin.qq.com/s?__biz=Mzg5MjY3OTk0OQ==&mid=2247484096&idx=1&sn=11677bc50cd18e448135319394238e80&chksm=c03b20a2f74ca9b41c7d1c1e60e1407e1530a98b86498822f387da26e551826f8136663b45a0#rd) | 微服务|
| 2 | [一种流式数据场景下Elasticsearch索引的自动化扩容方法](https://mp.weixin.qq.com/s?__biz=Mzg5MjY3OTk0OQ==&mid=2247484167&idx=1&sn=94587b5e196bbda2d6cc4b976b03d0c7&chksm=c03b2165f74ca873b77380a23c4e06b71adf6ffc40634440f467fb71c20aa4cc2fe72a5d65a9#rd) | 搜索引擎 |
| 3 | [大数据钻取分析方法、装置、设备及存储介质](https://mp.weixin.qq.com/s?__biz=Mzg5MjY3OTk0OQ==&mid=2247484385&idx=1&sn=6fe4a4ac34badd91db39b4cc042a3f18&chksm=c03b2183f74ca89508333f3d5c8330aa32248eda86e4cf7657a5a293e1bf9d49888fe78b1072#rd) | 大数据分析 |
| 4 | [一种基于工作流引擎的自动化办公方法和系统](https://mp.weixin.qq.com/s?__biz=Mzg5MjY3OTk0OQ==&mid=2247484895&idx=1&sn=1094f0b9abef603e8126dea68db75cca&chksm=c03b27bdf74caeab50d56ac110b9ab0d36bc9b9069e311083a5c4295ab03ee4b0595a00a3ba2#rd) | 工作流引擎 |
### 视频教程
|<div align=left><a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg5MjY3OTk0OQ==&action=getalbum&album_id=2862983682029043714#wechat_redirect" target="_blank">Elasticsearch数据搜索与分析实战演练</a></div> |
|--|
|<div align=left><a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg5MjY3OTk0OQ==&action=getalbum&album_id=2790222720155451398#wechat_redirect" target="_blank">RuoYi-activiti开发指南</a></div> |
### 附录中央技术储备仓库Central Technique Reserve Repository
#### 基础篇:职业化从做好OA系统开始
1. [Spring boot整合Mybatis实现增删改查支持多数据源](https://gitee.com/shenzhanwang/SSM)![输入图片说明](https://img.shields.io/badge/-%E7%B2%BE%E5%93%81-orange.svg "在这里输入图片标题")
2. [Spring,SpringMVC和Hibernate的整合实现增删改查](https://gitee.com/shenzhanwang/SSH)
3. [Spring boot整合activiti工作流引擎实现OA开发](https://gitee.com/shenzhanwang/Spring-activiti)![输入图片说明](https://img.shields.io/badge/-%E6%8B%9B%E7%89%8C-yellow.svg)
4. [Ruoyi-boot集成工作流引擎Flowable实例](https://gitee.com/shenzhanwang/Ruoyi-flowable)![输入图片说明](https://img.shields.io/badge/-%E6%8B%9B%E7%89%8C-yellow.svg)
5. [Spring发布与调用REST风格的WebService](https://gitee.com/shenzhanwang/Spring-REST)
6. [Spring boot整合Axis调用SOAP风格的web服务](https://gitee.com/shenzhanwang/Spring-axis)
7. [Spring boot整合Apache Shiro实现RBAC权限控制](https://gitee.com/shenzhanwang/Spring-shiro)
8. [使用Spring security实现RBAC权限控制](https://gitee.com/shenzhanwang/spring-security-demo)
#### 中级篇:中间件的各种姿势
9. [Spring boot整合mongoDB文档数据库实现增删改查](https://gitee.com/shenzhanwang/Spring-mongoDB)
10. [Spring连接Redis实现缓存](https://gitee.com/shenzhanwang/Spring-redis)
11. [Spring连接图存数据库Neo4j实现增删改查](https://gitee.com/shenzhanwang/Spring-neo4j)
12. Spring boot整合列存数据库hbase实现增删改查
13. [Spring平台整合消息队列ActiveMQ实现发布订阅、生产者消费者模型JMS](https://gitee.com/shenzhanwang/Spring-activeMQ)
14. [Spring boot整合消息队列RabbitMQ实现四种消息模式AMQP](https://gitee.com/shenzhanwang/Spring-rabbitMQ)
15. Spring boot整合kafka 2.1.0实现大数据消息管道
16. [Spring boot整合websocket实现即时通讯](https://gitee.com/shenzhanwang/Spring-websocket)![输入图片说明](https://img.shields.io/badge/-%E7%B2%BE%E5%93%81-orange.svg "在这里输入图片标题")
17. [Spring security整合oauth2实现token认证](https://gitee.com/shenzhanwang/Spring-security-oauth2)
18. [Spring boot整合MinIO客户端实现文件管理](https://gitee.com/shenzhanwang/Spring-minio)
19. 23种设计模式源码、注释、使用场景
20. [使用ETL工具Kettle的实例](https://gitee.com/shenzhanwang/Kettle-demo)
21. Git指南和分支管理策略
22. 使用数据仓库进行OLAP数据分析Mysql+Kettle+Zeppelin
#### 高级篇:分布式系统和大数据开发
23. [zookeeper原理、架构、使用场景和可视化](https://gitee.com/shenzhanwang/zookeeper-practice)
24. Spring boot整合Apache dubbo v2.7.5实现分布式服务治理SOA架构 ![输入图片说明](https://img.shields.io/badge/-%E7%B2%BE%E5%93%81-orange.svg "在这里输入图片标题")
> 包含组件Spring boot v2.2.2+Dubbo v2.7.5+Nacos v1.1.1
<a href="https://images.gitee.com/uploads/images/2020/0114/084731_fd0b7a82_1110335.gif" target="_blank">效果图</a>
25. 使用Spring Cloud Alibaba v2.2.7实现微服务架构MSA架构![输入图片说明](https://img.shields.io/badge/-%E6%8B%9B%E7%89%8C-yellow.svg)
> 包含组件Nacos+Feign+Gateway+Ribbon+Sentinel+Zipkin
<a href="https://images.gitee.com/uploads/images/2020/0106/201827_ac61db63_1110335.gif" target="_blank">效果图</a>
26. 使用jenkins+centos+git+maven搭建持续集成环境自动化部署分布式服务
27. 使用docker+compose+jenkins+gitlab+spring cloud实现微服务的编排、持续集成和动态扩容
28. 使用Spark进行分布式计算
- Spark SQL做离线计算
- Spark Streaming做实时计算
- Structured Streaming做实时计算
29. 使用Flink实现流批一体化的分布式计算
30. 搭建高可用nginx集群和Tomcat负载均衡
31. 使用mycat实现Mysql数据库的主从复制、读写分离、分表分库、负载均衡和高可用
32. [《Elasticsearch数据搜索与分析实战》源码](https://gitee.com/shenzhanwang/Spring-elastic_search) ![输入图片说明](https://img.shields.io/badge/-%E6%8B%9B%E7%89%8C-yellow.svg "在这里输入图片标题")
#### 特别篇:分布式事务和并发控制
33. 基于可靠消息最终一致性实现分布式事务activeMQ
34. Spring boot dubbo整合seata实现分布式事务![输入图片说明](https://img.shields.io/badge/-%E7%B2%BE%E5%93%81-orange.svg "在这里输入图片标题")
> 包含组件nacos v2.0.2 + seata v1.4.2 +spring boot dubbo v2.7.5
<a href="https://images.gitee.com/uploads/images/2020/0119/112233_62a33a77_1110335.gif" target="_blank">效果图</a>
35. Spring cloud alibaba v2.2.7整合seata实现分布式事务 ![输入图片说明](https://img.shields.io/badge/-%E7%B2%BE%E5%93%81-orange.svg "在这里输入图片标题")
> 包含组件nacos v2.0.2 + seata v1.4.2 +spring cloud alibaba v2.2.7
<a href="https://images.gitee.com/uploads/images/2020/0119/134408_ee14a016_1110335.gif" target="_blank">效果图</a>
36. 并发控制:数据库锁机制和事务隔离级别的实现![输入图片说明](https://img.shields.io/badge/-%E7%B2%BE%E5%93%81-orange.svg "在这里输入图片标题")
37. 并发控制使用redission实现分布式锁
38. 并发控制使用zookeeper实现分布式锁
39. 并发控制Java多线程编程实例
40. 并发控制使用netty实现高性能NIO通信
### 关注微信公众号获取更多技术文章和源码
![输入图片说明](https://gitee.com/shenzhanwang/Spring-elastic_search/raw/master/pic/qrcode_for_gh_4c2318bb0f7f_258.jpg)

137
pom.xml Normal file
View File

@ -0,0 +1,137 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hb</groupId>
<artifactId>hb-minio</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.6.RELEASE</version>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.6.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.6.RELEASE</version>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.0</version>
</dependency>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
<version>2.1.6.RELEASE</version>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
<!-- Jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
<build>
<finalName>hb-minio</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.6.RELEASE</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- 指定maven编译方式为jdk1.8版本 -->
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,14 @@
package com.hb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,36 @@
package com.hb;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.hb.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("hb minio api文档")
.description("minio操作API文档")
//.termsOfServiceUrl("http://gitee.com/shenzhanwang/projects")
.version("1.0")
.build();
}
}

View File

@ -0,0 +1,33 @@
package com.hb.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
//重写父类提供的跨域请求处理的接口
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET", "POST", "PUT", "DELETE")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息因为跨域访问默认不能获取全部头部信息
.exposedHeaders("token");
}
};
}
}

View File

@ -0,0 +1,49 @@
package com.hb.config;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
/**
* Redis使用FastJson序列化
*
* @author ruoyi
*/
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz)
{
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException
{
if (t == null)
{
return new byte[0];
}
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length <= 0)
{
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
}
}

View File

@ -0,0 +1,30 @@
package com.hb.config;
import com.hb.interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
/**
* @Auther: shaoming
* @Date: 2021/1/8 14:11
* @Description: 注册拦截器配置类
*/
@Configuration//表名这是springboot的配置类
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//定义排除swagger访问的路径配置
String[] swaggerExcludes=new String[]{"/swagger-ui.html","/swagger-resources/**","/webjars/**", "/getPicture"};
registry.addInterceptor(new MyInterceptor())
// addPathPatterns 用于添加拦截规则
.addPathPatterns("/**")
.excludePathPatterns(swaggerExcludes);
WebMvcConfigurer.super.addInterceptors(registry);
}
}

View File

@ -0,0 +1,75 @@
package com.hb.config;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
@Configuration
public class MinioConfig {
@Value("${minio.url}")
private String url;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
/*@Bean
public MinioClient getMinioClient() {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
return minioClient;
}*/
@Bean
public MinioClient minioClient(){
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// Do nothing (trust any client certificate)
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
// Do nothing (trust any server certificate)
}
}
};
// Install the all-trusting trust manager
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (Exception e) {
e.printStackTrace();
}
// Create a custom OkHttpClient that trusts all certificates
OkHttpClient customHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
.hostnameVerifier((hostname, session) -> true)
.build();
// Set the custom SSLContext for MinioClient
return MinioClient.builder()
.endpoint(url)
.credentials(accessKey, secretKey)
.httpClient(customHttpClient)
.build();
}
}

View File

@ -0,0 +1,69 @@
package com.hb.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置
*
* @author ruoyi
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
@Bean
public DefaultRedisScript<Long> limitScript()
{
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(limitScriptText());
redisScript.setResultType(Long.class);
return redisScript;
}
/**
* 限流脚本
*/
private String limitScriptText()
{
return "local key = KEYS[1]\n" +
"local count = tonumber(ARGV[1])\n" +
"local time = tonumber(ARGV[2])\n" +
"local current = redis.call('get', key);\n" +
"if current and tonumber(current) > count then\n" +
" return tonumber(current);\n" +
"end\n" +
"current = redis.call('incr', key)\n" +
"if tonumber(current) == 1 then\n" +
" redis.call('expire', key, time)\n" +
"end\n" +
"return tonumber(current);";
}
}

View File

@ -0,0 +1,341 @@
package com.hb.constant;
//import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
* @author ruoyi
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* www主域
*/
public static final String WWW = "www.";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 通用成功标识
*/
public static final String SUCCESS = "0";
/**
* 通用失败标识
*/
public static final String FAIL = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
//MQ相关---------------------------------------------------------
/**
* 限流 redis key
*/
//public static final String DEVICE_HEART_KEY = "device:heart:";
/**
* 设备状态 redis key alarm存储用 暂时未用上
*/
public static final String DEVICE_STATE_KEY = "device:state:";
/**
* 任务 -> 状态key
*/
//public static final String TASK_STATUS_KEY = "task:status:";
/**
* 打印文件 redis key
*/
//public static final String TASK_JOBINFO_KEY = "task:jobInfo:";
/**
* 用户登录 tel key
*/
public static final String LOGIN_TOKEN_ROLE_KEY = "login_token_role:";
/**
* 用户登录 语言
*/
// public static final String LOGIN_LANG_KEY = "login_lang:";
/**
* 设备 -> 权限key
*/
public static final String DEVICE_ROLE_KEY = "device:role:";
/**
* 用户 -> 消息内容
*/
public static final String USER_SEND_MSG_KEY = "user:send_msg:";
/**
* 用户 -> 消息内容
*/
public static final String USER_WX_MSG_KEY = "user:wx_msg:";
/**
* 设备 -> 权限key 机器id
*/
public static final String MACHINE_ID = "machine_id";
/**
* 设备 -> 权限key 权限Key
*/
public static final String ROLE_KEY = "role_key";
public static final String DEVICE_CODE = "device_code";
public static final String UUID = "uuid";
public static final String SUPER_ADMIN = "admin";
//---------------------------------------------------------
/**
* 验证码有效期分钟
*/
public static final Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
public static final String TOKEN = "token";
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
/**
* 用户ID
*/
public static final String JWT_USERID = "userid";
/**
* 用户名称
*/
//public static final String JWT_USERNAME = Claims.SUBJECT;
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
/**
* 大屏映射路径 前缀
*/
public static final String GOVIEW_PREFIX = "/goview";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi:";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/**
* 定时任务白名单配置仅允许访问的包名如其他需要可以自行添加
*/
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
/**
* 用户语言
*/
public static final String USER_LANGUAGE_KEY = "user:language:";
/**
* 首页大屏地址参数key
*/
public static final String MAIN_PAGE_URL_KEY = "mainPage.URL.";
/**
* 评估子流程
*/
public static final String ASSESS_INSTANCE_KEY = "process:instance:assess:";
/**
* 前处理子流程
*/
public static final String OPTIMIZE_INSTANCE_KEY = "process:instance:optimize:";
/**
* 设备视频推流
*/
public static final String VIDEO_STREAM_STATUS_KEY = "video:stream:status:";
/**
* 排版模型
*/
public static final String COMPOSE_INSTANCE_KEY = "process:instance:compose:";
/**
* 打印仿真
*/
public static final String PRINT_SIMULATE_INSTANCE_KEY = "process:instance:printSimulate:";
/**
* 打印仿真零件组合
*/
public static final String PRINT_SIMULATE_CHILD_INSTANCE_KEY = "process:instance:child:printSimulate:";
/**
* 切片/路径规划子项
*/
public static final String SLICE_PATH_PLANNING_CHILD_INSTANCE_KEY = "process:instance:child:slicePathPlanning:";
/**
* 切片/路径规划
*/
public static final String SLICE_PATH_PLANNING_INSTANCE_KEY = "process:instance:slicePathPlanning:";
/**
* 在线排单
*/
public static final String ONLINE_ORDER_CHILD_INSTANCE_KEY = "process:instance:child:onlineOrder:";
/**
* 在线排单
*/
public static final String ONLINE_ORDER_INSTANCE_KEY = "process:instance:onlineOrder:";
/**
* 排单确认子项
*/
public static final String SCHEDULE_CONFIRM_CHILD_INSTANCE_KEY = "process:instance:child:scheduleConfirm:";
/**
* 排单确认
*/
public static final String SCHEDULE_CONFIRM_INSTANCE_KEY = "process:instance:scheduleConfirm:";
/**
* 打印任务子项
*/
public static final String PRINT_TASK_CHILD_INSTANCE_KEY = "process:instance:child:printTask:";
/**
* 打印任务
*/
public static final String PRINT_TASK_INSTANCE_KEY = "process:instance:printTask:";
/**
* 取件任务子项
*/
public static final String COLLECT_PART_CHILD_INSTANCE_KEY = "process:instance:child:collectPart:";
/**
* 取件确认任务
*/
public static final String COLLECT_PART_INSTANCE_KEY = "process:instance:collectPart:";
/**
* 取件确认任务子项
*/
public static final String COLLECT_CONFIREM_CHILD_INSTANCE_KEY = "process:instance:child:collectConfirm:";
/**
* 取件确认任务
*/
public static final String COLLECT_CONFIREM_INSTANCE_KEY = "process:instance:collectConfirm:";
/**
* 打印质检任务子项 PrintInspection
*/
public static final String PRINT_INSPECTION_CHILD_INSTANCE_KEY = "process:instance:child:printInspection:";
/**
* 打印质检任务 PrintInspection
*/
public static final String PRINT_INSPECTION_INSTANCE_KEY = "process:instance:printInspection:";
/**
* 成品入库任务子项 warehouse
*/
public static final String WAREHOUSE_CHILD_INSTANCE_KEY = "process:instance:child:warehouse:";
/**
* 成品入库任务
*/
public static final String WAREHOUSE_INSTANCE_KEY = "process:instance:warehouse:";
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
public static final String VALIDATE_URL = "https://web.hb3dp.com:8090/wx/api/userInfo";
}

View File

@ -0,0 +1,94 @@
package com.hb.constant;
/**
* 返回状态码
*
* @author ruoyi
*/
public class HttpStatus
{
/**
* 操作成功
*/
public static final int SUCCESS = 200;
/**
* 对象创建成功
*/
public static final int CREATED = 201;
/**
* 请求已经被接受
*/
public static final int ACCEPTED = 202;
/**
* 操作已经执行成功但是没有返回数据
*/
public static final int NO_CONTENT = 204;
/**
* 资源已被移除
*/
public static final int MOVED_PERM = 301;
/**
* 重定向
*/
public static final int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
public static final int NOT_MODIFIED = 304;
/**
* 参数列表错误缺少格式不匹配
*/
public static final int BAD_REQUEST = 400;
/**
* 未授权
*/
public static final int UNAUTHORIZED = 401;
/**
* 访问受限授权过期
*/
public static final int FORBIDDEN = 403;
/**
* 资源服务未找到
*/
public static final int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
public static final int BAD_METHOD = 405;
/**
* 资源冲突或者资源被锁
*/
public static final int CONFLICT = 409;
/**
* 不支持的数据媒体类型
*/
public static final int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
public static final int ERROR = 500;
/**
* 接口未实现
*/
public static final int NOT_IMPLEMENTED = 501;
/**
* 系统警告消息
*/
public static final int WARN = 601;
}

View File

@ -0,0 +1,301 @@
package com.hb.controller;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import com.hb.util.DateUtil;
import com.hb.util.ServletUtils;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.hb.domain.AjaxResult;
import com.hb.util.MinioUtil;
@Api(tags = "Minio操作接口")
@RestController
public class MinioController {
@Autowired
MinioUtil minioUtil;
/*@ApiOperation("列出所有的桶")
@RequestMapping(value = "/listBuckets", method = RequestMethod.GET)
@ResponseBody
public AjaxResult listBuckets() throws Exception {
return AjaxResult.success(minioUtil.listBuckets());
}*/
@ApiOperation("上传一个文件")
@ApiImplicitParams({
@ApiImplicitParam(name = "uploadfile", value = "MultipartFile文件对象", dataType="__file", paramType="form", required = true),
@ApiImplicitParam(name = "bucket", value = "桶名称", required = true),
@ApiImplicitParam(name = "objectName", value = "文件夹路径20231215/002938", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
@ResponseBody
public AjaxResult fileupload(@RequestParam MultipartFile uploadfile, @RequestParam String bucket,
@RequestParam(required = false) String objectName) throws Exception {
minioUtil.createBucket(bucket);
if (objectName != null) {
minioUtil.uploadFile(uploadfile.getInputStream(), bucket, objectName + "/" + uploadfile.getOriginalFilename());
} else {
minioUtil.uploadFile(uploadfile.getInputStream(), bucket, uploadfile.getOriginalFilename());
}
return AjaxResult.success();
}
@ApiOperation("上传一个文件2")
@ApiImplicitParams({
@ApiImplicitParam(name = "uploadfile", value = "MultipartFile文件对象", dataType="__file", paramType="form", required = true),
@ApiImplicitParam(name = "bucket", value = "桶名称", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@RequestMapping(value = "/uploadfile2", method = RequestMethod.POST)
@ResponseBody
public AjaxResult fileupload2(@RequestParam MultipartFile uploadfile, @RequestParam String bucket) throws Exception {
minioUtil.createBucket(bucket);
String fileDir = buildDir();
String fileDirName = buildDirName(fileDir, uploadfile.getOriginalFilename());
minioUtil.uploadFile2(uploadfile, bucket, fileDirName);
return AjaxResult.success();
}
@ApiOperation("递归列出一个桶中的所有文件和目录")
@ApiImplicitParams({
@ApiImplicitParam(name = "bucket", value = "桶名称", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@RequestMapping(value = "/listFiles", method = RequestMethod.GET)
@ResponseBody
public AjaxResult listFiles(@RequestParam String bucket) throws Exception {
return AjaxResult.success("200", minioUtil.listFiles(bucket));
}
@ApiOperation("下载一个文件")
@ApiImplicitParams({
@ApiImplicitParam(name = "bucket", value = "桶名称", required = true),
@ApiImplicitParam(name = "objectName", value = "文件全路径20231215/002938/gh_03ace048af5d_344 (1) (2).jpg", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
@ResponseBody
public void downloadFile(@RequestParam String bucket, @RequestParam String objectName,
HttpServletResponse response) throws Exception {
InputStream stream = minioUtil.download(bucket, objectName);
ServletOutputStream output = response.getOutputStream();
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
IOUtils.copy(stream, output);
}
@ApiOperation("下载一个文件")
@ApiImplicitParams({
@ApiImplicitParam(name = "bucket", value = "桶名称", required = true),
@ApiImplicitParam(name = "objectName", value = "文件全路径20231215/002938/gh_03ace048af5d_344 (1) (2).jpg", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@RequestMapping(value = "/getPicture", method = RequestMethod.GET)
@ResponseBody
public void getLocalPicture(@RequestParam String bucket, @RequestParam String objectName,
HttpServletResponse response) {
try {
String contentType = minioUtil.getContenType(bucket, objectName);
// 判断文件类型是否为图片
boolean isImage = contentType != null && contentType.startsWith("image/");
if (!isImage) {
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error("文件类型不是图片,无法查看!")));
} else {
InputStream stream = minioUtil.download(bucket, objectName);
ServletOutputStream output = response.getOutputStream();
//response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8"));
//response.setContentType("application/octet-stream");
//response.setCharacterEncoding("UTF-8");
IOUtils.copy(stream, output);
}
}catch (Exception e) {
e.printStackTrace();
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(e.getMessage())));
}
}
@ApiOperation("删除一个文件")
@RequestMapping(value = "/deleteFile", method = RequestMethod.GET)
@ResponseBody
public AjaxResult deleteFile(@RequestParam String bucket, @RequestParam String objectName) throws Exception {
minioUtil.deleteObject(bucket, objectName);
return AjaxResult.success();
}
@ApiOperation(value = "单个直传", notes = "单文件生成签名地址,前端直接传")
@ApiImplicitParams({
@ApiImplicitParam(name = "fileName", value = "文件名称", required = true),
@ApiImplicitParam(name = "bucket", value = "桶名称", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@ApiResponses(
{
@ApiResponse(code = 200, message = "生成地址成功"),
@ApiResponse(code = 1001, message = "生成失败,文件名不能为空"),
@ApiResponse(code = 1002, message = "生成失败,桶名不能为空"),
@ApiResponse(code = 1003, message = "生成地址出错"),
}
)
@PostMapping("/buildOnePutURL")
@ResponseBody
public AjaxResult buildOnePutURL(String fileName, String bucket) {
AjaxResult ajaxResult = new AjaxResult();
if (StringUtils.isEmpty(fileName)) {
ajaxResult.put("code", 1001);
ajaxResult.put("msg", "生成失败,文件名不能为空");
return ajaxResult;
}
if (StringUtils.isEmpty(bucket)) {
ajaxResult.put("code", 1002);
ajaxResult.put("msg", "生成失败,桶名不能为空");
return ajaxResult;
}
try {
String fileDir = buildDir(); //目录
String fileCode = UUID.randomUUID().toString(); //文件编号,放在数据库用
//JSONObject jsonData = getOneURL(0, fileCode, fileDir, fileName, bucket);
String fileDirName = buildDirName(fileDir, fileName);
minioUtil.createBucket(bucket);
String putURL = minioUtil.getOneURL(fileDirName, bucket);
JSONObject jsonData = new JSONObject();
jsonData.put("index", 0);
jsonData.put("fileCode", fileCode);
jsonData.put("fileDir", fileDir);
jsonData.put("fileName", fileName);
jsonData.put("fileDirName", fileDirName);
jsonData.put("putURL", putURL);
if (jsonData == null) {
ajaxResult.put("code", 1003);
ajaxResult.put("msg", "生成失败,Minio操作失败");
return ajaxResult;
}
ajaxResult.put("code", 200);
ajaxResult.put("msg", "success");
ajaxResult.put("data", jsonData);
} catch (Exception e) {
e.printStackTrace();
ajaxResult.put("code", 500);
ajaxResult.put("msg", "生成失败");
}
return ajaxResult;
}
/*@ApiOperation("删除一个桶")
@RequestMapping(value = "/deleteBucket", method = RequestMethod.GET)
@ResponseBody
public AjaxResult deleteBucket(@RequestParam String bucket) throws Exception {
minioUtil.deleteBucket(bucket);
return AjaxResult.success();
}*/
@ApiOperation(value = "生成文件预览临时url", notes = "生成文件预览临时url有效期7天")
@ApiImplicitParams({
@ApiImplicitParam(name = "fileDirName", value = "文件全路径", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@ApiResponses(
{
@ApiResponse(code = 200, message = "生成成功返回文件预览url"),
@ApiResponse(code = 1001, message = "文件全路径不能为空"),
@ApiResponse(code = 1002, message = "桶名不能为空"),
@ApiResponse(code = 500, message = "生成失败"),
}
)
@PostMapping("/getMinioURL")
@ResponseBody
public AjaxResult getMinioURL(String bucket, String fileDirName) {
AjaxResult ajaxResult = new AjaxResult();
if (StringUtils.isEmpty(fileDirName)) {
ajaxResult.put("code", 1001);
ajaxResult.put("msg", "生成失败,文件全路径不能为空");
return ajaxResult;
}
if (StringUtils.isEmpty(bucket)) {
ajaxResult.put("code", 1002);
ajaxResult.put("msg", "生成失败,桶名不能为空");
return ajaxResult;
}
try {
String url = minioUtil.getMinioURL(bucket, fileDirName);
ajaxResult.put("code", 200);
ajaxResult.put("msg", "success");
ajaxResult.put("url", url);
} catch (Exception e) {
e.printStackTrace();
ajaxResult.put("code", 500);
ajaxResult.put("msg", "success");
}
return ajaxResult;
}
@ApiOperation(value = "生成多个文件预览临时url", notes = "生成多个文件预览临时url有效期7天")
@ApiImplicitParams({
@ApiImplicitParam(name = "fileDirNames", value = "文件全路径数组", required = true),
@ApiImplicitParam(paramType = "header", name = "Authorization", value = "Bearer YOUR_TOKEN_HERE", required = true)
})
@ApiResponses(
{
@ApiResponse(code = 200, message = "生成成功返回文件预览url"),
@ApiResponse(code = 1001, message = "文件全路径不能为空"),
@ApiResponse(code = 1002, message = "文件全路径不能为空"),
@ApiResponse(code = 500, message = "生成失败"),
}
)
@PostMapping("/getMinioURLs")
public AjaxResult getMinioURLs(String bucket, String[] fileDirNames) {
AjaxResult ajaxResult = new AjaxResult();
if (fileDirNames == null || (fileDirNames != null && fileDirNames.length <= 0)) {
ajaxResult.put("code", 1001);
ajaxResult.put("msg", "文件全路径不能为空");
return ajaxResult;
}
if (StringUtils.isEmpty(bucket)) {
ajaxResult.put("code", 1002);
ajaxResult.put("msg", "生成失败,桶名不能为空");
return ajaxResult;
}
try {
//List<String> urlList = minioUtil.getMinioURLs(bucket, fileDirNames);
List<String> urlList = new ArrayList<>();
for (String fileDirName : fileDirNames) {
String url = minioUtil.getMinioURL(bucket, fileDirName);
urlList.add(url);
}
ajaxResult.put("code", 200);
ajaxResult.put("msg", "success");
ajaxResult.put("urlList", urlList);
} catch (Exception e) {
e.printStackTrace();
ajaxResult.put("code", 500);
ajaxResult.put("msg", "success");
}
return ajaxResult;
}
private String buildDir() {
return DateUtil.getDateTime("yyyyMMdd/HHmmss");
}
public String buildDirName(String fileDir, String fileName) {
return String.format("%s/%s", fileDir, fileName);
}
}

View File

@ -0,0 +1,193 @@
package com.hb.domain;
import java.util.HashMap;
/**
*
*/
public class AjaxResult extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/** 状态码 */
public static final String CODE_TAG = "code";
/** 返回内容 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/**
* 状态类型
*/
public enum Type
{
/** 成功 */
SUCCESS(200),
/** 警告 */
WARN(301),
/** 错误 */
ERROR(500);
private final int value;
Type(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* 初始化一个新创建的 AjaxResult 对象使其表示一个空消息
*/
public AjaxResult()
{
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param type 状态类型
* @param msg 返回内容
*/
public AjaxResult(Type type, String msg)
{
super.put(CODE_TAG, type.value);
super.put(MSG_TAG, msg);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param type 状态类型
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResult(Type type, String msg, Object data)
{
super.put(CODE_TAG, type.value);
super.put(MSG_TAG, msg);
if (data != null)
{
super.put(DATA_TAG, data);
}
}
/**
* 方便链式调用
*
* @param key
* @param value
* @return 数据对象
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static AjaxResult success(Object data)
{
return AjaxResult.success("操作成功", data);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResult success(String msg)
{
return AjaxResult.success(msg, null);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResult success(String msg, Object data)
{
return new AjaxResult(Type.SUCCESS, msg, data);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult warn(String msg)
{
return AjaxResult.warn(msg, null);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult warn(String msg, Object data)
{
return new AjaxResult(Type.WARN, msg, data);
}
/**
* 返回错误消息
*
* @return
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(String msg)
{
return AjaxResult.error(msg, null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult error(String msg, Object data)
{
return new AjaxResult(Type.ERROR, msg, data);
}
}

View File

@ -0,0 +1,24 @@
package com.hb.domain;
public class Fileinfo {
String filename;
Boolean directory;
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public Boolean getDirectory() {
return directory;
}
public void setDirectory(Boolean directory) {
this.directory = directory;
}
}

View File

@ -0,0 +1,49 @@
package com.hb.interceptor;
import com.hb.constant.Constants;
import com.hb.constant.HttpStatus;
import com.hb.domain.AjaxResult;
import com.hb.util.HttpUtils;
import com.hb.util.ServletUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//在请求处理之前进行拦截处理
//System.out.println("测试拦截器------preHandle------" + request.getRequestURL());
//返回true表示继续执行请求返回false表示停止执行请求;
String token = request.getHeader("Authorization");
if (StringUtils.hasText(token)){
//验证token的合法性根据自己的业务逻辑补充
String result = HttpUtils.sendPost(Constants.VALIDATE_URL, "token=" + token);
if (!StringUtils.isEmpty(result)) {
JSONObject resultJSON = JSONObject.parseObject(result);
int code = resultJSON.getIntValue("code");
if (code == 200) {
return true;
}
}
}
//没有token说明没有登录
//使用response设置响应给前端的信息根据自己的业务需求
int code = HttpStatus.UNAUTHORIZED;
String msg = com.hb.util.StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(msg)));
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//在请求处理之后进行拦截处理
//System.out.println("测试拦截器------postHandle");
}
}

View File

@ -0,0 +1,9 @@
package com.hb.service;
public interface MinIOService {
}

View File

@ -0,0 +1,52 @@
package com.hb.service.impl;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.hb.service.MinIOService;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.errors.MinioException;
@Service("minIOService")
public class MinIOServiceImpl implements MinIOService {
private static final Logger LOG = LoggerFactory.getLogger(MinIOServiceImpl.class);
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
try {
// Create a minioClient with the MinIO server playground, its access
// key and secret key.
MinioClient minioClient = MinioClient.builder().endpoint("http://192.168.7.250:9000")
.credentials("minioadmin", "minioadmin").build();
// Make 'asiatrip' bucket if not exist.
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("abc").build());
if (!found) {
// Make a new bucket called 'asiatrip'.
minioClient.makeBucket(MakeBucketArgs.builder().bucket("abc").build());
} else {
System.out.println("Bucket 'abc' already exists.");
}
// Upload '/home/user/Photos/asiaphotos.zip' as object name
// 'asiaphotos-2015.zip' to bucket
// 'asiatrip'.
// minioClient.uploadObject(UploadObjectArgs.builder().bucket("abc").object("1.txt")
// .filename("D:\\实时监控数据.txt").build());
// System.out.println("'实时监控数据.txt' is successfully uploaded as "
// + "object '1.txt' to bucket 'abc'.");
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
System.out.println("HTTP trace: " + e.httpTrace());
}
}
}

View File

@ -0,0 +1,85 @@
package com.hb.util;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 字符集工具类
*
* @author ruoyi
*/
public class CharsetKit
{
/** ISO-8859-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** UTF-8 */
public static final String UTF_8 = "UTF-8";
/** GBK */
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset)
{
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset)
{
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset)
{
if (null == srcCharset)
{
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset)
{
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
{
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset()
{
return Charset.defaultCharset().name();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
package com.hb.util;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateUtil {
public static String buildAlarmMsgCode() {
return "A" + getDateTime("yyyyMMddHHmmssSSS");
}
public static String buildNoticeMsgCode() {
return "N" + getDateTime("yyyyMMddHHmmssSSS");
}
public static String getDateTime(String timeFmt) {
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFmt, Locale.CHINA);
return dateTime.format(formatter);
}
public static String getDateTime() {
return getDateTime("yyyy-MM-dd HH:mm:ss");
}
}

View File

@ -0,0 +1,265 @@
package com.hb.util;
import com.hb.constant.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.*;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
/**
* 通用http发送方法
*
* @author ruoyi
*/
public class HttpUtils
{
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url)
{
return sendGet(url, StringUtils.EMPTY);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param)
{
return sendGet(url, param, Constants.UTF8);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @param contentType 编码类型
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try
{
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (in != null)
{
in.close();
}
}
catch (Exception ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
{
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try
{
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
public static String sendSSLPost(String url, String param)
{
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
try
{
log.info("sendSSLPost - {}", urlNameString);
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
URL console = new URL(urlNameString);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String ret = "";
while ((ret = br.readLine()) != null)
{
if (ret != null && !"".equals(ret.trim()))
{
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
}
}
log.info("recv - {}", result);
conn.disconnect();
br.close();
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
}
return result.toString();
}
private static class TrustAnyTrustManager implements X509TrustManager
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[] {};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier
{
@Override
public boolean verify(String hostname, SSLSession session)
{
return true;
}
}
}

View File

@ -0,0 +1,194 @@
package com.hb.util;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import io.minio.*;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import com.hb.domain.Fileinfo;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.web.multipart.MultipartFile;
@Component
public class MinioUtil {
@Autowired
private MinioClient minioClient;
@Autowired
private RedisTemplate redisTemplate;
/**
* 创建一个桶
*/
public void createBucket(String bucket) throws Exception {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
}
}
/**
* 上传一个文件
*/
public void uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
.stream(stream, -1, 10485760).build());
}
/**
* 列出所有的桶
*/
public List<String> listBuckets() throws Exception {
List<Bucket> list = minioClient.listBuckets();
List<String> names = new ArrayList<>();
list.forEach(b -> {
names.add(b.name());
});
return names;
}
/**
* 列出一个桶中的所有文件和目录
*/
public List<Fileinfo> listFiles(String bucket) throws Exception {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucket).recursive(true).build());
List<Fileinfo> infos = new ArrayList<>();
results.forEach(r->{
Fileinfo info = new Fileinfo();
try {
Item item = r.get();
info.setFilename(item.objectName());
info.setDirectory(item.isDir());
infos.add(info);
} catch (Exception e) {
e.printStackTrace();
}
});
return infos;
}
/**
* 下载一个文件
*/
public InputStream download(String bucket, String objectName) throws Exception {
InputStream stream = minioClient.getObject(
GetObjectArgs.builder().bucket(bucket).object(objectName).build());
return stream;
}
/**
* 删除一个桶
*/
public void deleteBucket(String bucket) throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
}
/**
* 删除一个对象
*/
public void deleteObject(String bucket, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
}
/**
* 生成直传链接
* @param fileDirName
* @param bucket
* @return
*/
public String getOneURL(String fileDirName, String bucket) throws Exception{
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
if (!found) {
throw new RuntimeException("桶不存在!");
}
Map<String, String> reqParams = new HashMap<String, String>();
reqParams.put("response-content-type", "application/json");
return minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT) //这里必须是PUT如果是GET的话就是文件访问地址了如果是POST上传会报错.
.bucket(bucket) // 存储桶
.object(fileDirName) // 文件名
.expiry(60 * 60 * 24)
.extraQueryParams(reqParams)
.build());
}
public String getMinioURL(String bucket, String fileDirName) throws Exception{
String key = bucket + ":" + fileDirName.replaceAll("/", ":");
String url = (String) redisTemplate.opsForValue().get(key);
if (StringUtils.isEmpty(url)) {
int timeout = 60 * 60 * 24 * 7;
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(fileDirName)
.expiry(timeout, TimeUnit.SECONDS) //生成的预签名url可访问的有效时间最大期限7天
.build();
url = minioClient.getPresignedObjectUrl(build);
redisTemplate.opsForValue().set(key, url);
redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
return url;
}
public List<String> getMinioURLs(String bucket, String[] fileDirNames) throws Exception{
List<String> urlList = new ArrayList<>();
for (String fileDirName : fileDirNames) {
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(fileDirName)
.expiry(60 * 60 * 24 * 7) //生成的预签名url可访问的有效时间最大期限7天
.build();
String url = minioClient.getPresignedObjectUrl(build);
urlList.add(url);
}
return urlList;
}
public String getContenType(String bucket, String objectName) throws Exception{
// 创建StatObjectArgs对象
StatObjectArgs statObjectArgs = StatObjectArgs.builder()
.bucket(bucket)
.object(objectName)
.build();
// 获取对象信息
StatObjectResponse statObjectResponse = minioClient.statObject(statObjectArgs);
if (statObjectResponse == null) {
throw new RuntimeException("文件不存在!");
}
// 获取文件类型
String contentType = statObjectResponse.contentType();
System.out.println("文件类型:" + contentType);
return contentType;
}
public void uploadFile2(MultipartFile file, String bucket, String fileDirName) throws Exception{
Long fileSize = file.getSize();
String fileType = file.getContentType();
String fileName = file.getOriginalFilename();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucket) // 存储桶
.object(fileDirName) // 文件名
.stream(file.getInputStream(), fileSize, -1) // 文件内容
.contentType(fileType) // 文件类型
.build());
}
}

View File

@ -0,0 +1,218 @@
package com.hb.util;
import com.hb.constant.Constants;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* 客户端工具类
*
* @author ruoyi
*/
public class ServletUtils
{
/**
* 获取String参数
*/
public static String getParameter(String name)
{
return getRequest().getParameter(name);
}
/**
* 获取String参数
*/
public static String getParameter(String name, String defaultValue)
{
return Convert.toStr(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Integer参数
*/
public static Integer getParameterToInt(String name)
{
return Convert.toInt(getRequest().getParameter(name));
}
/**
* 获取Integer参数
*/
public static Integer getParameterToInt(String name, Integer defaultValue)
{
return Convert.toInt(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name)
{
return Convert.toBool(getRequest().getParameter(name));
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue)
{
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/**
* 获得所有请求参数
*
* @param request 请求对象{@link ServletRequest}
* @return Map
*/
public static Map<String, String[]> getParams(ServletRequest request)
{
final Map<String, String[]> map = request.getParameterMap();
return Collections.unmodifiableMap(map);
}
/**
* 获得所有请求参数
*
* @param request 请求对象{@link ServletRequest}
* @return Map
*/
public static Map<String, String> getParamMap(ServletRequest request)
{
Map<String, String> params = new HashMap<>();
for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
{
params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
}
return params;
}
/**
* 获取request
*/
public static HttpServletRequest getRequest()
{
return getRequestAttributes().getRequest();
}
/**
* 获取response
*/
public static HttpServletResponse getResponse()
{
return getRequestAttributes().getResponse();
}
/**
* 获取session
*/
public static HttpSession getSession()
{
return getRequest().getSession();
}
public static ServletRequestAttributes getRequestAttributes()
{
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
/**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param string 待渲染的字符串
*/
public static void renderString(HttpServletResponse response, String string)
{
try
{
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().print(string);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 是否是Ajax异步请求
*
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request)
{
String accept = request.getHeader("accept");
if (accept != null && accept.contains("application/json"))
{
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
{
return true;
}
String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
{
return true;
}
String ajax = request.getParameter("__ajax");
return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
}
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str)
{
try
{
return URLEncoder.encode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
/**
* 内容解码
*
* @param str 内容
* @return 解码后的内容
*/
public static String urlDecode(String str)
{
try
{
return URLDecoder.decode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
}

View File

@ -0,0 +1,90 @@
package com.hb.util;
/**
* 字符串格式化
*
* @author ruoyi
*/
public class StrFormatter
{
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray)
{
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
{
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
{
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1)
{
if (handledPosition == 0)
{
return strPattern;
}
else
{ // 字符串模板剩余部分不再包含占位符加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
}
else
{
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
{
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
{
// 转义符之前还有一个转义符占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
else
{
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
}
else
{
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}

View File

@ -0,0 +1,609 @@
package com.hb.util;
import com.hb.constant.Constants;
import org.springframework.util.AntPathMatcher;
import java.util.*;
/**
* 字符串工具类
*
* @author ruoyi
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
/** 下划线 */
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue)
{
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll)
{
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll)
{
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
** @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects)
{
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects)
{
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map)
{
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str)
{
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object)
{
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object)
{
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object)
{
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str)
{
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start)
{
if (str == null)
{
return NULLSTR;
}
if (start < 0)
{
start = str.length() + start;
}
if (start < 0)
{
start = 0;
}
if (start > str.length())
{
return NULLSTR;
}
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end)
{
if (str == null)
{
return NULLSTR;
}
if (end < 0)
{
end = str.length() + end;
}
if (start < 0)
{
start = str.length() + start;
}
if (end > str.length())
{
end = str.length();
}
if (start > end)
{
return NULLSTR;
}
if (start < 0)
{
start = 0;
}
if (end < 0)
{
end = 0;
}
return str.substring(start, end);
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params)
{
if (isEmpty(params) || isEmpty(template))
{
return template;
}
return StrFormatter.format(template, params);
}
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static final Set<String> str2Set(String str, String sep)
{
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
{
List<String> list = new ArrayList<String>();
if (StringUtils.isEmpty(str))
{
return list;
}
// 过滤空白字符串
if (filterBlank && StringUtils.isBlank(str))
{
return list;
}
String[] split = str.split(sep);
for (String string : split)
{
if (filterBlank && StringUtils.isBlank(string))
{
continue;
}
if (trim)
{
string = string.trim();
}
list.add(string);
}
return list;
}
/**
* 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
*
* @param collection 给定的集合
* @param array 给定的数组
* @return boolean 结果
*/
public static boolean containsAny(Collection<String> collection, String... array)
{
if (isEmpty(collection) || isEmpty(array))
{
return false;
}
else
{
for (String str : array)
{
if (collection.contains(str))
{
return true;
}
}
return false;
}
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @param cs 指定字符串
* @param searchCharSequences 需要检查的字符串数组
* @return 是否包含任意一个字符串
*/
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
{
if (isEmpty(cs) || isEmpty(searchCharSequences))
{
return false;
}
for (CharSequence testStr : searchCharSequences)
{
if (containsIgnoreCase(cs, testStr))
{
return true;
}
}
return false;
}
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str)
{
if (str == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (i > 0)
{
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
}
else
{
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1))
{
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
{
sb.append(SEPARATOR);
}
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
{
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs)
{
if (str != null && strs != null)
{
for (String s : strs)
{
if (str.equalsIgnoreCase(trim(s)))
{
return true;
}
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name)
{
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
// 不含下划线仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
// 跳过原始字符串中开头结尾的下换线或双重下划线
if (camel.isEmpty())
{
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法
* 例如user_name->userName
*/
public static String toCamelCase(String s)
{
if (s == null)
{
return null;
}
if (s.indexOf(SEPARATOR) == -1)
{
return s;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c == SEPARATOR)
{
upperCase = true;
}
else if (upperCase)
{
sb.append(Character.toUpperCase(c));
upperCase = false;
}
else
{
sb.append(c);
}
}
return sb.toString();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url)
{
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
return (T) obj;
}
/**
* 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式该字符串为指定长度
*/
public static final String padl(final Number num, final int size)
{
return padl(num.toString(), size, '0');
}
/**
* 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @return 返回指定长度的字符串由原字符串左补齐或截取得到
*/
public static final String padl(final String s, final int size, final char c)
{
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
sb.append(c);
}
sb.append(s);
}
else
{
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
sb.append(c);
}
}
return sb.toString();
}
}

View File

@ -0,0 +1,44 @@
server:
port: 8888
logging:
config: classpath:log4j2.xml
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 1000MB
# redis 配置
redis:
# 地址
host: 192.168.12.71
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password: 123456
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
#minio配置
minio:
url: https://192.168.12.71:9000 #对象存储服务的URL
accessKey: QVoCEhy0xek0pquP #Access key账户
secretKey: g89JlYE4Nnii66g6JmGRoSF7S4bc0hm6 #Secret key密码
#minio:
# url: https://192.168.12.180:9091
# accessKey: Iws9bNohJkz8fRhU
# secretKey: DaPp2vzxsX87fFfyYa51fWaeclxGfcwN

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="off">
<Properties>
<!-- 日志存储路径 -->
<Property name="baseDir">./logs</Property>
</Properties>
<CustomLevels>
<CustomLevel name="AUDIT" intLevel="50" />
</CustomLevels>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="[%-5p] [%d{HH:mm:ss}] %c - %m%n" />
</Console>
<!-- 自定义 -->
<RollingFile name="RollingFileAUDIT"
fileName="${baseDir}/logservice-web/audit-log/audit-log.log" filePattern="${baseDir}/logservice-web/audit-log/audit-log-%i.log">
<ThresholdFilter level="AUDIT" onMatch="ACCEPT" onMismatch="DENY" />
<PatternLayout pattern="[%d{yyyy/MM/dd HH:mm:ssS}][%p][LOGSERVICE][日志系统]%m%n" />
<Policies>
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<!-- 保存最大文件个数 -->
<DefaultRolloverStrategy max="50" />
</RollingFile>
<!--Trace级别日志输出-->
<RollingFile name="system-trace"
fileName="${baseDir}/logservice-web/trace.log" filePattern="${baseDir}/logservice-web/trace-%i.log">
<Filters>
<ThresholdFilter level="debug" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<PatternLayout charset="UTF-8" pattern="[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n" />
<Policies>
<!-- 日志文件大小 -->
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<!-- 保存最大文件个数 -->
<DefaultRolloverStrategy max="50" />
</RollingFile>
<!--Info级别日志输出-->
<RollingFile name="system-info"
fileName="${baseDir}/logservice-web/info.log"
filePattern="${baseDir}/logservice-web/info-%i.log">
<Filters>
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<PatternLayout charset="UTF-8" pattern="[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n" />
<Policies>
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<DefaultRolloverStrategy max="50" />
</RollingFile>
<!--Debug级别日志输出-->
<RollingFile name="system-debug"
fileName="${baseDir}/logservice-web/debug.log" filePattern="${baseDir}/logservice-web/debug-%i.log">
<Filters>
<ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<PatternLayout charset="UTF-8" pattern="[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n" />
<Policies>
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<DefaultRolloverStrategy max="50" />
</RollingFile>
<!--Error级别日志输出-->
<RollingFile name="system-error"
fileName="${baseDir}/logservice-web/error.log" filePattern="${baseDir}/logservice-web/error-%i.log">
<Filters>
<ThresholdFilter level="AUDIT" onMatch="DENY" onMismatch="NEUTRAL" />
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<PatternLayout charset="UTF-8" pattern="[%d{yyyy/MM/dd HH:mm:ssSSS}][%p][LOGSERVICE][日志系统][%l]%n%m%n" />
<Policies>
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<DefaultRolloverStrategy max="50" />
</RollingFile>
</Appenders>
<Loggers>
<logger name="io.netty" level="INFO"></logger>
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.elasticsearch" level="INFO"></logger>
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="system-info" />
<appender-ref ref="system-trace" />
<appender-ref ref="system-debug" />
<appender-ref ref="system-error" />
<appender-ref ref="RollingFileAUDIT" />
</root>
</Loggers>
</configuration>