remove 精简脚手架

This commit is contained in:
DaxPay
2024-05-09 19:31:49 +08:00
parent 055d0b2ed7
commit 5ffa465ea3
50 changed files with 0 additions and 3015 deletions

View File

@@ -1,106 +0,0 @@
package cn.bootx.platform.baseapi.controller;
import cn.bootx.platform.baseapi.core.chinaword.service.ChinaWordService;
import cn.bootx.platform.baseapi.dto.chinaword.ChinaWordDto;
import cn.bootx.platform.baseapi.dto.chinaword.ChinaWordVerifyResult;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordParam;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordVerifyParam;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.hutool.core.io.IoUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.file.Files;
import java.util.List;
/**
* 敏感词
* @author xxm
* @since 2023-08-09
*/
@Tag(name ="敏感词管理")
@RestController
@RequestMapping("/chinaword")
@RequiredArgsConstructor
public class ChinaWordController {
private final ChinaWordService chinaWordService;
@Operation( summary = "添加")
@PostMapping(value = "/add")
public ResResult<Void> add(@RequestBody ChinaWordParam param){
chinaWordService.add(param);
return Res.ok();
}
@Operation( summary = "修改")
@PostMapping(value = "/update")
public ResResult<Void> update(@RequestBody ChinaWordParam param){
chinaWordService.update(param);
return Res.ok();
}
@Operation( summary = "删除")
@DeleteMapping(value = "/delete")
public ResResult<Void> delete(Long id){
chinaWordService.delete(id);
return Res.ok();
}
@Operation( summary = "通过ID查询")
@GetMapping(value = "/findById")
public ResResult<ChinaWordDto> findById(Long id){
return Res.ok(chinaWordService.findById(id));
}
@Operation( summary = "刷新缓存")
@PostMapping(value = "/refresh")
public ResResult<ChinaWordDto> refresh(){
chinaWordService.refresh();
return Res.ok();
}
@Operation( summary = "测试敏感词效果")
@PostMapping(value = "/verify")
public ResResult<ChinaWordVerifyResult> verify(@RequestBody ChinaWordVerifyParam param){
return Res.ok(chinaWordService.verify(param.getText(),param.getSkip(),param.getSymbol()));
}
@Operation( summary = "查询所有")
@GetMapping(value = "/findAll")
public ResResult<List<ChinaWordDto>> findAll(){
return Res.ok(chinaWordService.findAll());
}
@Operation( summary = "分页查询")
@GetMapping(value = "/page")
public ResResult<PageResult<ChinaWordDto>> page(PageParam pageParam, ChinaWordParam query){
return Res.ok(chinaWordService.page(pageParam,query));
}
@Operation(summary = "批量导入")
@PostMapping("/importBatch")
public ResResult<Void> local(MultipartFile file, String type) throws IOException {
chinaWordService.importBatch(file, type);
return Res.ok();
}
@Operation(summary = "获取模板")
@GetMapping("/getTemplate")
public ResponseEntity<byte[]> getTemplate() throws IOException {
InputStream is = Files.newInputStream(new File("D:/data/xxxx.xlsx").toPath());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(IoUtil.readBytes(is), headers, HttpStatus.OK);
}
}

View File

@@ -1,90 +0,0 @@
package cn.bootx.platform.baseapi.controller;
import cn.bootx.platform.baseapi.core.dataresult.entity.DataResultSql;
import cn.bootx.platform.baseapi.core.dataresult.service.DataResultSqlService;
import cn.bootx.platform.baseapi.core.dataresult.service.SqlQueryService;
import cn.bootx.platform.baseapi.dto.dataresult.SqlQueryResult;
import cn.bootx.platform.baseapi.param.dataresult.SqlQueryParam;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.hutool.db.PageResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* SQL查询
*
* @author xxm
* @since 2023/3/9
*/
@Tag(name = "SQL查询")
@RestController
@RequestMapping("/data/result")
@RequiredArgsConstructor
public class DataResultController {
private final DataResultSqlService dataResultSqlService;
private final SqlQueryService sqlQueryService;
@Operation(summary = "分页查询")
@GetMapping("/page")
public ResResult<PageResult<DataResultSql>> page(){
return Res.ok(dataResultSqlService.page());
}
@Operation(summary = "新建")
@PostMapping("/add")
public ResResult<Void> add(){
dataResultSqlService.add();
return Res.ok();
}
@Operation(summary = "修改")
@PostMapping("/update")
public ResResult<Void> update(){
dataResultSqlService.update();
return Res.ok();
}
@Operation(summary = "测试SQL解析和执行")
@PostMapping("/test")
public ResResult<Void> test(@RequestBody Map<String, Object> map) {
dataResultSqlService.querySql(map);
return Res.ok();
}
// @Operation(summary = "通过SQL查出结果字段")
// @PostMapping("/queryFieldBySql")
// public ResResult<List<String>> queryFieldBySql(@RequestBody SqlQueryParam param) {
// return Res.ok(dataResultService.queryFieldBySql(param));
// }
@Operation(summary = "执行SQL查询语句")
@PostMapping("/querySql")
public ResResult<SqlQueryResult> querySql(@RequestBody SqlQueryParam param, PageParam pageParam){
return Res.ok(sqlQueryService.query(param,pageParam));
}
@SneakyThrows
@Operation(summary = "导出SQL查询的结果")
@PostMapping("/exportQueryResult")
public ResponseEntity<byte[]> exportQueryResult(@RequestBody SqlQueryParam param, @ParameterObject PageParam pageParam){
byte[] bytes = sqlQueryService.exportQueryResult(param,pageParam);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
}

View File

@@ -1,122 +0,0 @@
package cn.bootx.platform.baseapi.controller;
import cn.bootx.platform.baseapi.dto.dynamicsource.DynamicDataSourceDto;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.dto.KeyValue;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.baseapi.core.dynamicsource.service.DynamicDataSourceService;
import cn.bootx.platform.baseapi.param.dynamicsource.DynamicDataSourceParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 动态数据源管理
*
* @author xxm
* @since 2022-09-24
*/
@Tag(name = "动态数据源管理")
@RestController
@RequestMapping("/dynamic/source")
@RequiredArgsConstructor
public class DynamicDataSourceController {
private final DynamicDataSourceService dynamicDataSourceService;
@Operation(summary = "添加")
@PostMapping(value = "/add")
public ResResult<Void> add(@RequestBody DynamicDataSourceParam param) {
dynamicDataSourceService.add(param);
return Res.ok();
}
@Operation(summary = "修改")
@PostMapping(value = "/update")
public ResResult<Void> update(@RequestBody DynamicDataSourceParam param) {
dynamicDataSourceService.update(param);
return Res.ok();
}
@Operation(summary = "分页查询")
@GetMapping(value = "/page")
public ResResult<PageResult<DynamicDataSourceDto>> page(PageParam pageParam,
DynamicDataSourceParam dynamicDataSourceParam) {
return Res.ok(dynamicDataSourceService.page(pageParam, dynamicDataSourceParam));
}
@Operation(summary = "通过ID查询")
@GetMapping(value = "/findById")
public ResResult<DynamicDataSourceDto> findById(Long id) {
return Res.ok(dynamicDataSourceService.findById(id));
}
@Operation(summary = "编码是否被使用")
@GetMapping("/existsByCode")
public ResResult<Boolean> existsByCode(String code) {
return Res.ok(dynamicDataSourceService.existsByCode(code));
}
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public ResResult<Boolean> existsByCode(String code, Long id) {
return Res.ok(dynamicDataSourceService.existsByCode(code, id));
}
@Operation(summary = "查询所有")
@GetMapping(value = "/findAll")
public ResResult<List<DynamicDataSourceDto>> findAll() {
return Res.ok(dynamicDataSourceService.findAll());
}
@Operation(summary = "删除")
@DeleteMapping(value = "/delete")
public ResResult<Void> delete(Long id) {
dynamicDataSourceService.delete(id);
return Res.ok();
}
@Operation(summary = "测试连接(根据参数)")
@PostMapping(value = "/testConnection")
public ResResult<String> testConnection(@RequestBody DynamicDataSourceParam param) {
return Res.ok(dynamicDataSourceService.testConnection(param));
}
@Operation(summary = "测试连接(根据主键ID)")
@GetMapping(value = "/testConnectionById")
public ResResult<String> testConnectionById(Long id) {
return Res.ok(dynamicDataSourceService.testConnection(id));
}
@Operation(summary = "根据id进行添加到连接池中")
@PostMapping(value = "/addDynamicDataSourceById")
public ResResult<String> addDynamicDataSourceById(Long id) {
dynamicDataSourceService.addDynamicDataSourceById(id);
return Res.ok();
}
@Operation(summary = "是否已经添加到连接池中")
@GetMapping(value = "/existsByDataSourceKey")
public ResResult<Boolean> existsByDataSourceKey(String code) {
return Res.ok(dynamicDataSourceService.existsByDataSourceKey(code));
}
@Operation(summary = "查询当前数据源列表")
@GetMapping(value = "/findAllDataSource")
public ResResult<List<KeyValue>> findAllDataSource() {
return Res.ok(dynamicDataSourceService.findAllDataSource());
}
@Operation(summary = "从数据源列表中删除指定数据源")
@DeleteMapping("/removeDataSourceByKey")
public ResResult<Void> removeDataSourceByKey(String key) {
dynamicDataSourceService.removeDataSourceByKey(key);
return Res.ok();
}
}

View File

@@ -1,82 +0,0 @@
package cn.bootx.platform.baseapi.controller;
import cn.bootx.platform.baseapi.dto.dynamicform.DynamicFormDto;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.baseapi.core.dynamicform.service.DynamicFormService;
import cn.bootx.platform.baseapi.param.dynamicform.DynamicFormParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 动态表单
*
* @author xxm
* @since 2022-07-28
*/
@Tag(name = "动态表单")
@RestController
@RequestMapping("/dynamic/form")
@RequiredArgsConstructor
public class DynamicFormController {
private final DynamicFormService dynamicFormService;
@Operation(summary = "添加")
@PostMapping(value = "/add")
public ResResult<Void> add(@RequestBody DynamicFormParam param) {
dynamicFormService.add(param);
return Res.ok();
}
@Operation(summary = "修改")
@PostMapping(value = "/update")
public ResResult<Void> update(@RequestBody DynamicFormParam param) {
dynamicFormService.update(param);
return Res.ok();
}
@Operation(summary = "删除")
@DeleteMapping(value = "/delete")
public ResResult<Void> delete(Long id) {
dynamicFormService.delete(id);
return Res.ok();
}
@Operation(summary = "通过ID查询")
@GetMapping(value = "/findById")
public ResResult<DynamicFormDto> findById(Long id) {
return Res.ok(dynamicFormService.findById(id));
}
@Operation(summary = "查询所有")
@GetMapping(value = "/findAll")
public ResResult<List<DynamicFormDto>> findAll() {
return Res.ok(dynamicFormService.findAll());
}
@Operation(summary = "分页查询")
@GetMapping(value = "/page")
public ResResult<PageResult<DynamicFormDto>> page(PageParam pageParam, DynamicFormParam dynamicFormParam) {
return Res.ok(dynamicFormService.page(pageParam, dynamicFormParam));
}
@Operation(summary = "编码是否被使用")
@GetMapping("/existsByCode")
public ResResult<Boolean> existsByCode(String code) {
return Res.ok(dynamicFormService.existsByCode(code));
}
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public ResResult<Boolean> existsByCode(String code, Long id) {
return Res.ok(dynamicFormService.existsByCode(code, id));
}
}

View File

@@ -1,21 +0,0 @@
package cn.bootx.platform.baseapi.controller;
import cn.bootx.platform.baseapi.core.dynamicform.service.DynamicFormDataService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xxm
* @since 2022/8/13
*/
@Tag(name = "动态表单数据")
@RestController
@RequestMapping("/dynamic/form/data")
@RequiredArgsConstructor
public class DynamicFormDataController {
private final DynamicFormDataService dynamicFormDataService;
}

View File

@@ -1,94 +0,0 @@
package cn.bootx.platform.baseapi.controller;
import cn.bootx.platform.baseapi.core.template.service.GeneralTemplateService;
import cn.bootx.platform.baseapi.dto.template.GeneralTemplateDto;
import cn.bootx.platform.baseapi.param.template.GeneralTemplateParam;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 通用模板管理
* @author xxm
* @since 2023-08-12
*/
@Tag(name ="通用模板管理")
@RestController
@RequestMapping("/general/template")
@RequiredArgsConstructor
public class GeneralTemplateController {
private final GeneralTemplateService generalTemplateService;
@Operation( summary = "添加")
@PostMapping(value = "/add")
public ResResult<Void> add(@RequestBody GeneralTemplateParam param){
generalTemplateService.add(param);
return Res.ok();
}
@Operation( summary = "修改")
@PostMapping(value = "/update")
public ResResult<Void> update(@RequestBody GeneralTemplateParam param){
generalTemplateService.update(param);
return Res.ok();
}
@Operation( summary = "删除")
@DeleteMapping(value = "/delete")
public ResResult<Void> delete(Long id){
generalTemplateService.delete(id);
return Res.ok();
}
@Operation(summary = "批量删除")
@DeleteMapping("/deleteBatch")
public ResResult<Void> deleteBatch(@RequestBody List<Long> ids) {
generalTemplateService.deleteBatch(ids);
return Res.ok();
}
@Operation( summary = "通过ID查询")
@GetMapping(value = "/findById")
public ResResult<GeneralTemplateDto> findById(Long id){
return Res.ok(generalTemplateService.findById(id));
}
@Operation( summary = "通过Code查询")
@GetMapping(value = "/findByCode")
public ResResult<GeneralTemplateDto> findByCode(String code){
return Res.ok(generalTemplateService.findByCode(code));
}
@Operation(summary = "编码是否被使用")
@GetMapping("/existsByCode")
public ResResult<Boolean> existsByCode(String code) {
return Res.ok(generalTemplateService.existsByCode(code));
}
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public ResResult<Boolean> existsByCode(String code, Long id) {
return Res.ok(generalTemplateService.existsByCode(code, id));
}
@Operation( summary = "查询所有")
@GetMapping(value = "/findAll")
public ResResult<List<GeneralTemplateDto>> findAll(){
return Res.ok(generalTemplateService.findAll());
}
@Operation( summary = "分页查询")
@GetMapping(value = "/page")
public ResResult<PageResult<GeneralTemplateDto>> page(PageParam pageParam, GeneralTemplateParam query){
return Res.ok(generalTemplateService.page(pageParam,query));
}
}

View File

@@ -1,22 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.convert;
import cn.bootx.platform.baseapi.core.chinaword.entity.ChinaWord;
import cn.bootx.platform.baseapi.dto.chinaword.ChinaWordDto;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordParam;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 敏感词
* @author xxm
* @since 2023-08-09
*/
@Mapper
public interface ChinaWordConvert {
ChinaWordConvert CONVERT = Mappers.getMapper(ChinaWordConvert.class);
ChinaWord convert(ChinaWordParam in);
ChinaWordDto convert(ChinaWord in);
}

View File

@@ -1,30 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
public class ChinaWordImportType implements Converter<String> {
@Override
public Class<?> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里读的时候会调用
*
* @param context
* @return
*/
@Override
public String convertToJavaData(ReadConverterContext<?> context) {
return "自定义:" + context.getReadCellData().getStringValue();
}
}

View File

@@ -1,39 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.dao;
import cn.bootx.platform.baseapi.core.chinaword.entity.ChinaWord;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordParam;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.common.query.generator.QueryGenerator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 敏感词
* @author xxm
* @since 2023-08-09
*/
@Repository
@RequiredArgsConstructor
public class ChinaWordManager extends BaseManager<ChinaWordMapper, ChinaWord> {
public List<ChinaWord> findAllByEnable(boolean enable){
return findAllByField(ChinaWord::getEnable,enable);
}
/**
* 分页
*/
public Page<ChinaWord> page(PageParam pageParam, ChinaWordParam param) {
Page<ChinaWord> mpPage = MpUtil.getMpPage(pageParam, ChinaWord.class);
QueryWrapper<ChinaWord> wrapper = QueryGenerator.generator(param, this.getEntityClass());
wrapper.select(this.getEntityClass(),MpUtil::excludeBigField)
.orderByDesc(MpUtil.getColumnName(ChinaWord::getId));
return this.page(mpPage,wrapper);
}
}

View File

@@ -1,14 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.dao;
import cn.bootx.platform.baseapi.core.chinaword.entity.ChinaWord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 敏感词
* @author xxm
* @since 2023-08-09
*/
@Mapper
public interface ChinaWordMapper extends BaseMapper<ChinaWord> {
}

View File

@@ -1,52 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.entity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import cn.bootx.platform.baseapi.core.chinaword.convert.ChinaWordConvert;
import cn.bootx.platform.baseapi.dto.chinaword.ChinaWordDto;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordParam;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpDelEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 敏感词
* @author xxm
* @since 2023/8/8
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName(value = "base_china_word",autoResultMap = true)
public class ChinaWord extends MpDelEntity implements EntityBaseFunction<ChinaWordDto> {
/** 敏感词 */
@DbColumn(comment = "敏感词")
private String word;
/** 类型 */
@DbColumn(comment = "分类")
private String type;
/** 描述 */
@DbColumn(comment = "描述")
private String description;
/** 是否启用 */
@DbColumn(comment = "是否启用")
private Boolean enable;
@Schema(description = "是否是白名单名词")
private Boolean white;
/** 创建对象 */
public static ChinaWord init(ChinaWordParam in) {
return ChinaWordConvert.CONVERT.convert(in);
}
/** 转换成dto */
@Override
public ChinaWordDto toDto() {
return ChinaWordConvert.CONVERT.convert(this);
}
}

View File

@@ -1,171 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.service;
import cn.bootx.platform.baseapi.core.chinaword.dao.ChinaWordManager;
import cn.bootx.platform.baseapi.core.chinaword.entity.ChinaWord;
import cn.bootx.platform.baseapi.core.chinaword.wordfilter.WordContext;
import cn.bootx.platform.baseapi.core.chinaword.wordfilter.WordFilter;
import cn.bootx.platform.baseapi.core.chinaword.wordfilter.WordType;
import cn.bootx.platform.baseapi.dto.chinaword.ChinaWordDto;
import cn.bootx.platform.baseapi.dto.chinaword.ChinaWordVerifyResult;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordImportParam;
import cn.bootx.platform.baseapi.param.chinaword.ChinaWordParam;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.ResultConvertUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.event.SyncReadListener;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 敏感词服务
* @author xxm
* @since 2023/8/9
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ChinaWordService {
private final WordContext wordContext;
private final WordFilter wordFilter;
private final ChinaWordManager chinaWordManager;
/**
* 添加
*/
public void add(ChinaWordParam param){
ChinaWord chinaWord = ChinaWord.init(param);
this.updateWord(chinaWord);
chinaWordManager.save(chinaWord);
}
/**
* 批量导入
*/
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public void importBatch(MultipartFile file, String type){
InputStream inputStream = file.getInputStream();
//同步读取文件内容
SyncReadListener syncReadListener = new SyncReadListener();
EasyExcel.read(inputStream, syncReadListener)
.head(ChinaWordImportParam.class)
.sheet().doRead();
syncReadListener.getList();
}
/**
* 修改
*/
public void update(ChinaWordParam param){
ChinaWord ChinaWord = chinaWordManager.findById(param.getId()).orElseThrow(DataNotExistException::new);
BeanUtil.copyProperties(param,ChinaWord, CopyOptions.create().ignoreNullValue());
refresh();
chinaWordManager.updateById(ChinaWord);
}
/**
* 分页
*/
public PageResult<ChinaWordDto> page(PageParam pageParam, ChinaWordParam query){
return MpUtil.convert2DtoPageResult(chinaWordManager.page(pageParam,query));
}
/**
* 获取单条
*/
public ChinaWordDto findById(Long id){
return chinaWordManager.findById(id).map(ChinaWord::toDto).orElseThrow(DataNotExistException::new);
}
/**
* 获取全部
*/
public List<ChinaWordDto> findAll(){
return ResultConvertUtil.dtoListConvert(chinaWordManager.findAll());
}
/**
* 删除
*/
public void delete(Long id){
refresh();
chinaWordManager.deleteById(id);
}
/**
* 测试敏感词效果
*/
public ChinaWordVerifyResult verify(String text, int skip, char symbol){
ChinaWordVerifyResult result = new ChinaWordVerifyResult();
if (wordFilter.include(text,skip)) {
String replaceText = wordFilter.replace(text, skip, symbol);
int count = wordFilter.wordCount(text, skip);
Set<String> wordList = wordFilter.wordList(text, skip);
result.setText(replaceText)
.setCount(count)
.setSensitiveWords(wordList)
.setSensitive(true);
}
return result;
}
/**
* 刷新缓存
*/
public void refresh(){
initData();
}
/**
* 更新敏感词库
*/
public void updateWord(ChinaWord chinaWord){
if (Objects.equals(chinaWord.getEnable(),true)){
if (Objects.equals(chinaWord.getWhite(),true)){
wordContext.addWord(Collections.singleton(chinaWord.getWord()), WordType.WHITE);
} else {
wordContext.addWord(Collections.singleton(chinaWord.getWord()), WordType.BLACK);
}
}
}
/**
* 初始化数据
*/
@EventListener(WebServerInitializedEvent.class)
public void initData(){
List<ChinaWord> chinaWords = chinaWordManager.findAllByEnable(true);
// 黑名单
Set<String> black = chinaWords.stream()
.filter(o -> Objects.equals(o.getWhite(), false))
.map(ChinaWord::getWord)
.collect(Collectors.toSet());
// 白名单
Set<String> white = chinaWords.stream()
.filter(o -> Objects.equals(o.getWhite(), true))
.map(ChinaWord::getWord)
.collect(Collectors.toSet());
wordContext.initKeyWord(black,white);
}
}

View File

@@ -1,16 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.wordfilter;
/**
* 结束类型定义
*
* @author minghu.zhang
* @date 11:37 2020/11/11
**/
public enum EndType {
/**
* 有下一个,结束
*/
HAS_NEXT, IS_END
}

View File

@@ -1,30 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.wordfilter;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 敏感词标记
*
* @author minghu.zhang
*/
@Getter
@Setter
public class FlagIndex {
/**
* 标记结果
*/
private boolean flag;
/**
* 是否黑名单词汇
*/
private boolean isWhiteWord;
/**
* 标记索引
*/
private List<Integer> index;
}

View File

@@ -1,149 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.wordfilter;
import lombok.Getter;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static cn.bootx.platform.baseapi.code.WordFilterCode.IS_END;
import static cn.bootx.platform.baseapi.code.WordFilterCode.IS_WHITE_WORD;
/**
* 词库上下文环境
* <p>
* 初始化敏感词库将敏感词加入到HashMap中构建DFA算法模型
*
* @author minghu.zhang
*/
@Getter
@Service
@Component
@SuppressWarnings({"rawtypes", "unchecked"})
public class WordContext {
/**
* 敏感词字典
*/
private final Map wordMap = new HashMap(1024);
/**
* 初始化敏感词库
*/
public synchronized void initKeyWord(Iterable<String> blackList,Iterable<String> whiteList) {
try {
wordMap.clear();
// 将敏感词库加入到HashMap中
addWord(blackList, WordType.BLACK);
// 将非敏感词库也加入到HashMap中
addWord(whiteList, WordType.WHITE );
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 读取敏感词库将敏感词放入HashSet中构建一个DFA算法模型<br>
* 中 = { isEnd = 0 国 = {<br>
* isEnd = 1 人 = {isEnd = 0 民 = {isEnd = 1} } 男 = { isEnd = 0 人 = { isEnd = 1 }
* } } } 五 = { isEnd = 0 星 = { isEnd = 0 红 = { isEnd = 0 旗 = { isEnd = 1 } } } }
*/
public synchronized void addWord(Iterable<String> wordList, WordType wordType) {
Map nowMap;
Map<String, String> newWorMap;
// 迭代keyWordSet
for (String key : wordList) {
nowMap = wordMap;
for (int i = 0; i < key.length(); i++) {
// 转换成char型
char keyChar = key.charAt(i);
// 获取
Object wordMap = nowMap.get(keyChar);
// 如果存在该key直接赋值
if (wordMap != null) {
nowMap = (Map) wordMap;
} else {
// 不存在则构建一个map同时将isEnd设置为0因为他不是最后一个
newWorMap = new HashMap<>(4);
// 不是最后一个
newWorMap.put(IS_END, String.valueOf(EndType.HAS_NEXT.ordinal()));
nowMap.put(keyChar, newWorMap);
nowMap = newWorMap;
}
if (i == key.length() - 1) {
// 最后一个
nowMap.put(IS_END, String.valueOf(EndType.IS_END.ordinal()));
nowMap.put(IS_WHITE_WORD, String.valueOf(wordType.ordinal()));
}
}
}
}
/**
* 在线删除敏感词
*
* @param wordList 敏感词列表
* @param wordType 黑名单 BLACk白名单WHITE
*/
public void removeWord(Iterable<String> wordList, WordType wordType) {
Map nowMap;
for (String key : wordList) {
List<Map> cacheList = new ArrayList<>();
nowMap = wordMap;
for (int i = 0; i < key.length(); i++) {
char keyChar = key.charAt(i);
Object map = nowMap.get(keyChar);
if (map != null) {
nowMap = (Map) map;
cacheList.add(nowMap);
} else {
return;
}
if (i == key.length() - 1) {
char[] keys = key.toCharArray();
boolean cleanable = false;
char lastChar = 0;
for (int j = cacheList.size() - 1; j >= 0; j--) {
Map cacheMap = cacheList.get(j);
if (j == cacheList.size() - 1) {
if (String.valueOf(WordType.BLACK.ordinal()).equals(cacheMap.get(IS_WHITE_WORD))) {
if (wordType == WordType.WHITE) {
return;
}
}
if (String.valueOf(WordType.WHITE.ordinal()).equals(cacheMap.get(IS_WHITE_WORD))) {
if (wordType == WordType.BLACK) {
return;
}
}
cacheMap.remove(IS_WHITE_WORD);
cacheMap.remove(IS_END);
if (cacheMap.isEmpty()) {
cleanable = true;
continue;
}
}
if (cleanable) {
Object isEnd = cacheMap.get(IS_END);
if (String.valueOf(EndType.IS_END.ordinal()).equals(isEnd)) {
cleanable = false;
}
cacheMap.remove(lastChar);
}
lastChar = keys[j];
}
if (cleanable) {
wordMap.remove(lastChar);
}
}
}
}
}
}

View File

@@ -1,214 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.wordfilter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* 敏感词过滤器
*
* @author minghu.zhang
*/
@Component
@RequiredArgsConstructor
@SuppressWarnings("rawtypes")
public class WordFilter {
private final WordContext context;
/**
* 替换敏感词
*
* @param text 输入文本
*/
public String replace(final String text) {
return replace(text, 0, '*');
}
/**
* 替换敏感词
* 查找敏感词,距离越长,过滤越严格,效率越低,开发者可以根据具体需求设置,
* 这里以“紧急”为敏感词举例,以此类推:
* 0 匹配紧急
* 1 匹配不紧不急紧x急
* 2 匹配紧急紧x急紧xx急
*
* @param text 输入文本
* @param symbol 替换符号
*/
public String replace(final String text, final char symbol) {
return replace(text, 0, symbol);
}
/**
* 替换敏感词
*
* @param text 输入文本
* @param skip 文本距离
* @param symbol 替换符号
*/
public String replace(final String text, final int skip, final char symbol) {
char[] charset = text.toCharArray();
for (int i = 0; i < charset.length; i++) {
FlagIndex fi = getFlagIndex(charset, i, skip);
if (fi.isFlag()) {
if (!fi.isWhiteWord()) {
for (int j : fi.getIndex()) {
charset[j] = symbol;
}
} else {
i += fi.getIndex().size() - 1;
}
}
}
return new String(charset);
}
/**
* 是否包含敏感词
*
* @param text 输入文本
*/
public boolean include(final String text) {
return include(text, 0);
}
/**
* 是否包含敏感词, 程序会跳过不同的距离,
* 查找敏感词,距离越长,过滤越严格,效率越低,开发者可以根据具体需求设置,
* 这里以“紧急”为敏感词举例,以此类推:
* 0 匹配紧急
* 1 匹配不紧不急紧x急
* 2 匹配紧急紧x急紧xx急
*
* @param text 输入文本
* @param skip 文本距离
*/
public boolean include(final String text, final int skip) {
boolean include = false;
char[] charset = text.toCharArray();
for (int i = 0; i < charset.length; i++) {
FlagIndex fi = getFlagIndex(charset, i, skip);
if(fi.isFlag()) {
if (fi.isWhiteWord()) {
i += fi.getIndex().size() - 1;
} else {
include = true;
break;
}
}
}
return include;
}
/**
* 获取敏感词数量
*
* @param text 输入文本
*/
public int wordCount(final String text) {
return wordCount(text, 0);
}
/**
* 获取敏感词数量
*
* @param text 输入文本
* @param skip 文本距离
*/
public int wordCount(final String text, final int skip) {
int count = 0;
char[] charset = text.toCharArray();
for (int i = 0; i < charset.length; i++) {
FlagIndex fi = getFlagIndex(charset, i, skip);
if (fi.isFlag()) {
if(fi.isWhiteWord()) {
i += fi.getIndex().size() - 1;
} else {
count++;
}
}
}
return count;
}
/**
* 获取敏感词列表
*
* @param text 输入文本
*/
public Set<String> wordList(String text) {
return wordList(text, 0);
}
/**
* 获取敏感词列表
*
* @param text 输入文本
* @param skip 文本距离
*/
public Set<String> wordList(final String text, final int skip) {
Set<String> wordSet = new LinkedHashSet<>();
char[] charset = text.toCharArray();
for (int i = 0; i < charset.length; i++) {
FlagIndex fi = getFlagIndex(charset, i, skip);
if (fi.isFlag()) {
if(fi.isWhiteWord()) {
i += fi.getIndex().size() - 1;
} else {
StringBuilder builder = new StringBuilder();
for (int j : fi.getIndex()) {
char word = text.charAt(j);
builder.append(word);
}
wordSet.add(builder.toString());
}
}
}
return wordSet;
}
/**
* 获取标记索引
*
* @param charset 输入文本
* @param begin 检测起始
* @param skip 文本距离
*/
private FlagIndex getFlagIndex(final char[] charset, final int begin, final int skip) {
FlagIndex fi = new FlagIndex();
Map current = context.getWordMap();
boolean flag = false;
int count = 0;
List<Integer> index = new ArrayList<>();
for (int i = begin; i < charset.length; i++) {
char word = charset[i];
Map mapTree = (Map) current.get(word);
if (count > skip || (i == begin && Objects.isNull(mapTree))) {
break;
}
if (Objects.nonNull(mapTree)) {
current = mapTree;
count = 0;
index.add(i);
} else {
count++;
if (flag && count > skip) {
break;
}
}
if ("1".equals(current.get("isEnd"))) {
flag = true;
}
if ("1".equals(current.get("isWhiteWord"))) {
fi.setWhiteWord(true);
break;
}
}
fi.setFlag(flag);
fi.setIndex(index);
return fi;
}
}

View File

@@ -1,15 +0,0 @@
package cn.bootx.platform.baseapi.core.chinaword.wordfilter;
/**
* 词汇类型
*
* @author minghu.zhang
* @date 11:37 2020/11/11
**/
public enum WordType {
/**
* 黑名单/白名单
*/
BLACK, WHITE
}

View File

@@ -1,22 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.convert;
import cn.bootx.platform.baseapi.core.dataresult.entity.DataResultSql;
import cn.bootx.platform.baseapi.dto.dataresult.QuerySqlDto;
import cn.bootx.platform.baseapi.param.dataresult.DataResultSqlParam;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author xxm
* @since 2023/3/13
*/
@Mapper
public interface DataResultSqlConvert {
DataResultSqlConvert CONVERT = Mappers.getMapper(DataResultSqlConvert.class);
QuerySqlDto convert(DataResultSql in);
DataResultSql convert(DataResultSqlParam in);
}

View File

@@ -1,16 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.dao;
import cn.bootx.platform.baseapi.core.dataresult.entity.DataResultSql;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
* @author xxm
* @since 2023/3/9
*/
@Slf4j
@Repository
public class DataResultSqlManager extends BaseManager<DataResultSqlMapper, DataResultSql> {
}

View File

@@ -1,14 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.dao;
import cn.bootx.platform.baseapi.core.dataresult.entity.DataResultSql;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xxm
* @since 2023/3/9
*/
@Mapper
public interface DataResultSqlMapper extends BaseMapper<DataResultSql> {
}

View File

@@ -1,35 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.dao;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.ResultType;
import org.apache.ibatis.annotations.Select;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 查询语句
* @author xxm
* @since 2023/8/29
*/
@Mapper
public interface SqlQueryMapper {
/**
* 查询带分页
* @param page 分页
* @param sql 查询语句
*/
@Select("${sql}")
Page<Map<String,Object>> queryByPage(Page<?> page, @Param("sql") String sql);
/**
* 查询
* @param sql 查询语句
*/
@Select("${sql}")
List<Map<String,Object>> query(@Param("sql") String sql);
}

View File

@@ -1,68 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.entity;
import cn.bootx.platform.baseapi.core.dataresult.convert.DataResultSqlConvert;
import cn.bootx.platform.baseapi.dto.dataresult.QuerySqlDto;
import cn.bootx.platform.baseapi.dto.dataresult.SqlField;
import cn.bootx.platform.baseapi.dto.dataresult.SqlParam;
import cn.bootx.platform.common.core.annotation.BigField;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.platform.common.mybatisplus.handler.JacksonRawTypeHandler;
import cn.bootx.table.modify.annotation.DbTable;
import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType;
import cn.bootx.table.modify.mysql.constants.MySqlFieldTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 数据集SQL语句
*
* @author xxm
* @since 2023/3/9
*/
@EqualsAndHashCode(callSuper = true)
@Data
//@DbTable(comment = "数据集SQL语句")
@Accessors(chain = true)
@TableName(value = "base_data_result_sql", autoResultMap = true)
public class DataResultSql extends MpBaseEntity implements EntityBaseFunction<QuerySqlDto> {
/** 数据源ID */
private Long databaseId;
/** 名称 */
private String name;
/** 是否集合 */
private Boolean isList;
/** sql语句 */
@BigField
private String sql;
/** SQL查询参数 */
@BigField
@TableField(typeHandler = JacksonRawTypeHandler.class)
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
private List<SqlParam> params;
/** SQL查询结果字段 */
@BigField
@TableField(typeHandler = JacksonRawTypeHandler.class)
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
private List<SqlField> fields;
/**
* 转换
*/
@Override
public QuerySqlDto toDto() {
return DataResultSqlConvert.CONVERT.convert(this);
}
}

View File

@@ -1,166 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.service;
import cn.bootx.platform.baseapi.code.QuerySqlCode;
import cn.bootx.platform.baseapi.core.dataresult.dao.DataResultSqlManager;
import cn.bootx.platform.baseapi.core.dataresult.entity.DataResultSql;
import cn.bootx.platform.baseapi.dto.dataresult.SqlParam;
import cn.bootx.platform.baseapi.core.dynamicsource.dao.DynamicDataSourceManager;
import cn.bootx.platform.baseapi.core.dynamicsource.entity.DynamicDataSource;
import cn.bootx.platform.baseapi.core.dynamicsource.service.DynamicDataSourceService;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.db.PageResult;
import cn.hutool.db.handler.EntityHandler;
import cn.hutool.db.handler.EntityListHandler;
import cn.hutool.db.sql.SqlExecutor;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.parsing.GenericTokenParser;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author xxm
* @since 2023/3/9
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DataResultSqlService {
private final DynamicRoutingDataSource dynamicRoutingDataSource;
private final DynamicDataSourceManager dynamicDataSourceManager;
private final DynamicDataSourceService dynamicDataSourceService;
private final DataResultSqlManager dataResultSqlManager;
/**
* 添加查询语句
*/
public void add() {
}
/**
* 修改
*/
public void update(){
}
/**
* 分页查询
*/
public PageResult<DataResultSql> page(){
return new PageResult<>();
}
/**
* 执行SQL查询
*/
@SneakyThrows
public Object querySql(Map<String, Object> map) {
// 获取SQL语句, 将 #{} 和 ${} 元素进行解析和替换
String sql = "select * from iam_client where system=#{system}";
DataResultSql dataResultSql = new DataResultSql().setDatabaseId(1633376006887067648L).setIsList(true).setSql(sql);
SqlAndParam sqlAndParam = this.sqlParamParser(dataResultSql, map);
// 对SQL语句进行解析
DataSource dataSource = this.getDataSource(dataResultSql.getDatabaseId());
Connection connection = dataSource.getConnection();
if (Objects.equals(dataResultSql.getIsList(), true)) {
return SqlExecutor.query(connection, sqlAndParam.sql, new EntityListHandler(),
ArrayUtil.toArray(sqlAndParam.param, Object.class));
}
else {
return SqlExecutor.query(connection, sqlAndParam.sql, new EntityHandler(),
ArrayUtil.toArray(sqlAndParam.param, Object.class));
}
}
/**
* 解析SQL
*/
private SqlAndParam sqlParamParser(DataResultSql dataResultSql, Map<String, Object> map) {
String sql = dataResultSql.getSql();
Map<String, SqlParam> sqlParamMap = Optional.ofNullable(dataResultSql.getParams())
.orElse(new ArrayList<>(0))
.stream()
.collect(Collectors.toMap(SqlParam::getName, Function.identity(), CollectorsFunction::retainLatest));
// # 参数处理
GenericTokenParser replaceTokenParser = new GenericTokenParser("#{", "}", content -> {
// 获取类型, 看是否是获取用户信息一类的
SqlParam sqlParam = sqlParamMap.get(content);
if (Objects.nonNull(sqlParam) && Objects.equals(sqlParam.getType(), QuerySqlCode.TYPE_USER_ID)) {
return String.valueOf(SecurityUtil.getUserId());
}
return map.get(content).toString();
});
sql = replaceTokenParser.parse(sql);
// $占位参数处理
List<Object> list = new ArrayList<>();
GenericTokenParser preparedTokenParser = new GenericTokenParser("${", "}", content -> {
Object param = map.get(content);
list.add(param);
return "?";
});
sql = preparedTokenParser.parse(sql);
return new SqlAndParam(sql, list);
}
/**
* 通过SQL查出结果字段
*/
// @SneakyThrows
// public List<String> queryFieldBySql(SqlQueryParam param) {
// String sql = "select * from iam_client";
// DataSource dataSource = this.getDataSource(param.getDatabaseId());
// Connection connection = dataSource.getConnection();
// Entity query = SqlExecutor.query(connection, sql, new EntityHandler());
// System.out.println(query);
// return new ArrayList<>(query.keySet());
// }
/**
* 获取数据源
*/
private DataSource getDataSource(Long id) {
DynamicDataSource dataSource = dynamicDataSourceManager.findById(id).orElseThrow(DataNotExistException::new);
DataSource source = dynamicRoutingDataSource.getDataSource(dataSource.getCode());
if (Objects.isNull(source)) {
dynamicDataSourceService.addDynamicDataSource(dataSource);
source = dynamicRoutingDataSource.getDataSource(dataSource.getCode());
}
return source;
}
/**
* 解析后的SQl语句和参数
*/
@Getter
@AllArgsConstructor
private static class SqlAndParam {
/** 解析后的SQL语句 */
private final String sql;
/** 解析后的参数 */
private List<Object> param;
}
}

View File

@@ -1,106 +0,0 @@
package cn.bootx.platform.baseapi.core.dataresult.service;
import cn.bootx.platform.baseapi.core.dataresult.dao.SqlQueryMapper;
import cn.bootx.platform.baseapi.dto.dataresult.SqlQueryResult;
import cn.bootx.platform.baseapi.param.dataresult.SqlQueryParam;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* SQL查询
* @author xxm
* @since 2023/8/29
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SqlQueryService {
private final SqlQueryMapper SqlQueryMapper;
/**
* SQL查询语句
* TODO 返回结果是无序的, 后期优化成有序的
*/
public SqlQueryResult query(SqlQueryParam param, PageParam pageParam){
try {
Page<?> page = MpUtil.getMpPage(pageParam, Object.class);
page.setSearchCount(false);
if (StrUtil.isNotBlank(param.getDatabaseKey())){
DynamicDataSourceContextHolder.push(param.getDatabaseKey());
}
List<Map<String, Object>> records;
if (param.isEnablePage()){
records = SqlQueryMapper.queryByPage(page, param.getSql()).getRecords();
} else {
records = SqlQueryMapper.query(param.getSql());
}
SqlQueryResult sqlQueryResult = new SqlQueryResult();
// 构造出表头
if (CollUtil.isNotEmpty(records)){
Map<String, Object> objectMap = records.get(0);
sqlQueryResult.setData(records)
.setFields(new ArrayList<>(objectMap.keySet()));
}
return sqlQueryResult;
} finally {
if (StrUtil.isNotBlank(param.getDatabaseKey())) {
DynamicDataSourceContextHolder.poll();
}
}
}
/**
* 导出查询结果
*/
public byte[] exportQueryResult(SqlQueryParam param, PageParam pageParam){
SqlQueryResult queryResult = this.query(param, pageParam);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
EasyExcel.write(byteArrayOutputStream)
.head(this.head(queryResult))
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.sheet("result")
.doWrite(this.dataList(queryResult));
return byteArrayOutputStream.toByteArray();
}
/**
* 单头
*/
private List<List<String>> head(SqlQueryResult queryResult) {
return queryResult.getFields()
.stream()
.map(Collections::singletonList)
.collect(Collectors.toList());
}
/**
* 内容
*/
private List<List<Object>> dataList(SqlQueryResult queryResult) {
List<Map<String, Object>> data = queryResult.getData();
List<String> fields = queryResult.getFields();
return data.stream()
.map(map->{
ArrayList<Object> objects = new ArrayList<>(fields.size());
fields.forEach(key->objects.add(StrUtil.toString(map.get(key))));
return objects;
}).collect(Collectors.toList());
}
}

View File

@@ -1,24 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.convert;
import cn.bootx.platform.baseapi.dto.dynamicform.DynamicFormDto;
import cn.bootx.platform.baseapi.param.dynamicform.DynamicFormParam;
import cn.bootx.platform.baseapi.core.dynamicform.entity.DynamicForm;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 动态表单
*
* @author xxm
* @since 2022-07-28
*/
@Mapper
public interface DynamicFormConvert {
DynamicFormConvert CONVERT = Mappers.getMapper(DynamicFormConvert.class);
DynamicForm convert(DynamicFormParam in);
DynamicFormDto convert(DynamicForm in);
}

View File

@@ -1,45 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.dao;
import cn.bootx.platform.baseapi.core.dynamicform.entity.DynamicForm;
import cn.bootx.platform.baseapi.param.dynamicform.DynamicFormParam;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.Objects;
/**
* 动态表单
*
* @author xxm
* @since 2022-07-28
*/
@Repository
@RequiredArgsConstructor
public class DynamicFormManager extends BaseManager<DynamicFormMapper, DynamicForm> {
/**
* 分页
*/
public Page<DynamicForm> page(PageParam pageParam, DynamicFormParam param) {
Page<DynamicForm> mpPage = MpUtil.getMpPage(pageParam, DynamicForm.class);
return lambdaQuery().select(DynamicForm.class, MpUtil::excludeBigField)
.like(Objects.nonNull(param.getCode()), DynamicForm::getCode, param.getCode())
.like(Objects.nonNull(param.getName()), DynamicForm::getName, param.getName())
.orderByDesc(MpIdEntity::getId)
.page(mpPage);
}
public boolean existsByCode(String code) {
return existedByField(DynamicForm::getCode, code);
}
public boolean existsByCode(String code, Long id) {
return existedByField(DynamicForm::getCode, code, id);
}
}

View File

@@ -1,16 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.dao;
import cn.bootx.platform.baseapi.core.dynamicform.entity.DynamicForm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 动态表单
*
* @author xxm
* @since 2022-07-28
*/
@Mapper
public interface DynamicFormMapper extends BaseMapper<DynamicForm> {
}

View File

@@ -1,50 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.entity;
import cn.bootx.platform.baseapi.core.dynamicform.convert.DynamicFormConvert;
import cn.bootx.platform.baseapi.dto.dynamicform.DynamicFormDto;
import cn.bootx.platform.baseapi.param.dynamicform.DynamicFormParam;
import cn.bootx.platform.common.core.annotation.BigField;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 动态表单
*
* @author xxm
* @since 2022-07-28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName(value = "base_dynamic_form", autoResultMap = true)
public class DynamicForm extends MpBaseEntity implements EntityBaseFunction<DynamicFormDto> {
/** 表单名称 */
private String name;
/** 表单键名 */
private String code;
/** 表单内容 */
@BigField
private String value;
/** 备注 */
private String remark;
/** 创建对象 */
public static DynamicForm init(DynamicFormParam in) {
return DynamicFormConvert.CONVERT.convert(in);
}
/** 转换成dto */
@Override
public DynamicFormDto toDto() {
return DynamicFormConvert.CONVERT.convert(this);
}
}

View File

@@ -1,24 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.entity;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author xxm
* @since 2022/7/30
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "动态表单数据")
public class DynamicFormData extends MpBaseEntity {
/** 表单id */
private Long formId;
/** 内容 */
}

View File

@@ -1,54 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.service;
import cn.bootx.platform.common.core.rest.param.PageParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 动态表单数据收集
*
* @author xxm
* @since 2022/8/13
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DynamicFormDataService {
/**
* 新增
*/
public void add() {
}
/**
* 更新
*/
public void update() {
}
/**
* 删除
*/
public void delete() {
}
/**
* 查询单条
*/
public void findById() {
}
/**
* 查询列表
*/
public void page(PageParam pageParam) {
}
}

View File

@@ -1,93 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicform.service;
import cn.bootx.platform.baseapi.dto.dynamicform.DynamicFormDto;
import cn.bootx.platform.baseapi.param.dynamicform.DynamicFormParam;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.ResultConvertUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.baseapi.core.dynamicform.dao.DynamicFormManager;
import cn.bootx.platform.baseapi.core.dynamicform.entity.DynamicForm;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 动态表单
*
* @author xxm
* @since 2022-07-28
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DynamicFormService {
private final DynamicFormManager dynamicFormManager;
/**
* 添加
*/
public void add(DynamicFormParam param) {
DynamicForm dynamicForm = DynamicForm.init(param);
dynamicFormManager.save(dynamicForm);
}
/**
* 修改
*/
public void update(DynamicFormParam param) {
DynamicForm dynamicForm = dynamicFormManager.findById(param.getId()).orElseThrow(DataNotExistException::new);
BeanUtil.copyProperties(param, dynamicForm, CopyOptions.create().ignoreNullValue());
dynamicFormManager.updateById(dynamicForm);
}
/**
* 分页
*/
public PageResult<DynamicFormDto> page(PageParam pageParam, DynamicFormParam dynamicFormParam) {
return MpUtil.convert2DtoPageResult(dynamicFormManager.page(pageParam, dynamicFormParam));
}
/**
* 获取单条
*/
public DynamicFormDto findById(Long id) {
return dynamicFormManager.findById(id).map(DynamicForm::toDto).orElseThrow(DataNotExistException::new);
}
/**
* 编码是否已经存在
*/
public boolean existsByCode(String code) {
return dynamicFormManager.existsByCode(code);
}
/**
* 编码是否已经存在(不包含自身)
*/
public boolean existsByCode(String code, Long id) {
return dynamicFormManager.existsByCode(code, id);
}
/**
* 获取全部
*/
public List<DynamicFormDto> findAll() {
return ResultConvertUtil.dtoListConvert(dynamicFormManager.findAll());
}
/**
* 删除
*/
public void delete(Long id) {
dynamicFormManager.deleteById(id);
}
}

View File

@@ -1,24 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicsource.convert;
import cn.bootx.platform.baseapi.dto.dynamicsource.DynamicDataSourceDto;
import cn.bootx.platform.baseapi.param.dynamicsource.DynamicDataSourceParam;
import cn.bootx.platform.baseapi.core.dynamicsource.entity.DynamicDataSource;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 动态数据源管理
*
* @author xxm
* @since 2022-09-24
*/
@Mapper
public interface DynamicDataSourceConvert {
DynamicDataSourceConvert CONVERT = Mappers.getMapper(DynamicDataSourceConvert.class);
DynamicDataSource convert(DynamicDataSourceParam in);
DynamicDataSourceDto convert(DynamicDataSource in);
}

View File

@@ -1,61 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicsource.dao;
import cn.bootx.platform.baseapi.core.dynamicsource.entity.DynamicDataSource;
import cn.bootx.platform.baseapi.param.dynamicsource.DynamicDataSourceParam;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/**
* 动态数据源管理
*
* @author xxm
* @since 2022-09-24
*/
@Repository
@RequiredArgsConstructor
public class DynamicDataSourceManager extends BaseManager<DynamicDataSourceMapper, DynamicDataSource> {
public Optional<DynamicDataSource> findByCode(String code) {
return findByField(DynamicDataSource::getCode, code);
}
public boolean existsByCode(String code) {
return existedByField(DynamicDataSource::getCode, code);
}
public boolean existsByCode(String code, Long id) {
return existedByField(DynamicDataSource::getCode, code, id);
}
/**
* 分页
*/
public Page<DynamicDataSource> page(PageParam pageParam, DynamicDataSourceParam param) {
Page<DynamicDataSource> mpPage = MpUtil.getMpPage(pageParam, DynamicDataSource.class);
return this.lambdaQuery()
.select(this.getEntityClass(), MpUtil::excludeBigField)
.eq(StrUtil.isNotBlank(param.getDatabaseType()), DynamicDataSource::getDatabaseType,
param.getDatabaseType())
.like(StrUtil.isNotBlank(param.getCode()), DynamicDataSource::getCode, param.getCode())
.like(StrUtil.isNotBlank(param.getName()), DynamicDataSource::getName, param.getName())
.orderByDesc(MpIdEntity::getId)
.page(mpPage);
}
/**
* 查询开启自动加载的数据源
*/
public List<DynamicDataSource>findAllByAutoLoad(){
return this.findAllByField(DynamicDataSource::isAutoLoad,true);
}
}

View File

@@ -1,16 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicsource.dao;
import cn.bootx.platform.baseapi.core.dynamicsource.entity.DynamicDataSource;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 动态数据源管理
*
* @author xxm
* @since 2022-09-24
*/
@Mapper
public interface DynamicDataSourceMapper extends BaseMapper<DynamicDataSource> {
}

View File

@@ -1,65 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicsource.entity;
import cn.bootx.platform.baseapi.core.dynamicsource.convert.DynamicDataSourceConvert;
import cn.bootx.platform.baseapi.dto.dynamicsource.DynamicDataSourceDto;
import cn.bootx.platform.baseapi.param.dynamicsource.DynamicDataSourceParam;
import cn.bootx.platform.common.core.annotation.EncryptionField;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 动态数据源管理
*
* @author xxm
* @since 2022-09-24
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("base_dynamic_data_source")
public class DynamicDataSource extends MpBaseEntity implements EntityBaseFunction<DynamicDataSourceDto> {
/** 数据源编码 */
private String code;
/** 数据源名称 */
private String name;
/** 数据库类型 */
private String databaseType;
/** 是否启动自动加载 */
private boolean autoLoad;
/** 驱动类 */
private String dbDriver;
/** 数据库地址 */
private String dbUrl;
/** 用户名 */
private String dbUsername;
/** 密码 */
@EncryptionField
private String dbPassword;
/** 备注 */
private String remark;
/** 创建对象 */
public static DynamicDataSource init(DynamicDataSourceParam in) {
return DynamicDataSourceConvert.CONVERT.convert(in);
}
/** 转换成dto */
@Override
public DynamicDataSourceDto toDto() {
return DynamicDataSourceConvert.CONVERT.convert(this);
}
}

View File

@@ -1,219 +0,0 @@
package cn.bootx.platform.baseapi.core.dynamicsource.service;
import cn.bootx.platform.baseapi.dto.dynamicsource.DynamicDataSourceDto;
import cn.bootx.platform.baseapi.param.dynamicsource.DynamicDataSourceParam;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.dto.KeyValue;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.ResultConvertUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.baseapi.core.dynamicsource.dao.DynamicDataSourceManager;
import cn.bootx.platform.baseapi.core.dynamicsource.entity.DynamicDataSource;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.db.ds.simple.SimpleDataSource;
import cn.hutool.db.handler.EntityHandler;
import cn.hutool.db.sql.SqlExecutor;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 动态数据源管理
*
* @author xxm
* @since 2022/9/24
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DynamicDataSourceService {
private final DynamicDataSourceManager dynamicDataSourceManager;
private final DataSourceCreator hikariDataSourceCreator;
private final DynamicRoutingDataSource dynamicRoutingDataSource;
private final DynamicDataSourceProperties dynamicDataSourceProperties;
/**
* 添加
*/
public void add(DynamicDataSourceParam param) {
DynamicDataSource dynamicDataSource = DynamicDataSource.init(param);
if (Objects.equals(dynamicDataSourceProperties.getPrimary(), param.getCode())) {
throw new BizException("名称不可为 " + dynamicDataSourceProperties.getPrimary());
}
if (dynamicDataSourceManager.existsByCode(param.getCode())) {
throw new BizException("编码重复");
}
dynamicDataSourceManager.save(dynamicDataSource);
}
/**
* 修改
*/
public void update(DynamicDataSourceParam param) {
DynamicDataSource dynamicDataSource = dynamicDataSourceManager.findById(param.getId())
.orElseThrow(DataNotExistException::new);
if (Objects.equals(dynamicDataSourceProperties.getPrimary(), param.getCode())) {
throw new BizException("名称不可为 " + dynamicDataSourceProperties.getPrimary());
}
if (dynamicDataSourceManager.existsByCode(param.getCode(), param.getId())) {
throw new BizException("编码重复");
}
BeanUtil.copyProperties(param, dynamicDataSource, CopyOptions.create().ignoreNullValue());
dynamicDataSourceManager.updateById(dynamicDataSource);
}
/**
* 分页
*/
public PageResult<DynamicDataSourceDto> page(PageParam pageParam, DynamicDataSourceParam dynamicDataSourceParam) {
return MpUtil.convert2DtoPageResult(dynamicDataSourceManager.page(pageParam, dynamicDataSourceParam));
}
/**
* 获取单条
*/
public DynamicDataSourceDto findById(Long id) {
return dynamicDataSourceManager.findById(id)
.map(DynamicDataSource::toDto)
.orElseThrow(DataNotExistException::new);
}
/**
* 编码查重
*/
public boolean existsByCode(String code) {
if (Objects.equals(dynamicDataSourceProperties.getPrimary(), code)) {
return true;
}
return dynamicDataSourceManager.existsByCode(code);
}
/**
* 编码查重 (不包含id)
*/
public boolean existsByCode(String code, Long id) {
if (Objects.equals(dynamicDataSourceProperties.getPrimary(), code)) {
return true;
}
return dynamicDataSourceManager.existsByCode(code, id);
}
/**
* 获取全部
*/
public List<DynamicDataSourceDto> findAll() {
return ResultConvertUtil.dtoListConvert(dynamicDataSourceManager.findAll());
}
/**
* 测试连接 根据参数
*/
public String testConnection(DynamicDataSourceParam param) {
try (SimpleDataSource ds = new SimpleDataSource(param.getDbUrl(), param.getDbUsername(), param.getDbPassword(),
param.getDbDriver()); Connection connection = ds.getConnection();) {
SqlExecutor.query(connection, "SELECT 1", new EntityHandler());
}
catch (Exception e) {
return e.getMessage();
}
return null;
}
/**
* 根据数据源id测试连接
*/
public String testConnection(Long id) {
DynamicDataSource dataSource = dynamicDataSourceManager.findById(id).orElseThrow(DataNotExistException::new);
DynamicDataSourceParam sourceParam = new DynamicDataSourceParam();
BeanUtil.copyProperties(dataSource, sourceParam);
return this.testConnection(sourceParam);
}
/**
* 删除
*/
public void delete(Long id) {
dynamicDataSourceManager.deleteById(id);
}
/**
* 添加数据源到多数据集合中
*/
public void addDynamicDataSource(DynamicDataSource dynamicDataSource) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setUrl(dynamicDataSource.getDbUrl());
dataSourceProperty.setPassword(dynamicDataSource.getDbPassword());
dataSourceProperty.setDriverClassName(dynamicDataSource.getDbDriver());
dataSourceProperty.setUsername(dynamicDataSource.getDbUsername());
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
dynamicRoutingDataSource.addDataSource(dynamicDataSource.getCode(), dataSource);
}
/**
* 根据id进行添加
*/
public void addDynamicDataSourceById(Long id) {
DynamicDataSource dataSource = dynamicDataSourceManager.findById(id).orElseThrow(DataNotExistException::new);
this.addDynamicDataSource(dataSource);
}
/**
* 查询当前数据源列表
*/
public List<KeyValue> findAllDataSource() {
Map<String, DataSource> dataSources = dynamicRoutingDataSource.getDataSources();
return dataSources.keySet().stream().map(s -> new KeyValue().setKey(s)).collect(Collectors.toList());
}
/**
* 判断该数据源当前是否已经添加
*/
public boolean existsByDataSourceKey(String key) {
Map<String, DataSource> dataSources = dynamicRoutingDataSource.getDataSources();
return dataSources.containsKey(key);
}
/**
* 删除数据源里的数据
*/
public void removeDataSourceByKey(String key) {
if (Objects.equals(dynamicDataSourceProperties.getPrimary(), key)) {
throw new BizException(key + " 数据源不可被删除");
}
dynamicRoutingDataSource.removeDataSource(key);
}
/**
* 启动时初始化加载
*/
public void initLoad(){
for (DynamicDataSource dynamicDataSource : dynamicDataSourceManager.findAllByAutoLoad()) {
try {
addDynamicDataSource(dynamicDataSource);
} catch (Exception e){
String errorMsg = dynamicDataSource.getName()+"数据源加载失败";
log.error(errorMsg,e);
}
}
}
}

View File

@@ -1,18 +0,0 @@
package cn.bootx.platform.baseapi.core.keyvalue.dao;
import cn.bootx.platform.baseapi.core.keyvalue.entity.SysKeyValue;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
* @author xxm
* @since 2022/3/30
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class SysKeyValueManager extends BaseManager<SysKeyValueMapper, SysKeyValue> {
}

View File

@@ -1,14 +0,0 @@
package cn.bootx.platform.baseapi.core.keyvalue.dao;
import cn.bootx.platform.baseapi.core.keyvalue.entity.SysKeyValue;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xxm
* @since 2022/3/30
*/
@Mapper
public interface SysKeyValueMapper extends BaseMapper<SysKeyValue> {
}

View File

@@ -1,50 +0,0 @@
package cn.bootx.platform.baseapi.core.keyvalue.entity;
import cn.bootx.platform.common.core.rest.dto.KeyValue;
import cn.bootx.platform.common.mybatisplus.base.MpDelEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* kv存储
*
* @author xxm
* @since 2022/3/30
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@TableName("base_key_value")
public class SysKeyValue extends MpDelEntity {
/**
* key值
*/
private String key;
/**
* value值
*/
private String value;
/**
* 转换成系统的 KayValue 对象
*/
public KeyValue toKeyValue() {
return new KeyValue(key, value);
}
/**
* 从 KayValue 转换
*/
public static SysKeyValue init(KeyValue keyValue) {
return new SysKeyValue(keyValue.getKey(), keyValue.getValue());
}
}

View File

@@ -1,69 +0,0 @@
package cn.bootx.platform.baseapi.core.keyvalue.service;
import cn.bootx.platform.common.core.function.SystemKeyValueService;
import cn.bootx.platform.common.core.rest.dto.KeyValue;
import cn.bootx.platform.baseapi.core.keyvalue.dao.SysKeyValueManager;
import cn.bootx.platform.baseapi.core.keyvalue.entity.SysKeyValue;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
/**
* kv存储
*
* @author xxm
* @since 2022/3/30
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SysKeyValueService implements SystemKeyValueService {
private final SysKeyValueManager sysKeyValueManager;
/**
* 获取值
*/
@Override
public String get(String key) {
return sysKeyValueManager.findByField(SysKeyValue::getKey, key).map(SysKeyValue::getValue).orElse(null);
}
/**
* 获取多个
*/
@Override
public List<KeyValue> gets(List<String> keys) {
return sysKeyValueManager.findAllByFields(SysKeyValue::getKey, keys)
.stream()
.map(SysKeyValue::toKeyValue)
.collect(Collectors.toList());
}
/**
* 设置值
*/
@Override
public void setup(String key, String value) {
SysKeyValue sysKeyValue = sysKeyValueManager.findByField(SysKeyValue::getKey, key)
.orElse(new SysKeyValue().setKey(key).setValue(value));
sysKeyValueManager.saveOrUpdate(sysKeyValue);
}
/**
* 保存多个值
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void setupBatch(List<KeyValue> list) {
List<SysKeyValue> collect = list.stream()
.map(SysKeyValue::init)
.collect(Collectors.toList());
sysKeyValueManager.saveAll(collect);
}
}

View File

@@ -1,22 +0,0 @@
package cn.bootx.platform.baseapi.core.template.convert;
import cn.bootx.platform.baseapi.core.template.entity.GeneralTemplate;
import cn.bootx.platform.baseapi.dto.template.GeneralTemplateDto;
import cn.bootx.platform.baseapi.param.template.GeneralTemplateParam;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 通用模板管理
* @author xxm
* @since 2023-08-12
*/
@Mapper
public interface GeneralTemplateConvert {
GeneralTemplateConvert CONVERT = Mappers.getMapper(GeneralTemplateConvert.class);
GeneralTemplate convert(GeneralTemplateParam in);
GeneralTemplateDto convert(GeneralTemplate in);
}

View File

@@ -1,47 +0,0 @@
package cn.bootx.platform.baseapi.core.template.dao;
import cn.bootx.platform.baseapi.core.template.entity.GeneralTemplate;
import cn.bootx.platform.baseapi.param.template.GeneralTemplateParam;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.common.query.generator.QueryGenerator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/**
* 通用模板管理
* @author xxm
* @since 2023-08-12
*/
@Repository
@RequiredArgsConstructor
public class GeneralTemplateManager extends BaseManager<GeneralTemplateMapper, GeneralTemplate> {
/**
* 分页
*/
public Page<GeneralTemplate> page(PageParam pageParam, GeneralTemplateParam param) {
Page<GeneralTemplate> mpPage = MpUtil.getMpPage(pageParam, GeneralTemplate.class);
QueryWrapper<GeneralTemplate> wrapper = QueryGenerator.generator(param, this.getEntityClass());
wrapper.select(this.getEntityClass(),MpUtil::excludeBigField)
.orderByDesc(MpUtil.getColumnName(GeneralTemplate::getId));
return this.page(mpPage,wrapper);
}
public Optional<GeneralTemplate> findByCode(String code){
return findByField(GeneralTemplate::getCode,code);
}
public boolean existsByCode(String code) {
return existedByField(GeneralTemplate::getCode, code);
}
public boolean existsByCode(String code, Long id) {
return existedByField(GeneralTemplate::getCode, code, id);
}
}

View File

@@ -1,14 +0,0 @@
package cn.bootx.platform.baseapi.core.template.dao;
import cn.bootx.platform.baseapi.core.template.entity.GeneralTemplate;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 通用模板管理
* @author xxm
* @since 2023-08-12
*/
@Mapper
public interface GeneralTemplateMapper extends BaseMapper<GeneralTemplate> {
}

View File

@@ -1,77 +0,0 @@
package cn.bootx.platform.baseapi.core.template.entity;
import cn.bootx.platform.baseapi.core.template.convert.GeneralTemplateConvert;
import cn.bootx.platform.baseapi.dto.template.GeneralTemplateDto;
import cn.bootx.platform.baseapi.param.template.GeneralTemplateParam;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.table.modify.annotation.DbComment;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 通用模板管理
* @author xxm
* @since 2023/8/12
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("base_general_template")
public class GeneralTemplate extends MpBaseEntity implements EntityBaseFunction<GeneralTemplateDto> {
/** 模板名称 */
@DbComment("模板名称")
private String name;
/** 模板代码 */
@DbComment("模板代码")
private String code;
/**
* 使用类型(导入/导出)
* @see cn.bootx.platform.baseapi.code.GeneralTemplateCode
*/
@DbComment("使用类型(导入/导出)")
private String useType;
/** 模板类型 */
@DbComment("模板类型")
private String fileType;
/** 模板后缀名 */
@DbComment("模板后缀名")
private String fileSuffix;
/**
* 状态
* @see cn.bootx.platform.baseapi.code.GeneralTemplateCode
*/
@DbComment("状态")
private String state;
/** 文件ID */
@DbComment("文件ID")
@TableField(updateStrategy = FieldStrategy.NEVER)
private Long fileId;
/** 备注 */
@DbComment("备注")
private String remark;
/** 创建对象 */
public static GeneralTemplate init(GeneralTemplateParam in) {
return GeneralTemplateConvert.CONVERT.convert(in);
}
/** 转换成dto */
@Override
public GeneralTemplateDto toDto() {
return GeneralTemplateConvert.CONVERT.convert(this);
}
}

View File

@@ -1,112 +0,0 @@
package cn.bootx.platform.baseapi.core.template.service;
import cn.bootx.platform.baseapi.core.template.dao.GeneralTemplateManager;
import cn.bootx.platform.baseapi.core.template.entity.GeneralTemplate;
import cn.bootx.platform.baseapi.dto.template.GeneralTemplateDto;
import cn.bootx.platform.baseapi.param.template.GeneralTemplateParam;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.ResultConvertUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 通用模板管理
* @author xxm
* @since 2023-08-12
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class GeneralTemplateService {
private final GeneralTemplateManager generalTemplateManager;
/**
* 添加
*/
public void add(GeneralTemplateParam param){
if (generalTemplateManager.existsByCode(param.getCode())) {
throw new BizException("code重复");
}
GeneralTemplate generalTemplate = GeneralTemplate.init(param);
generalTemplateManager.save(generalTemplate);
}
/**
* 修改
*/
public void update(GeneralTemplateParam param){
if (generalTemplateManager.existsByCode(param.getCode(),param.getId())) {
throw new BizException("code重复");
}
GeneralTemplate generalTemplate = generalTemplateManager.findById(param.getId()).orElseThrow(DataNotExistException::new);
BeanUtil.copyProperties(param,generalTemplate, CopyOptions.create().ignoreNullValue());
generalTemplateManager.updateById(generalTemplate);
}
/**
* 分页
*/
public PageResult<GeneralTemplateDto> page(PageParam pageParam,GeneralTemplateParam query){
return MpUtil.convert2DtoPageResult(generalTemplateManager.page(pageParam,query));
}
/**
* 获取单条
*/
public GeneralTemplateDto findById(Long id){
return generalTemplateManager.findById(id).map(GeneralTemplate::toDto).orElseThrow(DataNotExistException::new);
}
/**
* 根据编码获取
*/
public GeneralTemplateDto findByCode(String code){
return generalTemplateManager.findByCode(code).map(GeneralTemplate::toDto).orElseThrow(DataNotExistException::new);
}
/**
* 获取全部
*/
public List<GeneralTemplateDto> findAll(){
return ResultConvertUtil.dtoListConvert(generalTemplateManager.findAll());
}
/**
* code是否存在
*/
public boolean existsByCode(String code) {
return generalTemplateManager.existsByCode(code);
}
/**
* code是否存在
*/
public boolean existsByCode(String code, Long id) {
return generalTemplateManager.existsByCode(code, id);
}
/**
* 删除
*/
public void delete(Long id){
generalTemplateManager.deleteById(id);
}
/**
* 批量删除
*/
public void deleteBatch(List<Long> ids){
generalTemplateManager.deleteByIds(ids);
}
}

View File

@@ -1,28 +0,0 @@
package cn.bootx.platform.baseapi.handler.dynamicsource;
import cn.bootx.platform.baseapi.core.dynamicsource.service.DynamicDataSourceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 初始化数据源函数
* @author xxm
* @since 2023/5/17
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicDataSourceLoadHandler {
private final DynamicDataSourceService dynamicDataSourceService;
/**
* 启动时初始化加载多数据源
*/
@Bean
public void dynamicDataSourceService$initLoad(){
dynamicDataSourceService.initLoad();
}
}

View File

@@ -1,124 +0,0 @@
package cn.bootx.platform.notice.controller;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.notice.core.dingtalk.entity.corp.DingCorpNoticeReceive;
import cn.bootx.platform.notice.core.dingtalk.entity.msg.DingTextMsg;
import cn.bootx.platform.notice.core.template.service.MessageTemplateService;
import cn.bootx.platform.notice.core.wecom.entity.WeComNoticeReceive;
import cn.bootx.platform.notice.core.wecom.entity.msg.WeComTextMsg;
import cn.bootx.platform.notice.service.DingTalkNoticeSender;
import cn.bootx.platform.notice.service.EmailNoticeSender;
import cn.bootx.platform.notice.service.WeComNoticeSender;
import cn.bootx.platform.notice.service.WeComRobotNoticeSender;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Tag(name = "nc测试")
@RestController
@RequestMapping("/nc/test")
@RequiredArgsConstructor
public class NcDemoController {
private final MessageTemplateService messageTemplateService;
private final EmailNoticeSender mailSendService;
private final DingTalkNoticeSender dingTalkNoticeSender;
private final WeComNoticeSender weComNoticeSender;
private final WeComRobotNoticeSender weComRobotNoticeSender;
@Operation(summary = "邮件消息测试")
@PostMapping("/sendMsg")
public ResResult<Void> sendMsg() {
// 传入模板code和参数
Map<String, Object> map = new HashMap<>();
String data = messageTemplateService.rendering("code", map);
// 调用发送
mailSendService.sentSimpleMail("xxm@bootx.cn", "测试邮件", data);
return Res.ok();
}
@Operation(summary = "钉钉消息测试")
@PostMapping("/sendDingMsg")
public ResResult<Void> sendDingMsg() {
DingTextMsg msg = new DingTextMsg("中文通知");
DingCorpNoticeReceive receive = new DingCorpNoticeReceive().setUseridList(Collections.singletonList(""));
dingTalkNoticeSender.sendTextCorpNotice(msg, receive);
return Res.ok();
}
@SneakyThrows
@Operation(summary = "钉钉图片消息测试")
@PostMapping("/sendDingImageMsg")
public ResResult<Void> sendDingImageMsg(MultipartFile file) {
DingCorpNoticeReceive receive = new DingCorpNoticeReceive()
.setUseridList(Collections.singletonList("manager7303"));
dingTalkNoticeSender.sendImageCorpNotice(file.getInputStream(), receive);
return Res.ok();
}
@SneakyThrows
@Operation(summary = "钉钉文件消息测试")
@PostMapping("/sendDingFileMsg")
public ResResult<Void> sendDingFileMsg(MultipartFile file) {
DingCorpNoticeReceive receive = new DingCorpNoticeReceive()
.setUseridList(Collections.singletonList("manager7303"));
dingTalkNoticeSender.sendFileCorpNotice(file.getInputStream(), file.getOriginalFilename(), receive);
return Res.ok();
}
@Operation(summary = "企微消息测试")
@PostMapping("/sendWeComMsg")
public ResResult<String> sendWeComMsg() {
WeComTextMsg msg = new WeComTextMsg("企微消息测试");
WeComNoticeReceive receive = new WeComNoticeReceive();
receive.setUseridList(Collections.singletonList("XiaXiangMing"));
return Res.ok(weComNoticeSender.sendTextNotice(msg, receive));
}
@SneakyThrows
@Operation(summary = "企微图片消息测试")
@PostMapping("/sendImageNotice")
public ResResult<String> sendImageNotice(MultipartFile file) {
WeComNoticeReceive receive = new WeComNoticeReceive();
receive.setUseridList(Collections.singletonList("XiaXiangMing"));
return Res.ok(weComNoticeSender.sendImageNotice(file.getInputStream(), receive));
}
@Operation(summary = "企微消息撤回")
@PostMapping("/recallNotice")
public ResResult<Void> recallNotice(String msgId) {
weComNoticeSender.recallNotice(msgId);
return Res.ok();
}
@SneakyThrows
@Operation(summary = "企微机器人图片发送")
@PostMapping("/p1")
public ResResult<Void> p1(MultipartFile file) {
weComRobotNoticeSender.sendImageNotice("bootx", file.getInputStream());
return Res.ok();
}
@SneakyThrows
@Operation(summary = "企微机器人文件发送")
@PostMapping("/p2")
public ResResult<Void> p2(MultipartFile file) {
weComRobotNoticeSender.sendFIleNotice("bootx", file.getInputStream(), file.getOriginalFilename());
return Res.ok();
}
}

View File

@@ -1,20 +0,0 @@
package cn.bootx.platform.notice.core.wechat.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.notice.core.wechat.entity.WeChatNoticeConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
* 微信消息配置
*
* @author xxm
* @since 2021/8/10
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class WeChatNoticeConfigManager extends BaseManager<WeChatNoticeConfigMapper, WeChatNoticeConfig> {
}

View File

@@ -1,14 +0,0 @@
package cn.bootx.platform.notice.core.wechat.dao;
import cn.bootx.platform.notice.core.wechat.entity.WeChatNoticeConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xxm
* @since 2021/8/10
*/
@Mapper
public interface WeChatNoticeConfigMapper extends BaseMapper<WeChatNoticeConfig> {
}

View File

@@ -1,21 +0,0 @@
package cn.bootx.platform.notice.core.wechat.entity;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信消息配置
*
* @author xxm
* @since 2021/8/10
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("notice_wechat_config")
public class WeChatNoticeConfig extends MpBaseEntity {
}