Browse Source

更新minio和elasicsearch的配置

flowtest
zhouhaibin 3 months ago
parent
commit
019b4e1fd4
  1. 2
      platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/mapper/CostItemDetailMapper.xml
  2. 4
      platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/vo/ProductsVO.java
  3. 88
      platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/impl/SupplierProductsServiceImpl.java
  4. 31
      platform-boot-starter-demo/src/main/resources/http_ca.crt
  5. 30
      platform-boot-starter-elasticsearch/pom.xml
  6. 221
      platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/config/ElasticSearchConfig.java
  7. 32
      platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/config/LocalDateTimeAdapter.java
  8. 74
      platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/entity/SupplierProductsDTO.java
  9. 6
      platform-boot-starter-oss/src/main/java/tech/abc/platform/oss/config/MinioConfig.java
  10. 24
      platform-boot-starter-oss/src/main/resources/application.yml
  11. 26
      platform-boot-starter/src/main/resources/application-platform.yml
  12. 8
      platform-support/src/main/java/tech/abc/platform/support/controller/AttachmentController.java
  13. 8
      platform-support/src/main/java/tech/abc/platform/support/service/AttachmentService.java
  14. 39
      platform-support/src/main/java/tech/abc/platform/support/service/impl/AttachmentServiceImpl.java
  15. 19
      pom.xml

2
platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/mapper/CostItemDetailMapper.xml

@ -21,7 +21,7 @@
</resultMap> </resultMap>
<sql id="getProductsPageByType_Column_List"> <sql id="getProductsPageByType_Column_List">
id, supplier_information_id, product_name, product_identity, id, supplier_information_id, product_name, product_identity,
product_price, source_information, model_id, remarks, product_price, source_information, model_id, remarks,image,
delete_flag delete_flag
</sql> </sql>
<sql id="getProductsPageByType_Query"> <sql id="getProductsPageByType_Query">

4
platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/vo/ProductsVO.java

@ -36,6 +36,8 @@ public class ProductsVO extends BaseVO {
@NotBlank(message = "【产品名称】不能为空") @NotBlank(message = "【产品名称】不能为空")
private String productName; private String productName;
private String image;
/** /**
* 产品标识型号 * 产品标识型号
*/ */
@ -64,7 +66,7 @@ public class ProductsVO extends BaseVO {
/** /**
* 产品描述 * 产品描述
*/ */
private String ModelDescription; private String productSpecifications;
/** /**
* 产品类型 (-1:全部, 0:供应商产品库, 1:公司产品库,2:个人产品库) * 产品类型 (-1:全部, 0:供应商产品库, 1:公司产品库,2:个人产品库)

88
platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/impl/SupplierProductsServiceImpl.java

@ -1,14 +1,24 @@
package tech.abc.platform.productManagement.service.impl; package tech.abc.platform.productManagement.service.impl;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import tech.abc.platform.common.exception.CommonException;
import tech.abc.platform.common.exception.CustomException;
import tech.abc.platform.common.vo.PageInfo; import tech.abc.platform.common.vo.PageInfo;
import tech.abc.platform.common.vo.SortInfo; import tech.abc.platform.common.vo.SortInfo;
import tech.abc.platform.elasticsearch.entity.SupplierProductsDTO; import tech.abc.platform.elasticsearch.entity.SupplierProductsDTO;
@ -47,7 +57,8 @@ public class SupplierProductsServiceImpl extends BaseServiceImpl<SupplierProduct
@Autowired @Autowired
private SupplierProductModelDetailsMapper supplierProductModelDetailsMapper; private SupplierProductModelDetailsMapper supplierProductModelDetailsMapper;
@Autowired @Autowired
private ElasticsearchClient client; private RestHighLevelClient client;
@Override @Override
public SupplierProducts init() { public SupplierProducts init() {
SupplierProducts entity=new SupplierProducts(); SupplierProducts entity=new SupplierProducts();
@ -97,49 +108,52 @@ public class SupplierProductsServiceImpl extends BaseServiceImpl<SupplierProduct
public IPage<SupplierProductsVO> querypagebyes(SupplierProductsVO queryVO, PageInfo pageInfo, SortInfo sortInfo) { public IPage<SupplierProductsVO> querypagebyes(SupplierProductsVO queryVO, PageInfo pageInfo, SortInfo sortInfo) {
// 执行查询 // 执行查询
Page<SupplierProductsVO> supplierProductsVOPage = new Page<>(pageInfo.getPageNum(), pageInfo.getPageSize()); Page<SupplierProductsVO> supplierProductsVOPage = new Page<>(pageInfo.getPageNum(), pageInfo.getPageSize());
List<SupplierProductsVO> supplierProductsVOList =new ArrayList<>();
String productName = queryVO.getProductName(); String productName = queryVO.getProductName();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchRequest searchRequest = new SearchRequest("pmg_supplier_products");
// //高亮器
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false)//多字段时,需要设置为false//因为高亮查询默认是对查询字段即description就行高亮,可以关闭字段匹配,这样就可以对查询到的多个字段(前提是有关键词并且改字段可以分词)进行高亮显示
.field("product_name")//若有关键字切可以分词,则可以高亮,写*可以匹配所有字段
.field("product_specifications")//若有关键字切可以分词,则可以高亮,写*可以匹配所有字段
.preTags("<span style=\"color: red;\">")//手动前缀标签
.postTags("</span>");
searchSourceBuilder
.query(QueryBuilders.multiMatchQuery(productName, "product_name", "product_specifications"))
.highlighter(highlightBuilder)
.from(pageInfo.getPageNum()-1) //起始位置:start=(page-1)*size
.size(pageInfo.getPageSize()); //每页显示条数;
searchRequest.source(searchSourceBuilder);
try { try {
SearchResponse<SupplierProductsDTO> searchResponse = client.search(srBuilder -> srBuilder SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
.index("pmg_supplier_products") // 解析结果
// MultiMatch 查找:对输入内容先分词再查询。 SearchHits hits = response.getHits();
.query(queryBuilder -> queryBuilder
.multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder
.fields("product_name", "product_specifications") supplierProductsVOPage.setTotal(response.getHits().getTotalHits().value);
.query(productName) SearchHit[] searchHits = hits.getHits();
.operator(Operator.Or))) Gson gson =new Gson();
//高亮显示 for (SearchHit hit : searchHits) {
.highlight(highlightBuilder -> highlightBuilder String json = gson.toJson(hit.getSourceAsMap());
.preTags("<span style=\"color: red;\">") SupplierProductsDTO supplierProductsDTO = gson.fromJson(json, SupplierProductsDTO.class);
.postTags("</span>") SupplierProductsVO supplierProductsVO =mapperFacade.map(supplierProductsDTO, SupplierProductsVO.class);
.requireFieldMatch(false) //多字段时,需要设置为false if(hit.getHighlightFields().get("product_name")!=null){
.fields("product_name", highlightFieldBuilder -> highlightFieldBuilder) supplierProductsVO.setProductName(hit.getHighlightFields().get("product_name").getFragments()[0].toString());
.fields("product_specifications", highlightFieldBuilder -> highlightFieldBuilder)
)
.from(pageInfo.getPageNum()-1)
.size(pageInfo.getPageSize())
, SupplierProductsDTO.class);
List<Hit<SupplierProductsDTO>> hitList = searchResponse.hits().hits();
supplierProductsVOPage.setTotal(searchResponse.hits().total().value());
List<SupplierProductsVO> supplierProductsVOList =new ArrayList<>();
for (Hit<SupplierProductsDTO> hit : hitList) {
SupplierProductsVO supplierProductsVO = new SupplierProductsVO();
BeanUtils.copyProperties(hit.source(),supplierProductsVO);
// SupplierProductsVO map = mapperFacade.map(hit.source(), SupplierProductsVO.class);
if(hit.highlight().get("product_name")!=null){
supplierProductsVO.setProductName(hit.highlight().get("product_name").get(0));
} }
if(hit.highlight().get("product_specifications")!=null){ if(hit.getHighlightFields().get("product_specifications")!=null){
supplierProductsVO.setProductSpecifications(hit.highlight().get("product_specifications").get(0)); supplierProductsVO.setProductSpecifications(hit.getHighlightFields().get("product_specifications").getFragments()[0].toString());
} }
supplierProductsVOList.add(supplierProductsVO); supplierProductsVOList.add(supplierProductsVO);
} }
supplierProductsVOPage.setRecords(supplierProductsVOList); supplierProductsVOPage.setRecords(supplierProductsVOList);
return supplierProductsVOPage;
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new CustomException(CommonException.ELASTICSEARCH_ERROR,"查询失败");
} }
return supplierProductsVOPage;
} }
@Override @Override

31
platform-boot-starter-demo/src/main/resources/http_ca.crt

@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFWjCCA0KgAwIBAgIVAIoa4/XgAnDR+55oINCE0Vm77NOfMA0GCSqGSIb3DQEB
CwUAMDwxOjA4BgNVBAMTMUVsYXN0aWNzZWFyY2ggc2VjdXJpdHkgYXV0by1jb25m
aWd1cmF0aW9uIEhUVFAgQ0EwHhcNMjQwNTI4MDMwODM5WhcNMjcwNTI4MDMwODM5
WjA8MTowOAYDVQQDEzFFbGFzdGljc2VhcmNoIHNlY3VyaXR5IGF1dG8tY29uZmln
dXJhdGlvbiBIVFRQIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
1YbHndQVi5WRsO52jh1ThRGbndrVTdaKgepCEPc0bt3EiHPEXB3xUnoPQkmcazn/
Vf3fuIV8ZLML6CeR5w5jX+FYr6fl7J4o2f8WWBGS9nWkpfYYxICUh0vf9g8y3jOc
yeeME3tNFCOPRW9rlYUjq4ba514lNaGZGOnLCV6G2LBZLXIkE7ukj+Mly3pDUpJv
5aen+nsWF9MyUcXa2U8mHvv3SHNSp+N+2jbpgTYAM6tWMSbpZ+6LTewNyQi+4QiJ
Qo2BGpfi6G6YAWXfvy+ewI7hkWZVnep9ndFjci7306IDj6wfWntGmvf7OTXT2m4U
8ZVg/PECfZAIwj7A5j60joia4r4q8ftlRa+wVNTyuEvAbSYfvLt+l9A/UldQ4Vxs
+VZOCpTNwME7UQUqaZq8TThgpqd9RFGwtgeJ7JV92NPlaQCHGC9FSE1iZQB6ykAE
Dl1df5dnlTMSfj2EreDBOF4JpI406C/RDXxg3c94986UZC7ra7qQ8WBnAxpsaVto
nXIVCFaBzn7yFkJbm4f6Zd0CCYrwB9pqhqp8LuVQr0ubDvawgodanuKBUkNC7qtZ
F7jxXzSj4bg1bhDRzyUrtuIg+CTMJA0rrZWxthE2gYzvbfZqMSInPwjkgGmL6vxN
KW1FJcIHamMTHU/tl1RNSA9BnczitN3/x7fWGGfSYN0CAwEAAaNTMFEwHQYDVR0O
BBYEFI8Vo0wKU5BgjNtgyZ26uPI0iKX2MB8GA1UdIwQYMBaAFI8Vo0wKU5BgjNtg
yZ26uPI0iKX2MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAANc
g7Wf5ET9QDbTXdN4mwL4Vr2pri2mAzB1LRqAz4UGmsgxZICUZXWOoo1P5qfzOkWm
xzP9BPHXMJLtQZh3pYtb+UGuxcLeT/IcuKpXiKVX4+7N6WVyEXZl1cSy2xf3i03j
AjqP0aRJBQo74aMcFKngh2tz7NMOmSPw5cYyLIsklL9uShh/tFEgMAZtC8aReHTj
WJJhIP0NgGHMiqbozTuDatDprKE4UDgt9tOKq/ci29kCDBHH2+siJOGsg5oDwa3V
Cin/bMwCdvZwQAbmOOETyHl/Og3PduHQZ1O2FbgPICxlPzKRxDx2jTmSg7Ub36t6
Ec/j+BV8eciZneJ0f9K3SGP4aG5GECYdsINhjbG0HQe+ktj0Fm3a4mwlR+vkmF3d
/LeW6mbaO/Km3H9iRT9SRa0LG1rslL6awVSueHxpmAXU+EGI/gxdacxV8T32V8IJ
cYYJcKVZC5HDnN4VP+PDXST3cfKGb1wRSL1+IkCjrY9EZK+DFJG/gmTdgDi9qSBx
99vHbnGyKBY5+UAZ2nVxnnRTyfLXXkZQZqVzuRg6STlKGvYbWSS/nBLVyp/dW32J
kJK7t92SV8TGzFY24VyfnBsQaf1mUnsSSn5tFDej6bvpA83nsL8sgUeHy/HbGKTA
5AxbnKvU2qtM65Sx01ZKVdbVE5ubYGxu2h7IGZ38
-----END CERTIFICATE-----

30
platform-boot-starter-elasticsearch/pom.xml

@ -9,13 +9,13 @@
</parent> </parent>
<artifactId>platform-boot-starter-elasticsearch</artifactId> <artifactId>platform-boot-starter-elasticsearch</artifactId>
<version>5.1.0</version> <version>5.1.0</version>
<name>platform-boot-starter-elasticsearch</name> <name>platform-boot-starter-elasticsearch</name>
<description>全文搜索</description> <description>全文搜索</description>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>tech.abc</groupId> <groupId>tech.abc</groupId>
@ -27,23 +27,31 @@
<!-- <groupId>org.springframework.boot</groupId>--> <!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>--> <!-- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>-->
<!-- </dependency>--> <!-- </dependency>-->
<!--es搜索-->
<dependency> <dependency>
<groupId>co.elastic.clients</groupId> <groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-java</artifactId> <artifactId>elasticsearch</artifactId>
<version>8.1.3</version> </dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>gson</artifactId>
<version>2.13.3</version>
</dependency> </dependency>
<!--es搜索-->
<!-- <dependency>-->
<!-- <groupId>co.elastic.clients</groupId>-->
<!-- <artifactId>elasticsearch-java</artifactId>-->
<!-- <version>8.1.3</version>-->
<!-- </dependency>-->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>jakarta.json</groupId>--> <!-- <groupId>com.fasterxml.jackson.core</groupId>-->
<!-- <artifactId>jakarta.json-api</artifactId>--> <!-- <artifactId>jackson-databind</artifactId>-->
<!-- <version>2.0.1</version>--> <!-- <version>2.13.3</version>-->
<!-- </dependency>--> <!-- </dependency>-->
<!--读取Word/Excel/PowerPoint文件内容--> <!--读取Word/Excel/PowerPoint文件内容-->
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>

221
platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/config/ElasticSearchConfig.java

@ -1,46 +1,23 @@
package tech.abc.platform.elasticsearch.config; package tech.abc.platform.elasticsearch.config;
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import org.apache.commons.lang3.StringUtils;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope; import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider; import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils; import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
/** /**
* ElasticSearch 配置 * ElasticSearch 配置
@ -58,7 +35,89 @@ public class ElasticSearchConfig {
private String userName; private String userName;
@Value("${elasticsearch.password}") @Value("${elasticsearch.password}")
private String passWord; private String password;
/**
* es 请求方式
*/
@Value("${elasticsearch.scheme}")
private String scheme;
/**
* es 连接超时时间
*/
@Value("${elasticsearch.connectTimeOut}")
private int connectTimeOut;
/**
* es socket 连接超时时间
*/
@Value("${elasticsearch.socketTimeOut}")
private int socketTimeOut;
/**
* es 请求超时时间
*/
@Value("${elasticsearch.connectionRequestTimeOut}")
private int connectionRequestTimeOut;
/**
* es 最大连接数
*/
@Value("${elasticsearch.maxConnectNum}")
private int maxConnectNum;
/**
* es 每个路由的最大连接数
*/
@Value("${elasticsearch.maxConnectNumPerRoute}")
private int maxConnectNumPerRoute;
/**
* 如果@Bean没有指定bean的名称那么方法名就是bean的名称
*/
@Bean
public RestHighLevelClient restHighLevelClient() {
// 构建连接对象
RestClientBuilder builder = RestClient.builder(getEsHost());
// 连接延时配置
builder.setRequestConfigCallback(requestConfigBuilder -> {
requestConfigBuilder.setConnectTimeout(connectTimeOut);
requestConfigBuilder.setSocketTimeout(socketTimeOut);
requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
return requestConfigBuilder;
});
// 连接数配置
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setMaxConnTotal(maxConnectNum);
httpClientBuilder.setMaxConnPerRoute(maxConnectNumPerRoute);
httpClientBuilder.setDefaultCredentialsProvider(getCredentialsProvider());
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
private HttpHost[] getEsHost() {
// 拆分地址(es为多节点时,不同host以逗号间隔)
List<HttpHost> hostLists = new ArrayList<>();
String[] hostList = hosts.split(",");
for (String addr : hostList) {
String host = addr.split(":")[0];
String port = addr.split(":")[1];
hostLists.add(new HttpHost(host, Integer.parseInt(port), scheme));
}
// 转换成 HttpHost 数组
return hostLists.toArray(new HttpHost[]{});
}
private CredentialsProvider getCredentialsProvider() {
// 设置用户名、密码
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));
return credentialsProvider;
}
/** /**
* 同步方式 * 同步方式
* *
@ -107,85 +166,27 @@ public class ElasticSearchConfig {
//// asyncClient = new ElasticsearchAsyncClient(transport); //// asyncClient = new ElasticsearchAsyncClient(transport);
// //
// } // }
@Bean
public ElasticsearchClient clientByPasswd() throws Exception {
ElasticsearchTransport transport = getElasticsearchTransport(userName, passWord, toHttpHost());
return new ElasticsearchClient(transport);
}
private static SSLContext buildSSLContext() { // /**
ClassPathResource resource = new ClassPathResource("http_ca.crt"); // * 解析配置的字符串hosts,转为HttpHost对象数组
SSLContext sslContext = null; // *
try { // * @return
CertificateFactory factory = CertificateFactory.getInstance("X.509"); // */
Certificate trustedCa; // private HttpHost[] toHttpHost() {
try (InputStream is = resource.getInputStream()) { // if (!StringUtils.hasLength(hosts)) {
trustedCa = factory.generateCertificate(is); // throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts不能为空!");
} // }
KeyStore trustStore = KeyStore.getInstance("pkcs12"); // // 多个IP逗号隔开
trustStore.load(null, null); // String[] hostArray = hosts.split(",");
trustStore.setCertificateEntry("ca", trustedCa); // HttpHost[] httpHosts = new HttpHost[hostArray.length];
SSLContextBuilder sslContextBuilder = SSLContexts.custom() // HttpHost httpHost;
.loadTrustMaterial(trustStore, null); // for (int i = 0; i < hostArray.length; i++) {
sslContext = sslContextBuilder.build(); // String[] strings = hostArray[i].split(":");
} catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException | // httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "https");
KeyManagementException e) { // httpHosts[i] = httpHost;
throw new RuntimeException("ES连接认证失败", e); // }
} // return httpHosts;
// }
return sslContext;
}
private static ElasticsearchTransport getElasticsearchTransport(String username, String passwd, HttpHost...hosts) {
// 账号密码的配置
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, passwd));
// 自签证书的设置,并且还包含了账号密码
RestClientBuilder.HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder
.setSSLContext(buildSSLContext())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setDefaultCredentialsProvider(credentialsProvider);
// 用builder创建RestClient对象
RestClient client = RestClient
.builder(hosts)
.setHttpClientConfigCallback(callback)
.build();
return new RestClientTransport(client, new JacksonJsonpMapper());
}
/**
* 异步方式
*
* @return
*/
@Bean
public ElasticsearchAsyncClient elasticsearchAsyncClient() {
HttpHost[] httpHosts = toHttpHost();
RestClient restClient = RestClient.builder(httpHosts).build();
RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
return new ElasticsearchAsyncClient(transport);
}
/**
* 解析配置的字符串hosts转为HttpHost对象数组
*
* @return
*/
private HttpHost[] toHttpHost() {
if (!StringUtils.hasLength(hosts)) {
throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts不能为空!");
}
// 多个IP逗号隔开
String[] hostArray = hosts.split(",");
HttpHost[] httpHosts = new HttpHost[hostArray.length];
HttpHost httpHost;
for (int i = 0; i < hostArray.length; i++) {
String[] strings = hostArray[i].split(":");
httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "https");
httpHosts[i] = httpHost;
}
return httpHosts;
}
// @Bean // @Bean
// ElasticsearchConverter elasticsearchConverter(SimpleElasticsearchMappingContext mappingContext) { // ElasticsearchConverter elasticsearchConverter(SimpleElasticsearchMappingContext mappingContext) {

32
platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/config/LocalDateTimeAdapter.java

@ -0,0 +1,32 @@
package tech.abc.platform.elasticsearch.config;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author 李昊哲
* @version 1.0
* @create 2023/10/19
*/
public class LocalDateTimeAdapter implements JsonDeserializer<LocalDateTime>, JsonSerializer<LocalDateTime> {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(dateTimeFormatter.format(src));
}
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return LocalDateTime.parse(json.getAsString().substring(0, 10) +" "+ json.getAsString().substring(11, 19), dateTimeFormatter);
} catch (Exception e) {
throw new JsonParseException(e);
}
}
}

74
platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/entity/SupplierProductsDTO.java

@ -1,12 +1,16 @@
package tech.abc.platform.elasticsearch.entity; package tech.abc.platform.elasticsearch.entity;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import tech.abc.platform.common.base.BaseEntity; import tech.abc.platform.common.base.BaseEntity;
import tech.abc.platform.elasticsearch.config.LocalDateTimeAdapter;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -19,149 +23,127 @@ import java.time.LocalDateTime;
* *
*/ */
@Data @Data
@TableName("pmg_supplier_products")
@JsonIgnoreProperties(ignoreUnknown=true)
public class SupplierProductsDTO { public class SupplierProductsDTO {
/** /**
* 供应商id * 供应商id
*/ */
@TableField("supplier_information_id") @SerializedName("supplier_information_id")
@JsonProperty("supplier_information_id")
private String supplierInformationId; private String supplierInformationId;
/** /**
* 厂商产品型号id * 厂商产品型号id
*/ */
@TableField("model_id") @SerializedName("model_id")
@JsonProperty("model_id")
private String modelId; private String modelId;
/** /**
* 个人产品规格 * 个人产品规格
*/ */
@TableField("product_specifications") @SerializedName("product_specifications")
@JsonProperty("product_specifications")
private String productSpecifications; private String productSpecifications;
/** /**
* 产品名称 * 产品名称
*/ */
@TableField("product_name") @SerializedName("product_name")
@JsonProperty("product_name")
private String productName; private String productName;
/** /**
* 产品标识型号 * 产品标识型号
*/ */
@TableField("product_identity") @SerializedName("product_identity")
@JsonProperty("product_identity")
private String productIdentity; private String productIdentity;
/** /**
* 产品价格 * 产品价格
*/ */
@TableField(value="product_price",updateStrategy= FieldStrategy.IGNORED) @SerializedName("product_price")
@JsonProperty("product_price")
private BigDecimal productPrice; private BigDecimal productPrice;
/** /**
* 信息来源 * 信息来源
*/ */
@TableField("source_information") @SerializedName("source_information")
@JsonProperty("source_information")
private String sourceInformation; private String sourceInformation;
/** /**
* 备注 * 备注
*/ */
@TableField("remarks") @SerializedName("remarks")
@JsonProperty("remarks")
private String remarks; private String remarks;
/** /**
* 产品图片 * 产品图片
*/ */
@TableField("image") @SerializedName("image")
@JsonProperty("image")
private String image; private String image;
/** /**
* 产品品牌 * 产品品牌
*/ */
@TableField("brand") @SerializedName("brand")
@JsonProperty("brand")
private String brand; private String brand;
/** /**
* 产品单位*/ * 产品单位*/
@TableField("unit") @SerializedName("unit")
@JsonProperty("unit")
private String unit; private String unit;
/** /**
* 除税价格 * 除税价格
*/ */
@TableField("ex_tax_price") @SerializedName("ex_tax_price")
@JsonProperty("ex_tax_price")
private BigDecimal exTaxPrice; private BigDecimal exTaxPrice;
/** /**
* 税率 * 税率
*/ */
@TableField("taxrate") @SerializedName("taxrate")
@JsonProperty("taxrate")
private BigDecimal taxrate; private BigDecimal taxrate;
/** /**
* 分类id * 分类id
*/ */
@TableField("category_id") @SerializedName("category_id")
@JsonProperty("category_id")
private String categoryId; private String categoryId;
/** /**
* 逻辑删除 * 逻辑删除
*/ */
@TableField(value = "delete_flag", fill = FieldFill.INSERT) @SerializedName("delete_flag")
@TableLogic
@JsonProperty("delete_flag")
protected String deleteFlag; protected String deleteFlag;
/** /**
* 创建人标识 * 创建人标识
*/ */
@TableField(value = "create_id", fill = FieldFill.INSERT) @SerializedName("create_id")
@JsonProperty("create_id")
private String createId; private String createId;
/** /**
* 创建时间 * 创建时间
*/ */
@TableField(value = "create_time", fill = FieldFill.INSERT) @SerializedName("create_time")
@JsonProperty("create_time") @JsonAdapter(LocalDateTimeAdapter.class)
private String createTime; private LocalDateTime createTime;
/** /**
* 更新人标识 * 更新人标识
*/ */
@TableField(value = "update_id", fill = FieldFill.INSERT_UPDATE) @SerializedName("update_id")
@JsonProperty("update_id")
private String updateId; private String updateId;
/** /**
* 更新时间 * 更新时间
*/ */
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @SerializedName("update_time")
@JsonProperty("update_time") @JsonAdapter(LocalDateTimeAdapter.class)
private String updateTime; private LocalDateTime updateTime;
/** /**
* 版本 * 版本
*/ */
@TableField(value = "version", fill = FieldFill.INSERT) @SerializedName("version")
@JsonProperty("version")
private Integer version; private Integer version;
/********非库表存储属性*****/ /********非库表存储属性*****/
} }

6
platform-boot-starter-oss/src/main/java/tech/abc/platform/oss/config/MinioConfig.java

@ -18,17 +18,17 @@ public class MinioConfig {
/** /**
* 账号 * 账号
*/ */
private String accessKey = "admin"; private String accessKey = "root";
/** /**
* 密钥 * 密钥
*/ */
private String secretKey = "12345678"; private String secretKey = "123456789";
/** /**
* 桶名 * 桶名
*/ */
private String bucketName = "abc"; private String bucketName = "test";
} }

24
platform-boot-starter-oss/src/main/resources/application.yml

@ -1,12 +1,12 @@
platform-config: #platform-config:
oss: # oss:
# 本地磁盘存储模式 ## 本地磁盘存储模式
# storeClass: tech.abc.platform.oss.service.impl.LocalStoreServiceImpl ## storeClass: tech.abc.platform.oss.service.impl.LocalStoreServiceImpl
# 集成minio模式 ## 集成minio模式
storeClass: tech.abc.platform.oss.service.impl.MinioStoreServiceImpl # storeClass: tech.abc.platform.oss.service.impl.MinioStoreServiceImpl
basePath: c:/attachment/ # basePath: c:/attachment/
minio: # minio:
server: http://127.0.0.1:9000 # server: http://127.0.0.1:9000
accessKey: admin # accessKey: minioadmin
secretKey: 12345678 # secretKey: minioadmin
bucketName: abc # bucketName: test

26
platform-boot-starter/src/main/resources/application-platform.yml

@ -1,9 +1,23 @@
server: server:
port: 8080 port: 8080
elasticsearch: elasticsearch:
# es host ip 地址(集群),多个以","间隔
uris: localhost:9200 uris: localhost:9200
username: elastic username: elastic
password: '1CVfNF7NPO+HQXprJGaR' password: 123456789
# es 请求方式
scheme: http
# es 连接超时时间(ms)
connectTimeOut: 1000
# es socket 连接超时时间(ms)
socketTimeOut: 30000
# es 请求超时时间(ms)
connectionRequestTimeOut: 500
# es 最大连接数
maxConnectNum: 100
# es 每个路由的最大连接数
maxConnectNumPerRoute: 100
#数据连接 #数据连接
spring: spring:
datasource: datasource:
@ -139,16 +153,16 @@ platform-config:
enableResend: true enableResend: true
oss: oss:
# 本地磁盘存储模式 # 本地磁盘存储模式
storeClass: tech.abc.platform.oss.service.impl.LocalStoreServiceImpl # storeClass: tech.abc.platform.oss.service.impl.LocalStoreServiceImpl
# 集成minio模式 # 集成minio模式
# storeClass: tech.abc.platform.oss.service.impl.MinioStoreServiceImpl storeClass: tech.abc.platform.oss.service.impl.MinioStoreServiceImpl
# 本地磁盘需要给出路径,如c:/attachment/或/data;minio因使用桶作为逻辑存储,无根路径,需留空 # 本地磁盘需要给出路径,如c:/attachment/或/data;minio因使用桶作为逻辑存储,无根路径,需留空
basePath: c:/attachment/ basePath: c:/attachment/
minio: minio:
server: http://127.0.0.1:9000 server: http://127.0.0.1:9000
accessKey: admin accessKey: root
secretKey: 12345678 secretKey: 123456789
bucketName: abc bucketName: test
mail: mail:
senderAddress: sealy321@126.com senderAddress: sealy321@126.com
file: file:

8
platform-support/src/main/java/tech/abc/platform/support/controller/AttachmentController.java

@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload; import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -42,6 +43,7 @@ import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
/** /**
@ -245,6 +247,12 @@ public class AttachmentController extends BaseController {
} }
@PostMapping("/uploadImageReturnUrl")
@AllowAuthenticated
public ResponseEntity<Result> uploadImageReturnUrl(MultipartFile image) {
String url = attachmentService.uploadImageReturnUrl(image);
return ResultUtil.success(url);
}
@PostMapping("/uploadImage") @PostMapping("/uploadImage")
@AllowAuthenticated @AllowAuthenticated
public ResponseEntity<Result> uploadImage(MultipartFile image) { public ResponseEntity<Result> uploadImage(MultipartFile image) {

8
platform-support/src/main/java/tech/abc/platform/support/service/AttachmentService.java

@ -57,7 +57,13 @@ public interface AttachmentService extends BaseService<Attachment> {
* @return 文件流 * @return 文件流
*/ */
InputStream getFile(String id); InputStream getFile(String id);
/**
* 上传图片并返回url
*
* @param image
* @return 图片url
*/
String uploadImageReturnUrl(MultipartFile image);
} }

39
platform-support/src/main/java/tech/abc/platform/support/service/impl/AttachmentServiceImpl.java

@ -1,6 +1,10 @@
package tech.abc.platform.support.service.impl; package tech.abc.platform.support.service.impl;
import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
@ -18,7 +22,10 @@ import tech.abc.platform.support.entity.Attachment;
import tech.abc.platform.support.mapper.AttachmentMapper; import tech.abc.platform.support.mapper.AttachmentMapper;
import tech.abc.platform.support.service.AttachmentService; import tech.abc.platform.support.service.AttachmentService;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -35,6 +42,8 @@ public class AttachmentServiceImpl extends BaseServiceImpl<AttachmentMapper, Att
@Autowired @Autowired
private ObjectStoreService objectStoreService; private ObjectStoreService objectStoreService;
@Autowired
private MinioClient minioClient;
@Override @Override
@ -132,8 +141,36 @@ public class AttachmentServiceImpl extends BaseServiceImpl<AttachmentMapper, Att
} }
@Override
public String uploadImageReturnUrl(MultipartFile image) {
//生成唯一性标识
String entityId = IdWorker.getIdStr();
// 存储文件
objectStoreService.uploadImage(image, entityId);
String realName = entityId + image.getOriginalFilename();
// 生成附件信息
Attachment entity = new Attachment();
entity.setName(image.getOriginalFilename());
// 设置友好显示大小
entity.setSize(FileUtil.getFileSize(image.getSize()));
entity.setLength(image.getSize());
// 设置存储相对路径
entity.setPath(FileConstant.IMAGE_PATH+realName);
entity.setType(image.getContentType());
entity.setRealName(realName);
entity.setEntity(entityId);
add(entity);
// GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
// .method(Method.GET)
// .bucket("test")
// .object(FileConstant.IMAGE_PATH+entityId + image.getOriginalFilename())
// .build();
// url = minioClient.getPresignedObjectUrl(args);
String url = "http://127.0.0.1:9000/test/image/"+realName;
return url;
// return entity.getId();
}
/** /**

19
pom.xml

@ -40,17 +40,22 @@
<platform.version>5.1.0</platform.version> <platform.version>5.1.0</platform.version>
<springboot.version>2.3.0.RELEASE</springboot.version> <springboot.version>2.3.0.RELEASE</springboot.version>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<jakartajson.version>2.0.1</jakartajson.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<elasticsearch.version>7.10.2</elasticsearch.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>jakarta.json</groupId> <groupId>org.elasticsearch</groupId>
<artifactId>jakarta.json-api</artifactId> <artifactId>elasticsearch</artifactId>
<version>${jakartajson.version}</version> <version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency> </dependency>
<!-- 邮件--> <!-- 邮件-->
<dependency> <dependency>
@ -70,6 +75,12 @@
<version>${springboot.version}</version> <version>${springboot.version}</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- 平台公共模块--> <!-- 平台公共模块-->
<dependency> <dependency>

Loading…
Cancel
Save