diff --git a/README.md b/README.md index 73286b7..c8f1cec 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ - master 快速上手开发spring boot 用户端单体应用 - feature/admin-auth-spring-security 基于master分支集成spring官方鉴权框架spring security框架,可用于后台管理系统后端项目,实现RBAC模型(角色 → 用户 → 菜单 → 权限)基于角色的访问控制 - feature/admin-auth-sa-token 基于master分支集成国产权限框架sa-token,可用于后台管理系统后端项目,实现RBAC模型(角色 → 用户 → 菜单 → 权限)基于角色的访问控制 +- component/rocketmq-and-es 基于master分支集成消息队列原生RocketMQ5.x与原生Elasticsearch 8.x,提供消息队列与搜索引擎服务,实现消息持久化与全文检索 +- feature/master-payment 基于master分支集成支付宝沙盒功能(H5支付、APP支付) ### 集成技术与功能亮点 diff --git a/pom.xml b/pom.xml index d667951..1a56425 100644 --- a/pom.xml +++ b/pom.xml @@ -25,9 +25,7 @@ 5.3 2023.0.1.0 2023.0.1 - 8.16.0 4.0.1 - 2.3.4 4.40.476.ALL @@ -124,19 +122,6 @@ ${sverlet.version} provided - - - co.elastic.clients - elasticsearch-java - ${elasticsearch.version} - - - - org.apache.rocketmq - rocketmq-spring-boot-starter - ${rocketmq.version} - - com.alipay.sdk diff --git a/src/main/java/cn/xf/basedemo/common/model/EsBaseModel.java b/src/main/java/cn/xf/basedemo/common/model/EsBaseModel.java deleted file mode 100644 index dd32333..0000000 --- a/src/main/java/cn/xf/basedemo/common/model/EsBaseModel.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.xf.basedemo.common.model; - -import lombok.Data; - -/** - * packageName cn.xf.basedemo.common.model - * @author remaindertime - * @className EsModel - * @date 2024/12/10 - * @description es基础模型 - */ -@Data -public class EsBaseModel { - - public EsBaseModel(String indexName, String documentId, T documentModel, Class clazz) { - this.indexName = indexName; - this.documentId = documentId; - this.documentModel = documentModel; - this.clazz = clazz; - } - - /** - * 索引名称 - */ - private String indexName; - - /** - * 文档id - */ - private String documentId; - - /** - * 映射对象 - */ - private T documentModel; - - /** - * 映射对象类对象 - */ - private Class clazz; - -} diff --git a/src/main/java/cn/xf/basedemo/common/model/EsSearchModel.java b/src/main/java/cn/xf/basedemo/common/model/EsSearchModel.java deleted file mode 100644 index 13bc030..0000000 --- a/src/main/java/cn/xf/basedemo/common/model/EsSearchModel.java +++ /dev/null @@ -1,81 +0,0 @@ -package cn.xf.basedemo.common.model; - -import lombok.Data; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * packageName cn.xf.basedemo.common.model - * @author remaindertime - * @className EsSearchModel - * @date 2024/12/11 - * @description es 搜索模型 - */ -@Data -public class EsSearchModel { - - public EsSearchModel() { - // 使用 LinkedHashMap 保持插入顺序 - this.sort = new LinkedHashMap<>(); - } - - /** - * 索引名称 - */ - private String indexName; - - /** - * 文档类型 - */ - private Class clazz; - - /** - * 页数 - */ - private Integer pageNum; - - /** - * 每页数量 - */ - private Integer pageSize; - /** - * 精准查询字段 - */ - private Map termQuery; - - /** - * 模糊查询字段(一般是text类型) - */ - private Map matchQuery; - - /** - * 排序字段规则 ({"age":"desc"}) - */ - private Map sort; - - /** - * 分组去重字段(支持的字段类型:keyword、numeric、date 和 boolean ) - */ - private String repeatField;; - - /** - * 分组嵌套查询别名 - */ - private String innerAlias; - - /** - * 分组嵌套查询数量 - */ - private Integer innerSize; - - /** - * 指定需要返回的字段 - */ - private List includes; - /** - * 指定需要排除的字段 - */ - private List excludes; - -} \ No newline at end of file diff --git a/src/main/java/cn/xf/basedemo/common/utils/EsUtil.java b/src/main/java/cn/xf/basedemo/common/utils/EsUtil.java deleted file mode 100644 index 3b371e1..0000000 --- a/src/main/java/cn/xf/basedemo/common/utils/EsUtil.java +++ /dev/null @@ -1,499 +0,0 @@ -package cn.xf.basedemo.common.utils; - -import cn.xf.basedemo.common.model.EsBaseModel; -import cn.xf.basedemo.common.model.EsSearchModel; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.*; -import co.elastic.clients.elasticsearch._types.query_dsl.*; -import co.elastic.clients.elasticsearch.core.*; -import co.elastic.clients.elasticsearch.core.search.*; -import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; -import co.elastic.clients.elasticsearch.indices.ExistsRequest; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.transport.endpoints.BooleanResponse; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; -import java.util.*; -import java.util.stream.Collectors; - -/** - * packageName cn.xf.basedemo.common.utils - * @author remaindertime - * @className EsUtil - * @date 2024/12/10 - * @description elasticsearch工具类 - */ -@Slf4j -@Component -public class EsUtil { - - public static ElasticsearchClient esClient; - - { - esClient = (ElasticsearchClient) ApplicationContextUtils.getBean("elasticsearchClient"); - } - - /** - * 判断索引是否存在 - * @param indexName - * @return - */ - public static boolean existIndex(String indexName) { - try { - // 创建 ExistsRequest 请求 - ExistsRequest request = new ExistsRequest.Builder() - .index(indexName) - .build(); - // 发送请求并获取响应 - BooleanResponse response = esClient.indices().exists(request); - // 返回索引是否存在 - return response.value(); - } catch (Exception e) { - // 处理异常 - e.printStackTrace(); - return false; - } - } - - /** - * 删除索引 - * - * @param indexName - */ - @SneakyThrows - public static void delIndex(String indexName) { - if (existIndex(indexName)) { - return; - } - esClient.indices().delete(d -> d.index(indexName)); - } - - /** - * 创建索引 - * - * @param indexName - * @return - */ - public static void createIndex(String indexName) { - if (existIndex(indexName)) { - throw new RuntimeException("索引已经存在"); - } - try { - CreateIndexResponse createIndexResponse = esClient.indices().create(c -> c.index(indexName)); - // 处理响应 - if (createIndexResponse.acknowledged()) { - log.info(" indexed create successfully."); - } else { - log.info("Failed to create index."); - } - } catch (Exception e) { - // 捕获异常并打印详细错误信息 - e.printStackTrace(); - throw new RuntimeException("创建索引失败,索引名:" + indexName + ",错误信息:" + e.getMessage(), e); - } - } - - /** - * 新增文档 - * @param esBaseModel - * @return - */ - public static boolean addDocument(EsBaseModel esBaseModel) { - try { - ObjectMapper objectMapper = new ObjectMapper(); - String jsonString = objectMapper.writeValueAsString(esBaseModel.getDocumentModel()); - log.info("es新增文档,文档内容:{}", jsonString); - // 创建 IndexRequest 实例 - IndexRequest request = new IndexRequest.Builder() - .index(esBaseModel.getIndexName()) - .id(esBaseModel.getDocumentId()) //指定文档id,不指定会自动生成 - .document(esBaseModel.getDocumentModel()) - .opType(OpType.Create) // 只会在文档 ID 不存在时创建文档 - .build(); - - IndexResponse response = esClient.index(request); - if ("created".equals(response.result())) { - log.info("Document created: " + response.id()); - return true; - } else { - log.info("Document already exists or failed to create."); - return false; - } - } catch (Exception e) { - log.error("es新增文档失败", e); - e.printStackTrace(); - } - return false; - } - - /** - * 更新文档 - * @param esBaseModel - * @return - */ - public boolean updateDocument(EsBaseModel esBaseModel) { - try { - UpdateRequest updateRequest = new UpdateRequest.Builder<>() - .index(esBaseModel.getIndexName()) - .id(esBaseModel.getDocumentId()) - .doc(esBaseModel.getDocumentModel()).build(); - UpdateResponse updateResponse = esClient.update(updateRequest, esBaseModel.getClazz()); - log.info("Document updated: " + updateResponse.id()); - return true; - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } - - /** - * 更新文档指定字段(script 脚本) - * @param esBaseModel - * @param script 脚本内容 - * @param params 传递参数内容 - */ - public void updateDocumentWithScript(EsBaseModel esBaseModel, String script, Map params) { - try { - UpdateRequest updateRequest = new UpdateRequest.Builder<>() - .index(esBaseModel.getIndexName()) - .id(esBaseModel.getDocumentId()) - .script(s -> - s.source(script)// 脚本内容:.source("ctx._source.age += params.increment") - .params(params)) // 传递参数内容:.params("increment",sonData.of(5)) - .build(); - UpdateResponse updateResponse = esClient.update(updateRequest, esBaseModel.getClazz()); - log.info("Document updated: " + updateResponse.id()); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 根据id查询文档 - * @param esBaseModel - * @return - */ - public static T getDocumentById(EsBaseModel esBaseModel) { - try { - GetRequest getRequest = new GetRequest.Builder() - .index(esBaseModel.getIndexName()) - .id(esBaseModel.getDocumentId()) - .build(); - GetResponse getResponse = esClient.get(getRequest, esBaseModel.getClazz()); - if (getResponse.found()) { - return getResponse.source(); - } - } catch (Exception e) { - log.error("es列表查询失败", e); - } - return null; - } - - /** - * 查询文档列表 - * @param searchModel - * @return - */ - public static List getDocumentList(EsSearchModel searchModel) { - List eslist = new ArrayList<>(); - try { - SearchResponse search = esClient.search(buildSearchRequest(searchModel), searchModel.getClazz()); - if (Objects.isNull(search)) { - return eslist; - } - HitsMetadata hits = search.hits(); - if (Objects.isNull(hits)) { - return eslist; - } - List> sourceHitList = hits.hits(); - if (CollectionUtils.isEmpty(sourceHitList)) { - return eslist; - } - sourceHitList.forEach(item -> { - // 处理每个命中 - eslist.add(item.source()); - }); - return eslist; - } catch (Exception e) { - log.error("es列表查询失败", e); - } - return eslist; - } - - /** - * 查询文档数量 - * @param searchModel - * @return - */ - public static long getDocumentCount(EsSearchModel searchModel) { - try { - CountRequest.Builder countRequest = new CountRequest.Builder(); - countRequest.index(searchModel.getIndexName()); - countRequest.query(createBoolQuery(searchModel.getTermQuery(), searchModel.getMatchQuery())); - CountResponse count = esClient.count(countRequest.build()); - if (Objects.isNull(count)) { - log.info("es列表数量查询异常{}", searchModel); - return 0; - } - return count.count(); - } catch (Exception e) { - log.error("es列表数量查询失败", e); - } - return 0; - } - - /** - * 根据id删除文档 - * @param esBaseModel - * @return - */ - public static Boolean deleteDocumentById(EsBaseModel esBaseModel) { - try { - DeleteRequest deleteRequest = new DeleteRequest.Builder() - .index(esBaseModel.getDocumentId()) - .id(esBaseModel.getDocumentId()) - .build(); - DeleteResponse deleteResponse = esClient.delete(deleteRequest); - if ("deleted".equals(deleteResponse.result())) { - log.info("Document deleted: " + deleteResponse.id()); - return true; - } else { - log.info("Document delete failed: " + deleteResponse.id()); - return false; - } - } catch (Exception e) { - log.error("es列表删除失败", e); - } - return false; - } - - /** - * 根据条件删除文档 - * @param searchModel - * @return 删除数量 - */ - public static long deleteDocumentByQuery(EsSearchModel searchModel) { - try { - DeleteByQueryRequest.Builder deleteRequest = new DeleteByQueryRequest.Builder(); - deleteRequest.index(searchModel.getIndexName()); - deleteRequest.query(createBoolQuery(searchModel.getTermQuery(), searchModel.getMatchQuery())); - deleteRequest.refresh(true); //设置删除操作后是否立即刷新索引,使删除结果立即可见 - deleteRequest.timeout(new Time.Builder().time("2s").build()); //设置删除操作的超时时间 - deleteRequest.conflicts(Conflicts.Proceed); //Conflicts.Proceed:在版本冲突时继续删除操作;Conflicts.Abort:在版本冲突时中止删除操作 - DeleteByQueryResponse dResponse = esClient.deleteByQuery(deleteRequest.build()); - if (Objects.nonNull(dResponse)) { - log.info("es条件删除成功,删除数量:{}", dResponse.deleted()); - return dResponse.deleted(); - } - } catch (Exception e) { - log.error("es条件删除数据失败", e); - } - return 0; - } - - /** - * 构建搜索请求对象 - * @param searchModel - * @return - */ - private static SearchRequest buildSearchRequest(EsSearchModel searchModel) { - //定义查询对象 - SearchRequest.Builder searchRequest = new SearchRequest.Builder(); - //设置索引名称 - searchRequest.index(searchModel.getIndexName()); - //分组去重 - if (StringUtils.isNotBlank(searchModel.getRepeatField())) { - searchRequest.collapse(buildCollapse(searchModel)); - } - //设置查询条件 - searchRequest.query(createBoolQuery(searchModel.getTermQuery(), searchModel.getMatchQuery())); - //设置排序规则 - if (searchModel.getSort() != null) { - searchRequest.sort(buildSort(searchModel.getSort())); - } - //设置分页参数 - if (searchModel.getPageSize() != null && searchModel.getPageSize() != null) { - searchRequest.from(searchModel.getPageSize() * (searchModel.getPageNum() - 1)); - searchRequest.size(searchModel.getPageSize()); - } - //设置查询字段/排查字段 - SourceConfig sourceConfig = buildSourceConfig(searchModel.getIncludes(), searchModel.getExcludes()); - if (Objects.nonNull(sourceConfig)) { - searchRequest.source(sourceConfig); - } - return searchRequest.build(); - } - - /** - * 构建查询条件 - * @param termQuery - * @param matchQuery - * @return - */ - private static Query createBoolQuery(Map termQuery, Map matchQuery) { - BoolQuery.Builder cQuery = new BoolQuery.Builder(); - // TermQuery 精准匹配 - if (termQuery != null) { - for (Map.Entry entry : termQuery.entrySet()) { - if (Objects.isNull(entry.getValue())) { - continue; - } - String key = entry.getKey(); - Object value = entry.getValue(); - if (value.getClass().isArray()) { //数组查询,使用 TermsQuery - Object[] values = (Object[]) entry.getValue(); - List objs = Arrays.stream(values) - .map(v -> FieldValue.of(v)) // 将每个对象转换为 FieldValue - .collect(Collectors.toList()); - cQuery.must(new TermsQuery.Builder() - .field(key) - .terms(t -> t.value(objs)) - .build() - ._toQuery()); - } else if (value.toString().contains(" ")) { // 短语查询,使用 MatchPhraseQuery (要严格按照单词顺序字符串中有空格,短信需匹配) - cQuery.must(new MatchPhraseQuery.Builder() - .field(key) - .query(value.toString()) - .build() - ._toQuery()); - } else { // 其他情况,使用 TermQuery 精准匹配 - cQuery.must(new TermQuery.Builder() - .field(key) - .value(value.toString()) - .build() - ._toQuery()); - } - } - } - // MatchQuery 模糊匹配全文检索分词查询 - if (matchQuery != null) { - for (Map.Entry entry : matchQuery.entrySet()) { - if (Objects.isNull(entry.getValue())) { - continue; - } - cQuery.must(new MatchQuery.Builder() - .field(entry.getKey()) - .query(entry.getValue().toString()) - .build() - ._toQuery()); - } - } - return cQuery.build()._toQuery(); - } - - /** - * 构建时间区间查询 - * @param startTime 开始时间 - * @param endTime 结束时间 - * @param fieldName 时间字段 - * @return - */ - public static Query createTimeQuery(String startTime, String endTime, String fieldName) { - DateRangeQuery dataQuery = new DateRangeQuery.Builder() - .field(fieldName) - .build(); - // 时间区间查询 - dataQuery.of(o -> o.gte(startTime)); - dataQuery.of(o -> o.lte(endTime)); - return dataQuery._toRangeQuery()._toQuery(); - } - - - /** - * 设置查询字段/排查字段 - * @param includes 需要字段 - * @param excludes 排除字段 - * @return - */ - private static SourceConfig buildSourceConfig(List includes, List excludes) { - boolean isIncludes = CollectionUtils.isEmpty(includes); - boolean isExcludes = CollectionUtils.isEmpty(excludes); - //设置查询字段/排查字段 - if (isIncludes || isExcludes) { - SourceFilter.Builder sourceFilter = new SourceFilter.Builder(); - if (isIncludes) - sourceFilter.includes(includes); - if (isExcludes) - sourceFilter.excludes(excludes); - return new SourceConfig.Builder().filter(sourceFilter.build()).build(); - } - return null; - } - - - /** - * 构建分组去重 - * @param searchModel - * @return - */ - private static FieldCollapse buildCollapse(EsSearchModel searchModel) { - FieldCollapse.Builder fieldCollapse = new FieldCollapse.Builder(); - //设置分组字段 - fieldCollapse.field(searchModel.getRepeatField()); - //设置嵌套配置 - if (StringUtils.isNotBlank(searchModel.getInnerAlias())) { - InnerHits.Builder innerHits = new InnerHits.Builder(); - //设置别名 - innerHits.name(searchModel.getInnerAlias()); - //设置查询数量 - if (searchModel.getInnerSize() != null) { - innerHits.size(searchModel.getInnerSize()); - } - fieldCollapse.innerHits(InnerHits.of(i -> i.name(searchModel.getInnerAlias()).size(10))); - } - return fieldCollapse.build(); - } - - /** - * 构建排序规则 - * @param sortMap - * @return - */ - private static List buildSort(Map sortMap) { - if (sortMap == null) { - return null; - } - List sortList = new ArrayList<>(); - for (Map.Entry sort : sortMap.entrySet()) { - sortList.add(new SortOptions.Builder().field(f -> f.field(sort.getKey()).order(SortOrder.valueOf(sort.getValue()))).build()); - } - return sortList; - } - - /** - * 案例:组合多条件查询(关于 must、mustNot、should 条件的使用) - */ - public Query combinationQueryTest() { - //query.must():and 文档必须满足该条件,如果不满足,文档将不匹配。 and - //query.should():or 文档可以不满足该条件,但满足该条件时会得分更高;即使不满足,文档也会出现在查询结果中,只是查询结果靠后。 - - //场景1:文档必须符合所有 must 条件和 mustNot 条件,同时至少满足一个 should 条件。如果 should 条件都不满足,文档将被排除不查询出来。 - BoolQuery.Builder query = new BoolQuery.Builder(); - //数字范围查询 - NumberRangeQuery.Builder numberQuery = new NumberRangeQuery.Builder(); - numberQuery.field("age").lte(30.0).build(); - // 构建查询条件 - query.must(o -> o.term(t -> t.field("status").value("active"))) // 必须满足的条件 - .mustNot(o -> o.term(t -> t.field("country").value("China"))) // 不能满足的条件 - .filter(f -> f.bool(bo -> bo - .should(so -> so.range(r -> r.number(numberQuery.build()))) // 至少满足一个 should 条件 - .should(so -> so.term(t -> t.field("gender").value("male"))) // 至少满足一个 should 条件 - .minimumShouldMatch("1") // 至少满足一个 should 条件 也可设置百分比 “50%” - )); - //场景2:文档必须符合所有 must 条件和 mustNot 条件,同时至少满足一个 should 条件。如果 should 条件都不满足,不用做额外的过滤(按照should原生特性处理)。 - query.must(o -> o.bool(bo -> bo - .should(so -> so.range(r -> r.number(numberQuery.build()))) // 至少满足一个 should 条件 - .should(so -> so.term(t -> t.field("gender").value("male"))) // 至少满足一个 should 条件 - .minimumShouldMatch("1") // 至少满足一个 should 条件 - )) - .must(o -> o.term(t -> t.field("status").value("active"))) // 必须满足的条件 - .mustNot(o -> o.term(t -> t.field("country").value("China"))); // 不能满足的条件 - - return query.build()._toQuery(); - } - -} diff --git a/src/main/java/cn/xf/basedemo/config/EsConfig.java b/src/main/java/cn/xf/basedemo/config/EsConfig.java deleted file mode 100644 index 70e2c1c..0000000 --- a/src/main/java/cn/xf/basedemo/config/EsConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -package cn.xf.basedemo.config; - -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.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -/** - * packageName cn.xf.basedemo.config - * @author remaindertime - * @className ElasticsearchConfig - * @date 2024/12/9 - * @description es工具类 - */ -@Component -public class EsConfig { - - @Value("${elasticsearch.host}") - private String elasticsearchHost; - @Value("${elasticsearch.port}") - private int elasticsearchPort; - @Value("${elasticsearch.username}") - private String username; - @Value("${elasticsearch.password}") - private String password; - - /** - -最大连接数 (maxConnTotal):设置总的最大连接数,取决于业务的并发量。500-2000 之间较为合理。 - -每个节点的最大连接数 (maxConnPerRoute):控制每个节点的最大连接数,建议 50-100 之间。 - -IO 线程数 (setIoThreadCount):根据 CPU 核心数设置,通常为 2-4 倍 CPU 核心数。 - -连接超时、套接字超时、获取连接超时:一般设置为 10-30 秒,复杂查询或大数据量操作可适当增加到 20-60 秒。 - -失败监听器 (setFailureListener):自定义重试和故障处理逻辑,确保高可用性。 - */ - @Bean - public ElasticsearchClient elasticsearchClient() { - - // 创建凭证提供者 - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials( - AuthScope.ANY, - new UsernamePasswordCredentials(username, password) - ); - - // 自定义 RestClientBuilder 配置 - RestClientBuilder restClientBuilder = RestClient.builder( - new HttpHost(elasticsearchHost, elasticsearchPort, "http") - ).setHttpClientConfigCallback(httpClientBuilder -> - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider) // 配置认证信息 - ); - // 配置连接超时、套接字超时、获取连接超时 - restClientBuilder.setRequestConfigCallback(builder -> - builder.setConnectTimeout(20000) - .setSocketTimeout(20000) - .setConnectionRequestTimeout(20000) - ); - // 创建 RestClientTransport 和 ElasticsearchClient - RestClient restClient = restClientBuilder.build(); - ElasticsearchTransport transport = new RestClientTransport( - restClient, - new JacksonJsonpMapper() // 使用 Jackson 进行 JSON 处理 - ); - - return new ElasticsearchClient(transport); - } - - /** - window系统本地启动 es8.x 重置密码命令:.\elasticsearch-reset-password -u elastic - */ -} diff --git a/src/main/java/cn/xf/basedemo/controller/business/UserController.java b/src/main/java/cn/xf/basedemo/controller/business/UserController.java index 543c84d..4ee842e 100644 --- a/src/main/java/cn/xf/basedemo/controller/business/UserController.java +++ b/src/main/java/cn/xf/basedemo/controller/business/UserController.java @@ -39,23 +39,4 @@ public class UserController { return RetObj.success(loginUser); } - @Operation(summary = "es同步用户信息", description = "用户信息") - @GetMapping("/syncEs") - public RetObj syncEs(Long userId) { - return userService.syncEs(userId); - } - - @Operation(summary = "es查询用户信息", description = "用户信息") - @GetMapping("/getEsId") - public RetObj getEsId(Long userId) { - return userService.getEsId(userId); - } - - - //发送队列消息 - @Operation(summary = "发送队列消息", description = "发送队列消息") - @GetMapping("/sendMsg") - public RetObj sendMsg(String msg) { - return userService.sendMQMsg(msg); - } } diff --git a/src/main/java/cn/xf/basedemo/mq/RocketMqMsgConsumer.java b/src/main/java/cn/xf/basedemo/mq/RocketMqMsgConsumer.java deleted file mode 100644 index b0f816a..0000000 --- a/src/main/java/cn/xf/basedemo/mq/RocketMqMsgConsumer.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.xf.basedemo.mq; - - -import lombok.extern.slf4j.Slf4j; -import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; -import org.apache.rocketmq.spring.core.RocketMQListener; -import org.springframework.stereotype.Component; - -/** - * RocketMqMsgComsumer - * - * @author 海言 - * @date 2025/10/13 - * @time 14:37 - * @Description - */ -@Slf4j -@Component -@RocketMQMessageListener(topic = "user-topic",consumerGroup = "consumer-group") -public class RocketMqMsgConsumer implements RocketMQListener { - @Override - public void onMessage(String s) { - log.info("接收到消息---------:{}",s); - } -} diff --git a/src/main/java/cn/xf/basedemo/mq/RocketMqMsgProducer.java b/src/main/java/cn/xf/basedemo/mq/RocketMqMsgProducer.java deleted file mode 100644 index 71bdc46..0000000 --- a/src/main/java/cn/xf/basedemo/mq/RocketMqMsgProducer.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.xf.basedemo.mq; - -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.apache.rocketmq.spring.core.RocketMQTemplate; -import org.springframework.stereotype.Service; - -/** - * RocketMqMsgProducer - * - * @author 海言 - * @date 2025/10/13 - * @time 14:34 - * @Description - */ -@Slf4j -@Service -public class RocketMqMsgProducer { - - @Resource - private RocketMQTemplate rocketMQTemplate; - - //发送普通消息 - public void sendMsg(String topic, String msg) { - rocketMQTemplate.convertAndSend(topic, msg); - log.info("发送普通消息:{}", msg); - } - - //发送带标签的消息 - public void sendMsg(String topic, String tag, String msg) { - rocketMQTemplate.convertAndSend(topic + ":" + tag, msg); - } - - //发送延迟消息 - public void sendDelayMsg(String topic, String msg, int delayLevel) { - rocketMQTemplate.syncSendDelayTimeMills(topic, msg, delayLevel); - } - -} \ No newline at end of file diff --git a/src/main/java/cn/xf/basedemo/service/UserService.java b/src/main/java/cn/xf/basedemo/service/UserService.java index 2cbe5d1..d910495 100644 --- a/src/main/java/cn/xf/basedemo/service/UserService.java +++ b/src/main/java/cn/xf/basedemo/service/UserService.java @@ -14,9 +14,4 @@ public interface UserService { RetObj login(LoginInfoReq res); - RetObj syncEs(Long userId); - - RetObj getEsId(Long userId); - - RetObj sendMQMsg(String msg); } diff --git a/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java b/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java index 21ff222..4b6c064 100644 --- a/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java +++ b/src/main/java/cn/xf/basedemo/service/impl/UserServiceImpl.java @@ -1,24 +1,19 @@ package cn.xf.basedemo.service.impl; -import cn.xf.basedemo.common.model.EsBaseModel; import cn.xf.basedemo.common.model.LoginInfo; import cn.xf.basedemo.common.model.LoginUser; import cn.xf.basedemo.common.model.RetObj; -import cn.xf.basedemo.common.utils.EsUtil; import cn.xf.basedemo.common.utils.JwtTokenUtils; import cn.xf.basedemo.common.utils.RSAUtils; -import cn.xf.basedemo.common.utils.StringUtil; import cn.xf.basedemo.config.GlobalConfig; import cn.xf.basedemo.mappers.UserMapper; import cn.xf.basedemo.model.domain.User; -import cn.xf.basedemo.model.req.LoginInfoReq; -import cn.xf.basedemo.mq.RocketMqMsgProducer; +import cn.xf.basedemo.model.res.LoginInfoRes; import cn.xf.basedemo.service.UserService; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -51,9 +46,6 @@ public class UserServiceImpl implements UserService { @Autowired private RedisTemplate redisTemplate; - @Resource - private RocketMqMsgProducer rocketMqMsgProducer; - @Override public RetObj login(LoginInfoReq res) { @@ -99,32 +91,4 @@ public class UserServiceImpl implements UserService { return RetObj.success(loginUser); } - @Override - public RetObj syncEs(Long userId) { - User user = userMapper.selectById(userId); - if (Objects.isNull(user)) { - return RetObj.error("用户不存在"); - } - String index = StringUtil.camelToKebabCase(user.getClass().getSimpleName()); - if (!EsUtil.existIndex(index)) { - EsUtil.createIndex(index); - } - EsUtil.addDocument(new EsBaseModel(index, String.valueOf(user.getId()), user, user.getClass())); - return RetObj.success(); - } - - @Override - public RetObj getEsId(Long userId) { - Object user = EsUtil.getDocumentById(new EsBaseModel("user", String.valueOf(userId), null, User.class)); - if (Objects.nonNull(user)) { - return RetObj.success(user); - } - return RetObj.error("es中不存在该用户"); - } - - @Override - public RetObj sendMQMsg(String msg) { - rocketMqMsgProducer.sendMsg("user-topic", msg); - return RetObj.success(); - } } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index fefc4ca..1964d39 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -1,113 +1,93 @@ spring: + servlet: + multipart: + max-file-size: 20MB + max-request-size: 20MB + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + serialization: + WRITE_DATES_AS_TIMESTAMPS: false + FAIL_ON_EMPTY_BEANS: false datasource: dynamic: primary: master - strict: true #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源. + strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源. hikari: - minimum-idle: 4 maximum-pool-size: 4 + minimum-idle: 4 + leak-detection-threshold: 0 connection-init-sql: SELECT 1 connection-test-query: SELECT 1 datasource: master: #${SERVER_ADDRESS} - url: jdbc:mysql://9.9.9.9:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai + url: jdbc:mysql://localhost:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai username: password: driver-class-name: com.mysql.cj.jdbc.Driver slave: - url: jdbc:mysql://9.9.9.9:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai + url: jdbc:mysql://localhost:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai username: password: driver-class-name: com.mysql.cj.jdbc.Driver + data: redis: - port: 6379 #Redis服务器连接的端口 - host: 9.9.9.9 # Redis服务器的地址 - password: # Redis服务器连接密码(默认为空) - timeout: 5000 # 连接超时时间(毫秒) + port: 6379 + host: localhost + password: + timeout: 5000 lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595 pool: - maxActive: 5000 #最大连接数 - maxIdle: 30 #连接池最大空闲连接数. - minIdle: 5 #连接池最小空闲连接数. - max-wait: 2000 #从连接池中获取连接时的最大等待时间 - time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间. + maxActive: 5000 + maxIdle: 30 + minIdle: 5 + max-wait: 2000 + time-between-eviction-runs: 60s cluster: refresh: - adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。 - period: 60s #刷新redis集群状态周期时间 + adaptive: true + period: 60s global: rsaPublicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC_F5UQC1QWsu3QsESQBz9M-GDA9Atm0qVSvwIsy568lyRLi-nq3VvvnmgrlL4yTbngFzyfb2Dn35cNCHsBvIaGuCY3_PpzPqMzVpxr2QlEkhEX9atnJQ1rWexS8QeZtPjpiIwoQrChTzXjD_sYUkDrqSykFplyivf0NSO2WqCBdwIDAQAB rsaPrivateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL8XlRALVBay7dCwRJAHP0z4YMD0C2bSpVK_AizLnryXJEuL6erdW--eaCuUvjJNueAXPJ9vYOfflw0IewG8hoa4Jjf8-nM-ozNWnGvZCUSSERf1q2clDWtZ7FLxB5m0-OmIjChCsKFPNeMP-xhSQOupLKQWmXKK9_Q1I7ZaoIF3AgMBAAECgYBxTUA61Ry0oL7U_86HP2TO9G4ZuhmQi9EucMaPXOPvmgYRLRIzCbDbMKc_P-BN3zwYnG57cgSZNz9OoPqeGvP_oVTnkoEpVkCSV-JP2p_DK09LdbDqszJXMrxAkPmWGUw8IRMcTJT1xJJcgzFE6T0CmTo-Vk47AnmqfJD4U6o74QJBAPRjVUJKZnrMSnSqKPDL2ThgTo8h7-KFxl_Z-g724lTOFiCmBpi6nCWAcuacFRrrYqxF-r9c4zdIyR7AvLROql8CQQDIK_kRF52dVtwShciZhyeUBLoi0nWV9F8mMGt60NTEER9zPEgPsv2aVn8h97KMWOwmd2Da4EPm25QxOuaKQC_pAkBczcfXp5co9KElkmR_pHl1jiTm97U3qSM-zPDHc_tYxvXiKgoBP4QCPbfkWMsu8MoEr4Jb3vMt0EcHlZtTQTgzAkAfmNla-lhV4sUgY1_T5EK6GbjsED6hag6u74u3ukkrnexR-10ApWdkumydBwV3I_464DM4uZfeVCDjWIHVpuYpAkEA6QLPztGD4V8Q1PqTEeSF3i68CKPM8vO1_mCH2JD7qsqDQcIKkczj5rTg7hlOKwB9V6gSw4CbnOF6moTooRD-cQ -redis: - datasource: - token: - database: 1 - host: 122.112.153.128 - port: 6379 - password: 'redis' - lettuce: - pool: - max-active: 8 - max-wait: -1ms - max-idle: 8 - min-idle: 0 - timeout: 3000ms +springdoc: + api-docs: + path: /v3/api-docs # 自定义 API 文档路径 + swagger-ui: + path: /swagger-ui.html # 自定义 Swagger UI 路径 + enabled: true + info: + title: 文撩 API 文档 + description: 这是文撩平台的 API 文档 + version: v1.0 -oss: - name: alioss - endpoint: ll-oss-pre.lianlianlvyou.com - accessKey: - secretKey: - bucketName: - args: - expireTime: 3600 #过期时间 - contentLengthRange: 2000 #大小限制 -# redis分布式锁 -redisson: - enabled: true - address: 'redis://192.168.10.113:6379' - password: '123456' - database: 5 - connectionPoolSize: 4 - connectionMinimumIdleSize: 4 +mybatis-plus: + configuration: + map-underscore-to-camel-case: false + auto-mapping-behavior: full + #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印 + mapper-locations: classpath*:mapper/**/*Mapper.xml + global-config: + # 逻辑删除配置 + db-config: + update-strategy: IGNORED + # 删除前 + logic-not-delete-value: 1 + # 删除后 + logic-delete-value: 0 -# 阿里云rocketmq -aliyun: - rocketmq: - config: - AccessKey: 1 - SecretKey: 1 - NAMESRV_ADDR: 1 - GROUP_ID: 1 - producer: - enabled: true - -rabbitmq: - configs: - order: #实例名称 - host: 192.168.10.111 - port: 5672 - virtualHost: ll-dev - username: zhangziheng - password: zhangziheng - producer: - enabled: true - exchange: order_status - routingKey: ORDER_COMPLETE - confirmCallback: orderMqConfirmCallback - commonChange: - host: 192.168.10.111 - port: 5672 - virtualHost: ll-dev - username: zhangziheng - password: zhangziheng - producer: - enabled: false - consumer: - enabled: true - subscribeList: - - queue: 'app-business' - messageListener: commonChangeMessageListener +# 参考文章 https://zhuanlan.zhihu.com/p/145359625 +management: + health: + elasticsearch: #禁用健康检查 + enabled: false + endpoints: + web: + exposure: + include: "health" + endpoint: + health: + show-details: always \ No newline at end of file