deploy-jar-template/pom.xml
@@ -83,10 +83,10 @@ </dependency> <!-- tcp通信模块引入,可配置是否开启:包括聊天功能基础等。2023-04-17 --> <dependency> <groupId>com.iplatform</groupId> <artifactId>iplatform-base-tcp</artifactId> </dependency> <!-- <dependency>--> <!-- <groupId>com.iplatform</groupId>--> <!-- <artifactId>iplatform-base-tcp</artifactId>--> <!-- </dependency>--> <!-- 启用Rocket队列消息模块,聊天集群使用,2023-09-26 --> <dependency> <groupId>com.walkersoft</groupId> @@ -161,16 +161,15 @@ </dependency> <!-- 测试商户功能模块,2023-06-01 --> <dependency> <groupId>com.iplatform</groupId> <artifactId>ishop-merchant</artifactId> </dependency> <!-- <dependency>--> <!-- <groupId>com.iplatform</groupId>--> <!-- <artifactId>ishop-merchant</artifactId>--> <!-- </dependency>--> <!-- 测试移动端,2023-06-23 --> <dependency> <groupId>com.iplatform</groupId> <artifactId>ishop-mobile</artifactId> </dependency> <!-- <dependency>--> <!-- <groupId>com.iplatform</groupId>--> <!-- <artifactId>ishop-mobile</artifactId>--> <!-- </dependency>--> <!-- 测试mongo聊天写入,2023-07-07 --> <!-- <dependency>--> deploy-jar-template/src/main/resources/application-dev.yml
@@ -87,7 +87,7 @@ host: 116.198.40.76 port: 6379 password: Jmy2019. database: 2 database: 15 mvc: pathmatch: @@ -161,7 +161,7 @@ # 平台缓存,是否启用redis缓存,默认使用基于内存缓存. # 注意:如果开启redis缓存,业务工程必须依赖(walker-support-redis) cache: redis-enabled: false redis-enabled: true # redis 缓存是否要重建,如果设置 true,则系统启动后会删除缓存,并执行默认重新加载方法。2023-08-26 # 注意:该参数一般在测试阶段使用,正式环境不要使用! redis-rebuild: true @@ -303,7 +303,21 @@ file-root: d:/tmp/ # 调用远程上传文件,是否按照本地文件处理,2023-07-03 # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 remote-as-local: true remote-as-local: false # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 # | ftp,2024-02-23增加 oss-type: aws_s3 # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 oss-prefix: http://localhost:8082/admin/oss/ oss-access-key: HDKSYC2Y4FELF5CL5FIB oss-secret-key: ktf8Px9uTvLFFpQNGsO41ehRsgJ0hWnLtxZnDBCX # oss服务地址 oss-endpoint: http://eos-beijing-1.cmecloud.cn # oss默认的桶名称 oss-bucket-name: ctoms-file protocol: http ftp: ip: 116.198.40.76 port: 22 @@ -343,7 +357,8 @@ # websocket连接端口 port-ws: 60000 # websocket连接uri websocket-uri: ws://localhost:60000/websocket # websocket-uri: ws://localhost:60000/websocket websocket-uri: ws://localhost:60000 # 通信线程数量 boss-thread-num: 2 # 业务处理线程数量 deploy-jar-template/src/main/resources/application-prod.yml
@@ -285,6 +285,19 @@ # 调用远程上传文件,是否按照本地文件处理,2023-07-03 # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 remote-as-local: true # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 oss-type: aws_s3 # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 oss-prefix: http://localhost:8082/admin/oss/ oss-access-key: HDKSYC2Y4FELF5CL5FIB oss-secret-key: 111 # oss服务地址 oss-endpoint: http://eos-beijing-1.cmecloud.cn # oss默认的桶名称 oss-bucket-name: ctoms-file protocol: http ftp: ip: 116.198.40.76 port: 22 deploy-jar-template/src/main/resources/application-test.yml
@@ -281,6 +281,20 @@ # 调用远程上传文件,是否按照本地文件处理,2023-07-03 # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 remote-as-local: true # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 # | ftp,2024-02-23增加 oss-type: aws_s3 # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 oss-prefix: http://localhost:8082/admin/oss/ oss-access-key: HDKSYC2Y4FELF5CL5FIB oss-secret-key: ktf8Px9uTvLFFpQNGsO41ehRsgJ0hWnLtxZnDBCX # oss服务地址 oss-endpoint: http://eos-beijing-1.cmecloud.cn # oss默认的桶名称 oss-bucket-name: ctoms-file protocol: http # ftp: # ip: 116.198.40.76 # port: 22 deploy-jar-template/src/main/resources/application.yml
@@ -1,7 +1,7 @@ spring: profiles: # active: oracle # active: dev active: master active: dev # active: master # active: test iplatform-base-admin/src/main/java/com/iplatform/base/controller/GenController.java
@@ -1,14 +1,22 @@ package com.iplatform.base.controller; import com.iplatform.base.SystemController; import com.iplatform.core.util.CharsetKit; import com.iplatform.core.util.Convert; import com.iplatform.mybatis.domain.GenTable; import com.iplatform.mybatis.domain.GenTableColumn; import com.iplatform.mybatis.domain.TableDataInfo; import com.iplatform.mybatis.service.IGenTableColumnService; import com.iplatform.mybatis.service.IGenTableService; import com.iplatform.mybatis.service.MetaDataServiceImpl; import com.iplatform.mybatis.util.VelocityInitializer; import com.iplatform.mybatis.util.VelocityUtils; import com.walker.infrastructure.utils.StringUtils; import com.walker.web.ResponseValue; import org.apache.commons.io.IOUtils; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; @@ -22,10 +30,14 @@ import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * 代码生成 操作处理。 @@ -48,6 +60,9 @@ @Autowired private IGenTableColumnService genTableColumnService; @Autowired private MetaDataServiceImpl metaDataService; /** * 查询代码生成列表 @@ -233,4 +248,51 @@ rspData.setTotal(0); return rspData; } /** * 生成指定表结构代码,支持多数据库。 * @param response * @param tableName 表名,可以是精确的表名,如:s_ment,也可以是前缀,如:s_ * @param isPrecision 是否精确查询(单表) * @param packageName * @throws IOException * @date 2024-02-20 */ @GetMapping("/batchDownloadGenCode") public void batchDownloadGenCode(HttpServletResponse response, String tableName, boolean isPrecision, String packageName) throws IOException{ List<GenTable> list = this.metaDataService.queryDatabaseTableInfo(tableName, isPrecision, packageName, null, null, null); if(StringUtils.isEmptyList(list)){ logger.error("未查找到任何表信息,无法生存代码,tableName={}", tableName); return; } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(outputStream); for(GenTable table : list){ VelocityInitializer.initVelocity(); VelocityContext context = VelocityUtils.prepareContext(table); // 获取模板列表 List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory()); for (String template : templates) { // 渲染模板 StringWriter sw = new StringWriter(); Template tpl = Velocity.getTemplate(template, CharsetKit.UTF_8); tpl.merge(context, sw); try { // 添加到zip zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table))); IOUtils.write(sw.toString(), zip, CharsetKit.UTF_8); IOUtils.closeQuietly(sw); zip.flush(); zip.closeEntry(); } catch (IOException e) { logger.error("渲染模板失败,表名:" + table.getTableName(), e); } } } IOUtils.closeQuietly(zip); byte[] data = outputStream.toByteArray(); genCode(response, data); } } iplatform-base-admin/src/main/java/com/iplatform/base/controller/UserController.java
@@ -19,6 +19,7 @@ import com.walker.di.DataImportException; import com.walker.file.FileInfo; import com.walker.infrastructure.utils.DateUtils; import com.walker.infrastructure.utils.FileCopyUtils; import com.walker.infrastructure.utils.NumberGenerator; import com.walker.infrastructure.utils.StringUtils; import com.walker.web.ResponseValue; @@ -35,6 +36,8 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -68,6 +71,18 @@ @PostMapping("/import") public ResponseValue importExcel(MultipartFile file, boolean updateSupport){ try { // ~~~~~~~~~~~~~~~~~~~~~ 测试 // String filePath = "d:/tmp/test_user_001.csv"; // FileOutputStream fileOutputStream = new FileOutputStream(new File(filePath)); // FileCopyUtils.copy(file.getInputStream(), fileOutputStream); // logger.info("文件写入成功:{}", filePath); // FileInfo testFileInfo = this.uploadFileToRemote(filePath, null, String.valueOf(this.getOwner())); // 2024-02-23 以下代码成功执行,暂时注释 // FileInfo testFileInfo = this.uploadFileToRemote(file.getInputStream(), "avatar.jpg", null, file.getSize(), null, String.valueOf(Constants.OWNER_PLATFORM)); // logger.info("testFileInfo = {}", testFileInfo); // ~~~~~~~~~~~~~~~~~~~~~ 测试 end UserDataImportor dataImportor = new UserDataImportor(file.getInputStream()); dataImportor.setId("user_import"); this.getDataImportEngine().executeImport(dataImportor, this.getCurrentUserPrincipal().getUserName()); @@ -75,6 +90,9 @@ logger.info("错误结果文件:{}", dataImportor.getErrorFile()); // FileInfo errorFileInfo = this.uploadFileToRemote(dataImportor.getErrorFile()); // this.uploadFileToRemote(file.getInputStream(), null, null, String.valueOf(this.getOwner()),) // 这里会报错,因为上传 s3 oss时动态生成的文件,总是说读取长度和期望长度不一致: // 保存文件到【oss】错误:Data read has a different length than the expected: dataLength=2764; expectedLength=107374178304; FileInfo errorFileInfo = this.uploadFileToRemote(dataImportor.getErrorFile(), null, String.valueOf(this.getOwner())); if(errorFileInfo != null){ logger.debug("用户导入存在'不符合数据': ,", errorFileInfo.toString()); iplatform-base-security/src/main/java/com/iplatform/security/DefaultAuthenticationFailureHandler.java
@@ -51,7 +51,7 @@ } try { ServletUtils.renderString(response, JsonUtils.objectToJsonString(ResponseValue.error(code, message))); ServletUtils.renderString(response, JsonUtils.objectToJsonString(ResponseValue.error(message))); } catch (Exception e) { logger.error("认证失败:" + request.getRequestURI(), e); } iplatform-base-security/src/main/java/com/iplatform/security/FailedAuthenticationEntryPoint.java
@@ -28,7 +28,7 @@ String msg = "认证失败,无权限访问系统资源" + request.getRequestURI(); try { ServletUtils.renderString(response, JsonUtils.objectToJsonString(ResponseValue.error(ResponseCode.NO_PERMISSION.getCode(), msg))); ServletUtils.renderString(response, JsonUtils.objectToJsonString(ResponseValue.error(ResponseCode.EXCEPTION.getCode(), msg))); } catch (Exception e) { logger.error("无权限访问系统资源" + request.getRequestURI()); } iplatform-base-security/src/main/java/com/iplatform/security/JwtAuthenticationTokenFilter.java
@@ -143,7 +143,7 @@ , userPrincipal.getUserName(), uuid, this.tokenGenerator, securityProperties.getTokenExpireWeb()); // 重新设置用户创建token时间 userPrincipal.setLastLoginTime(System.currentTimeMillis()); this.userOnlineProvider.cacheUserPrincipal(uuid, userPrincipal); this.userOnlineProvider.cacheUserPrincipal(uuid, userPrincipal, securityProperties.getTokenExpireWeb()); response.addHeader(Constants.TOKEN_HEADER_REFRESH, token); if(this.logger.isDebugEnabled()){ logger.debug("刷新token, uuid = " + uuid + ", " + token); iplatform-base-tcp-client/src/test/java/com/iplatform/AppTest.java
New file @@ -0,0 +1,16 @@ package com.iplatform; import com.iplatform.tcp.WebsocketClientTest; /** * Unit test for simple App. */ public class AppTest { public static void main( String[] args ) { System.out.println( "Hello World!" ); WebsocketClientTest test = new WebsocketClientTest(); test.createBatch(); } } iplatform-base-tcp-client/src/test/java/com/iplatform/tcp/DemoLoginResponse.java
New file @@ -0,0 +1,51 @@ package com.iplatform.tcp; public class DemoLoginResponse { /** * */ private static final long serialVersionUID = 1167352207355638142L; // @Override // protected void translateProperties(JSONObject result) { // result.put("status", status); // } @Override public String toString(){ return new StringBuilder("[protocol=").append(this.getProtocol()) .append(", name=").append(this.getUid()) .append(", status=").append(this.status) .append("]").toString(); } public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } private String protocol; public String getProtocol() { return protocol; } public void setProtocol(String protocol) { this.protocol = protocol; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } private int status = 0; private String uid; } iplatform-base-tcp-client/src/test/java/com/iplatform/tcp/DemoWebsocketClient.java
New file @@ -0,0 +1,81 @@ package com.iplatform.tcp; import com.walker.infrastructure.utils.JsonUtils; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; import java.util.HashMap; import java.util.Map; public class DemoWebsocketClient extends WebSocketClient { protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); public DemoWebsocketClient(URI serverUri) { super(serverUri); } @Override public void onOpen(ServerHandshake serverHandshake) { // logger.info("ws 连接成功"); String data = null; Map<String, String> map = new HashMap<>(4); map.put("protocol", "login"); map.put("uid", this.uid); try { data = JsonUtils.objectToJsonString(map); } catch (Exception e) { throw new RuntimeException(e); } this.send(data); logger.info("客户端发送登录请求,name = {}", this.uid); } @Override public void onMessage(String s) { if(s.indexOf("heartbeat") >= 0){ return; } logger.info("ws 收到消息:{}", s); try { DemoLoginResponse response = JsonUtils.jsonStringToObject(s, DemoLoginResponse.class); if(response.getProtocol().equals("login")){ logger.info("websocket 登录成功:{}", response.getUid()); } } catch (Exception e) { throw new RuntimeException(e); } } @Override public void onClose(int i, String s, boolean b) { logger.warn("连接被关闭:code={}, reason={}, remote={}", i, s, b); } @Override public void onError(Exception e) { logger.error("连接错误:" + e.getMessage(), e); } public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } private String uid; private String userName; } iplatform-base-tcp-client/src/test/java/com/iplatform/tcp/WebsocketClientTest.java
New file @@ -0,0 +1,100 @@ package com.iplatform.tcp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class WebsocketClientTest { protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); // private static final URI wsUri = URI.create("ws://127.0.0.1:60000/websocket"); // private static final URI wsUri = URI.create("ws://116.198.40.76:60000/websocket"); // private static final URI wsUri = URI.create("ws://10.8.4.35:60035/websocket"); // private static final URI wsUri = URI.create("ws://www.shikeying.com:60001/websocket"); // private static final URI wsUri = URI.create("ws://ctoms.chinapost.com.cn/ws/websocket"); private static final URI wsUri = URI.create("ws://localhost:60000"); // private static final URI wsUri = URI.create("ws://10.8.4.98:60011/websocket"); private static Map<String, DemoWebsocketClient> cacheClient = new ConcurrentHashMap<>(32770); private ExecutorService executorService = Executors.newFixedThreadPool(4); // private static int currentSize = 20000; private static int currentSize = 1; private static final int TOTAL_LINES = 2; // private static final int TOTAL_LINES = 16; // private static final int BATCH_SIZE = 8; private static final int BATCH_SIZE = 2; public void createBatch(){ logger.info(".........开始测试通信连接.......... TOTAL_LINES = {}, url = {}", TOTAL_LINES, wsUri); while(currentSize < TOTAL_LINES){ try { this.executorService.execute(new Runnable() { @Override public void run() { int count = BATCH_SIZE; for(int i=0; i<count; i++){ String uri = "mike" + (currentSize); DemoWebsocketClient client = createOneClient(wsUri, uri); logger.info("创建了一个客户端: " + uri); cacheClient.put(uri, client); currentSize ++; } } }); } catch (Exception ex){ ex.printStackTrace(); } finally { try { logger.info("currentSize = {}", currentSize); TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { throw new RuntimeException(e); } } } logger.info("已累计创建连接:{} 个", currentSize); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } // logger.info("准备关闭所有链接对象..."); // for(DemoWebsocketClient client : cacheClient.values()){ // client.close(); // } // logger.info("执行了关闭操作,所有连接稍后会完全关闭"); } private DemoWebsocketClient createOneClient(URI uri, String uid){ DemoWebsocketClient client = new DemoWebsocketClient(uri); client.setUid(uid); client.setConnectionLostTimeout(0); try { client.connectBlocking(); } catch (InterruptedException e) { throw new RuntimeException("创建client错误, uid=" + uid + ", " + e.getMessage(), e); } return client; } // public void createOneClient(){ // DemoWebsocketClient client = new DemoWebsocketClient(wsUri); // client.setUid("mike"); // try { // client.connectBlocking(); // } catch (InterruptedException e) { // throw new RuntimeException(e); // } // WaitConsoleInput.waitInput(); // } } iplatform-base-tcp-client/src/test/java/com/iplatform/tcp/WebsocketDemo.java
New file @@ -0,0 +1,22 @@ package com.iplatform.tcp; import com.iplatform.tcp.util.ws.WebDataResponse; import com.walker.infrastructure.utils.JsonUtils; import com.walker.infrastructure.utils.NumberGenerator; import org.junit.Test; public class WebsocketDemo { @Test public void sendDataFormat(){ WebDataResponse msg = new WebDataResponse(); msg.setMessageId(NumberGenerator.getLongSequenceId()); msg.setName("shikeying"); // 指定用户发送,该id与浏览器端注册的id保持一致。 msg.setData("你好,这是推送给浏览器的内容,一般是JSON格式。"); try { System.out.println(JsonUtils.objectToJsonString(msg)); } catch (Exception e) { throw new RuntimeException(e); } } } iplatform-base/src/main/java/com/iplatform/base/AbstractFileOperateSpiController.java
@@ -1,5 +1,6 @@ package com.iplatform.base; import com.iplatform.base.config.FileProperties; import com.iplatform.core.BeanContextAware; import com.walker.file.FileInfo; import com.walker.file.FileStoreType; @@ -144,34 +145,47 @@ protected FileInfo uploadFileToRemote(InputStream inputStream , String fileName, String groupId, long fileSize, Integer businessType, String owner) throws Exception{ String remoteFileStoreType = this.getArgumentVariable(ArgumentsConstants.CONFIG_UPLOAD_TYPE).getStringValue(); if(StringUtils.isEmpty(remoteFileStoreType)){ throw new PlatformRuntimeException("平台未配置任何远程存储类别:" + ArgumentsConstants.CONFIG_UPLOAD_TYPE); } // 2023-07-03,如果配置远程上传为本地 if(this.acquireFileOperateSpi().isRemoteAsLocal()){ return this.acquireFileOperateSpi().uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); } FileStoreType fileStoreType = FileStoreType.getType(remoteFileStoreType); // String remoteFileStoreType = this.getArgumentVariable(ArgumentsConstants.CONFIG_UPLOAD_TYPE).getStringValue(); // if(StringUtils.isEmpty(remoteFileStoreType)){ // throw new PlatformRuntimeException("平台未配置任何远程存储类别:" + ArgumentsConstants.CONFIG_UPLOAD_TYPE); // } // FileStoreType fileStoreType = FileStoreType.getType(remoteFileStoreType); String ossType = BeanContextAware.getBeanByType(FileProperties.class).getOssType(); if(StringUtils.isEmpty(ossType)){ throw new PlatformRuntimeException("平台未配置任何ossType"); } FileStoreType fileStoreType = FileStoreType.getType(ossType); if(fileStoreType == FileStoreType.Ftp){ return this.acquireFileOperateSpi().uploadFileToFtp(inputStream, fileName, groupId, fileSize, businessType, owner); } else { return this.acquireFileOperateSpi().uploadFileToOss(inputStream, fileName, groupId, fileSize, businessType, owner, fileStoreType); } } protected FileInfo[] uploadFileToRemote(InputStream[] inputStream , String[] fileName, String groupId, long[] fileSize, Integer businessType, String owner) throws Exception{ String remoteFileStoreType = this.getArgumentVariable(ArgumentsConstants.CONFIG_UPLOAD_TYPE).getStringValue(); if(StringUtils.isEmpty(remoteFileStoreType)){ throw new PlatformRuntimeException("平台未配置任何远程存储类别:" + ArgumentsConstants.CONFIG_UPLOAD_TYPE); } // String remoteFileStoreType = this.getArgumentVariable(ArgumentsConstants.CONFIG_UPLOAD_TYPE).getStringValue(); // if(StringUtils.isEmpty(remoteFileStoreType)){ // throw new PlatformRuntimeException("平台未配置任何远程存储类别:" + ArgumentsConstants.CONFIG_UPLOAD_TYPE); // } // FileStoreType fileStoreType = FileStoreType.getType(remoteFileStoreType); // 2023-07-03,如果配置远程上传为本地 if(this.acquireFileOperateSpi().isRemoteAsLocal()){ return this.acquireFileOperateSpi().uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); } FileStoreType fileStoreType = FileStoreType.getType(remoteFileStoreType); String ossType = BeanContextAware.getBeanByType(FileProperties.class).getOssType(); if(StringUtils.isEmpty(ossType)){ throw new PlatformRuntimeException("平台未配置任何ossType"); } FileStoreType fileStoreType = FileStoreType.getType(ossType); if(fileStoreType == FileStoreType.Ftp){ return this.acquireFileOperateSpi().uploadFileToFtp(inputStream, fileName, groupId, fileSize, businessType, owner); } else { iplatform-base/src/main/java/com/iplatform/base/ArgumentsConstants.java
@@ -28,9 +28,15 @@ /** 移动端域名 */ public static final String CONFIG_KEY_SITE_URL = "site_url"; /** 图片上传类型 1本地 2七牛云 3OSS 4COS, 默认本地 /** 图片上传类型 1-本地 2-七牛云 3-阿里云OSS 4-腾讯OSS 5-亚马逊s3, 默认本地 * <p>支持系统自己的定义常量,参考:{@linkplain com.walker.file.FileStoreType}</p> * <pre> * 1) 上传到本地,还是远程,业务选择,系统会配置远程ossType标识哪个平台。 * 2) 对于文件是存储本地还是远程,通过:isRemoteAsLocal()方法判断,可以用在测试阶段。 * </pre> * * */ @Deprecated public static final String CONFIG_UPLOAD_TYPE = "uploadType"; /** 全局本地图片域名 */ @@ -41,6 +47,8 @@ public static final String CONFIG_AL_UPLOAD_URL = "alUploadUrl"; /** 腾讯云上传URL */ public static final String CONFIG_TX_UPLOAD_URL = "txUploadUrl"; /** 亚马逊S3上传URL */ public static final String CONFIG_S3_UPLOAD_URL = "s3UploadUrl"; /** FTP上传URL */ public static final String CONFIG_FTP_UPLOAD_URL = "ftpUploadUrl"; iplatform-base/src/main/java/com/iplatform/base/config/FileProperties.java
@@ -30,6 +30,79 @@ this.remoteAsLocal = remoteAsLocal; } /** * oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛) * @return * @date 2023-12-13 */ public String getOssType() { return ossType; } public void setOssType(String ossType) { this.ossType = ossType; } /** * oss访问前缀,如:http://localhost:8082/admin/oss/ * @return * @date 2023-12-13 */ public String getOssPrefix() { return ossPrefix; } public void setOssPrefix(String ossPrefix) { this.ossPrefix = ossPrefix; } public String getOssAccessKey() { return ossAccessKey; } public void setOssAccessKey(String ossAccessKey) { this.ossAccessKey = ossAccessKey; } public String getOssSecretKey() { return ossSecretKey; } public void setOssSecretKey(String ossSecretKey) { this.ossSecretKey = ossSecretKey; } public String getOssEndpoint() { return ossEndpoint; } public void setOssEndpoint(String ossEndpoint) { this.ossEndpoint = ossEndpoint; } public String getOssBucketName() { return ossBucketName; } public void setOssBucketName(String ossBucketName) { this.ossBucketName = ossBucketName; } public String getProtocolStr() { return protocolStr; } public void setProtocolStr(String protocolStr) { this.protocolStr = protocolStr; } private String ossAccessKey; private String ossSecretKey; private String ossEndpoint; private String ossBucketName; private String ossType; private String ossPrefix; private String protocolStr = "http"; private boolean remoteAsLocal = true; private String fileRoot = null; iplatform-file-server/pom.xml
@@ -39,6 +39,13 @@ <scope>provided</scope> </dependency> <!-- 亚马逊S3 OSS 服务配置,2023-12-12 --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.11.126</version> </dependency> <!-- |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |~ 以下配置为"独立部署方式",2023-02-12 iplatform-file-server/src/main/java/com/iplatform/file/FileEngineFactory.java
@@ -1,5 +1,6 @@ package com.iplatform.file; import com.iplatform.base.PlatformRuntimeException; import com.iplatform.file.util.FileStoreUtils; import com.walker.file.FileInfo; import com.walker.file.FileOperateEngine; @@ -25,6 +26,21 @@ public class FileEngineFactory implements ApplicationBeanInitialized { protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); /** * 下载oss文件 * @param fileStoreType * @param id 文件唯一编号 * @return * @date 2023-12-13 */ public byte[] downloadOssFile(FileStoreType fileStoreType, String id){ try { return this.fileOperateEngineMap.get(fileStoreType).downloadFile(id); } catch (FileOperateException e) { throw new PlatformRuntimeException("下载oss文件错误:" + e.getMessage() + ", id=" + id, e); } } /** * 根据文件ID,返回文件对象。 @@ -142,7 +158,8 @@ public FileInfo uploadFileToOss(InputStream inputStream, String fileName, String groupId , long fileSize, Integer businessType, String owner, FileStoreType fileStoreType) throws FileOperateException{ if(fileStoreType != FileStoreType.OssQiNiu && fileStoreType != FileStoreType.OssTx && fileStoreType != FileStoreType.OssAli){ && fileStoreType != FileStoreType.OssTx && fileStoreType != FileStoreType.OssAli && fileStoreType != FileStoreType.OssAws){ throw new UnsupportedOperationException("不支持的OSS类型:" + fileStoreType); } if(this.remoteAsLocal){ @@ -155,7 +172,8 @@ public FileInfo[] uploadFileToOss(InputStream[] inputStream, String[] fileName, String groupId , long[] fileSize, Integer businessType, String owner, FileStoreType fileStoreType) throws FileOperateException{ if(fileStoreType != FileStoreType.OssQiNiu && fileStoreType != FileStoreType.OssTx && fileStoreType != FileStoreType.OssAli){ && fileStoreType != FileStoreType.OssTx && fileStoreType != FileStoreType.OssAli && fileStoreType != FileStoreType.OssAws){ throw new UnsupportedOperationException("不支持的OSS类型:" + fileStoreType); } if(this.remoteAsLocal){ iplatform-file-server/src/main/java/com/iplatform/file/config/FileConfig.java
@@ -1,11 +1,13 @@ package com.iplatform.file.config; import com.iplatform.base.config.FileProperties; import com.iplatform.core.PlatformConfiguration; import com.iplatform.file.FileEngineFactory; import com.iplatform.file.FileStoreCallback; import com.iplatform.file.service.FileServiceImpl; import com.iplatform.file.support.AliOssFileEngine; import com.iplatform.file.support.AttachmentJdbcCallback; import com.iplatform.file.support.AwsOssFileEngine; import com.iplatform.file.support.DefaultFileSystemEngine; import com.iplatform.file.support.DefaultFtpFileEngine; import com.iplatform.file.support.QnOssFileEngine; @@ -17,7 +19,7 @@ import org.springframework.context.annotation.Configuration; @Configuration public class FileConfig { public class FileConfig extends PlatformConfiguration { /** * 配置一个文件引擎工厂对象。 @@ -30,6 +32,7 @@ @Bean public FileEngineFactory fileEngineFactory(DefaultFtpFileEngine ftpFileEngine, DefaultFileSystemEngine fileSystemEngine , QnOssFileEngine qnOssFileEngine, TxOssFileEngine txOssFileEngine, AliOssFileEngine aliOssFileEngine , AwsOssFileEngine awsOssFileEngine , ArgumentsManager argumentsManager, FileProperties fileProperties){ FileEngineFactory fileEngineFactory = new FileEngineFactory(); fileEngineFactory.register(FileStoreType.Ftp, ftpFileEngine); @@ -37,6 +40,9 @@ fileEngineFactory.register(FileStoreType.OssQiNiu, qnOssFileEngine); fileEngineFactory.register(FileStoreType.OssTx, txOssFileEngine); fileEngineFactory.register(FileStoreType.OssAli, aliOssFileEngine); // 2023-12-13 fileEngineFactory.register(FileStoreType.OssAws, awsOssFileEngine); fileEngineFactory.setArgumentsManager(argumentsManager); fileEngineFactory.setRemoteAsLocal(fileProperties.isRemoteAsLocal()); fileEngineFactory.startup(); @@ -44,6 +50,28 @@ } /** * 创建:OSS服务引擎。 * * @param fileProperties * @param fileStoreCallback * @return * @date 2023-12-13 */ @Bean public AwsOssFileEngine awsOssFileEngine(FileProperties fileProperties, FileStoreCallback fileStoreCallback) throws Exception { AwsOssFileEngine engine = new AwsOssFileEngine(); engine.setPrefix(fileProperties.getOssPrefix()); engine.setFileStoreCallback(fileStoreCallback); engine.setAccessKey(fileProperties.getOssAccessKey()); engine.setSecretKey(fileProperties.getOssSecretKey()); engine.setEndpoint(fileProperties.getOssEndpoint()); engine.setBucketName(fileProperties.getOssBucketName()); engine.initS3Client(); logger.info(".............. OSS 初始化: 亚马逊S3!"); return engine; } /** * 阿里云 OSS 文件引擎定义。 * @param fileProperties * @param fileStoreCallback iplatform-file-server/src/main/java/com/iplatform/file/support/AbstractOssFileEngine.java
@@ -38,5 +38,19 @@ this.fileStoreCallback = fileStoreCallback; } /** * 返回OSS访问前缀,通常在配置yaml文件中配置。 * @return * @date 2023-12-13 */ public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } private String prefix; // oss前缀,2023-12-13 private FileStoreCallback fileStoreCallback = null; } iplatform-file-server/src/main/java/com/iplatform/file/support/AwsOssFileEngine.java
New file @@ -0,0 +1,359 @@ package com.iplatform.file.support; import com.amazonaws.ClientConfiguration; import com.amazonaws.Protocol; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.auth.policy.Policy; import com.amazonaws.auth.policy.Principal; import com.amazonaws.auth.policy.Resource; import com.amazonaws.auth.policy.Statement; import com.amazonaws.auth.policy.actions.S3Actions; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration; import com.amazonaws.services.s3.model.CORSRule; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.PutObjectResult; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectInputStream; import com.amazonaws.services.s3.model.SetBucketPolicyRequest; import com.walker.file.DefaultFileInfo; import com.walker.file.FileInfo; import com.walker.file.FileOperateException; import com.walker.file.FileStoreType; import com.walker.infrastructure.utils.Base64; import com.walker.infrastructure.utils.JsonUtils; import com.walker.infrastructure.utils.StringUtils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Calendar; /** * 亚马逊S3 OSS 实现。 * * @author 时克英 * @date 2023-12-12 */ public class AwsOssFileEngine extends AbstractOssFileEngine { public AwsOssFileEngine() { } @Override protected void executeUpload(InputStream inputStream, FileInfo fileInfo) throws FileOperateException { //初始化对象元数据 ObjectMetadata metadata = new ObjectMetadata(); // metadata.setContentType("plain/text"); AmazonS3 client = this.acquireOneClient(); try { String fileNameBase64 = new String(Base64.encode(fileInfo.getFileName().getBytes(StringUtils.DEFAULT_CHARSET_UTF8))); metadata.addUserMetadata("x-amz-meta-title", fileNameBase64); metadata.setContentLength(fileInfo.getFileSize()); //设置对象元数据 String objectKey = fileInfo.getId(); logger.debug("准备上传文件 objectKey = {}", objectKey); // String objectKey = createFileOssPath(fileInfo.getId(), fileInfo.getFileExt()); PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, inputStream, metadata); // PutObjectResult result = amazonS3Client.putObject(putObjectRequest); PutObjectResult result = client.putObject(putObjectRequest); System.out.println(JsonUtils.objectToJsonString(result)); StringBuilder url = new StringBuilder(); url.append(objectKey); // ((DefaultFileInfo) fileInfo).setFileSize(result.getMetadata().getContentLength()); ((DefaultFileInfo) fileInfo).setUrl(url.toString()); } catch (Exception var11) { throw new FileOperateException("保存文件到【oss】错误:" + var11.getMessage() + ", id=" + fileInfo.getId(), var11); } finally { if(client != null){ client.shutdown(); } } } @Override protected byte[] executeDownload(FileInfo fileInfo) throws FileOperateException { // throw new IllegalAccessError("不能调用OSS下载方法,请访问第三方链接"); AmazonS3 client = this.acquireOneClient(); S3ObjectInputStream objectContent = null; ByteArrayOutputStream fileOutputStream = null; try { //下载对象 S3Object object = client.getObject(bucketName, fileInfo.getId()); //获取对象流 objectContent = object.getObjectContent(); //初始化文件输出流 // FileOutputStream fileOutputStream = new FileOutputStream(new File(file_path)); fileOutputStream = new ByteArrayOutputStream(); byte[] readbuf = new byte[1024 * 20]; int read_len = 0; while ((read_len = objectContent.read(readbuf)) > 0) { //对象下载字节写入文件输出流 fileOutputStream.write(readbuf, 0, read_len); } return fileOutputStream.toByteArray(); } catch (Exception ex) { throw new FileOperateException("下载文件错误:" + ex.getMessage() + ", fileId=" + fileInfo.getId(), ex); } finally { //关闭流 try { if(objectContent != null){ objectContent.close(); } // if(fileOutputStream != null){ // fileOutputStream.close(); // } if(client != null){ client.shutdown(); } } catch (IOException e) { // throw new RuntimeException(e); logger.error("这里不需要抛出异常,仅用于调试知道流没有被关闭即可。", e); } } } @Override public FileStoreType getFileStoreType() { return FileStoreType.OssAws; } @Override public void close() { super.close(); this.closeAmazonS3Client(); } private AmazonS3 acquireOneClient(){ AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); ClientConfiguration clientConfiguration = new ClientConfiguration(); if (endpoint.contains("https")) { clientConfiguration.setProtocol(Protocol.HTTPS); logger.error("===================> HTTPS "); } else { clientConfiguration.setProtocol(Protocol.HTTP); logger.error("===================> HTTP "); } return AmazonS3ClientBuilder.standard() .withClientConfiguration(clientConfiguration) .withEndpointConfiguration( new AwsClientBuilder.EndpointConfiguration(this.endpoint, Regions.DEFAULT_REGION.getName())) .withCredentials(new AWSStaticCredentialsProvider(credentials)) .build(); // AmazonS3 amazonS3Client = new AmazonS3Client(credentials, clientConfiguration); // amazonS3Client.setEndpoint(endpoint); // amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); // return amazonS3Client; } /** * 初始化amazonS3Client * @author 时克英 * @date 2024-02-02 使用多例,无需初始化,废弃方法。 */ @Deprecated public void initS3Client() { logger.warn("不再使用单例,无需初始化,每次上传下载会创建新客户端连接!"); // AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); //创建AWS凭证 // ClientConfiguration connconfig = new ClientConfiguration(); //初始化客户端config // connconfig.setProtocol(Protocol.HTTP); //设置mos 请求协议为http // // //使用AWS凭证和clientConfiguration初始化AmazonS3Client客户端 // amazonS3Client = new AmazonS3Client(credentials, connconfig); // amazonS3Client.setEndpoint(endpoint); ////设置mos对象服务接口地址 // amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); // AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); // ClientConfiguration clientConfiguration = new ClientConfiguration(); // // if (endpoint.contains("https")) { // clientConfiguration.setProtocol(Protocol.HTTPS); // logger.error("===================> HTTPS "); // } else { // clientConfiguration.setProtocol(Protocol.HTTP); // logger.error("===================> HTTP "); // } // // AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(endpoint, "beijing1"); // AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials); // // // amazonS3Client = AmazonS3ClientBuilder.standard() // .withEndpointConfiguration(endpointConfiguration) // .withCredentials(credentialsProvider).build(); //// amazonS3Client = new AmazonS3Client(credentials, clientConfiguration); //// amazonS3Client.setEndpoint(endpoint); //// amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); ClientConfiguration clientConfiguration = new ClientConfiguration(); if (endpoint.contains("https")) { clientConfiguration.setProtocol(Protocol.HTTPS); logger.error("===================> HTTPS "); } else { clientConfiguration.setProtocol(Protocol.HTTP); logger.error("===================> HTTP "); } // 设置允许打开的最大 HTTP 连接数,默认为 50 个,此示例代码设置为 100 个。 // clientConfiguration.setMaxConnections(100 * 2); // // 设置 Socket 层传输数据的超时时间(单位:毫秒),默认为 50000 毫秒,此示例代码设置为 60000 毫秒。 // clientConfiguration.setSocketTimeout(60000 * 2); // // 设置建立连接的超时时间(单位:毫秒),默认为 10000 毫秒,此示例代码设置为 5000 毫秒。 // clientConfiguration.setConnectionTimeout(5000 * 2); // // 设置等待请求完成的超时时间(单位:毫秒)。默认不超时(0),此示例代码设置为 60000 毫秒。 // clientConfiguration.setRequestTimeout(60000 * 2); // // 设置客户端请求执行超时时间(单位:毫秒)。默认不超时(0),此示例代码设置为 60000 毫秒。 // clientConfiguration.setClientExecutionTimeout(60000 * 2); // // 设置连接空闲超时时间。超时则关闭连接,默认为 60000 毫秒,此示例代码设置为 90000 毫秒。 //// clientConfiguration.setConnectionMaxIdleMillis(90000 * 2); // // 设置请求失败后最大的重试次数,默认 3 次,此示例代码设置为 5 次。 // clientConfiguration.setMaxErrorRetry(5); // 设置连接 EOS 所使用的协议(HTTP 或 HTTPS),默认为 HTTPS,此示例代码设置为 HTTP。 // clientConfiguration.setProtocol(Protocol.HTTP); // 设置用户代理前缀,即 HTTP 的 User-Agent 头的前缀,此示例代码设置为 "EOS S3 Java SDK"。 // clientConfiguration.setUserAgentPrefix("EOS S3 Java SDK"); // 设置用户代理后缀,即 HTTP 的 User-Agent 头的后缀,此示例代码设置为 "1.12.378"。 // clientConfiguration.setUserAgentSuffix("1.12.378"); // 设置签名算法,默认为 v4 签名。此示例代码设置为 S3SignerType,即采用 v2 签名。 // clientConfiguration.setSignerOverride("S3SignerType"); // 2024-02-02,不用单例,使用多例即:每次调用创建客户端方式! // amazonS3Client = new AmazonS3Client(credentials, clientConfiguration); // amazonS3Client.setEndpoint(endpoint); // amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); } /** * 对应MOS JAVA SDK文档4.3.6章节 设置存储桶策略 */ @Deprecated public void setBucketPolicy() throws IOException { // List<String> readLines = Files.readLines(new File("policy.txt"), Charset.forName("utf8")); // StringBuilder sb = new StringBuilder(); // for(String str : readLines) // { // sb.append(str); // } // System.out.println(sb.toString()); // // //policy 信息查看项目根目录 policy.txt文件 // String policy = sb.toString(); // amazonS3Client.setBucketPolicy(bucket_name, policy); //通过Policy类构建桶策略 Policy bucket_policy = new Policy().withStatements(new Statement( Statement.Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(S3Actions.GetObject) .withResources( new Resource("arn:aws:s3:::" + bucketName + "/*"))); SetBucketPolicyRequest setBucketPolicyRequest = new SetBucketPolicyRequest(bucketName, bucket_policy.toJson()); //设置桶策略 // amazonS3Client.setBucketPolicy(setBucketPolicyRequest); } @Deprecated public void configBucketCors() { // 配置跨域访问策略 BucketCrossOriginConfiguration conf = new BucketCrossOriginConfiguration() .withRules( new CORSRule() .withId("1")// 配置规则 ID .withAllowedHeaders(Arrays.asList("*")) // 跨域请求可以使用的 HTTP 请求头部,支持通配符 * .withAllowedMethods(Arrays.asList(CORSRule.AllowedMethods.GET, CORSRule.AllowedMethods.PUT))// 跨域请求允许的 HTTP 操作,例如:GET,PUT,HEAD,POST,DELETE // .withAllowedOrigins(Arrays.asList("http://www.example1.com"))// 允许的访问来源,支持通配符 *,格式为:协议://域名[:端口] // .withMaxAgeSeconds(30)// 跨域请求得到结果的有效期 ); // SetBucketCrossOriginConfigurationRequest req = new SetBucketCrossOriginConfigurationRequest("bkt", conf); // amazonS3Client.setBucketCrossOriginConfiguration(req); // 删除跨域访问策略 // amazonS3Client.deleteBucketCrossOriginConfiguration("1"); } /** * 关闭amazonS3Client */ private void closeAmazonS3Client() { // if (this.amazonS3Client != null) { // amazonS3Client.shutdown(); //关闭客户端 // } } public byte[] testDownload(String fileId){ DefaultFileInfo fileInfo = new DefaultFileInfo(); fileInfo.setId(fileId); try { return this.executeDownload(fileInfo); } catch (FileOperateException e) { throw new RuntimeException("下载oss文件报错:" + e.getMessage() + ", fileId=" + fileId, e); } } public void setAccessKey(String accessKey) { this.accessKey = accessKey; } public void setSecretKey(String secretKey) { this.secretKey = secretKey; } public void setEndpoint(String endpoint) { this.endpoint = endpoint; } public void setBucketName(String bucketName) { this.bucketName = bucketName; } public void setProtocol(Protocol protocol) { this.protocol = protocol; } private String bucketName = "ctoms-file"; public String endpoint = "http://10.2.36.9:8080"; private String accessKey = "4XJOR8RXEWWRVV8N4HOC"; private String secretKey = "1Dp2ua3lcCocEQJMf1VtHBABPfpkUxF4gGE3xacW"; private Protocol protocol = Protocol.HTTP; // private AmazonS3 amazonS3Client; public String createFileOssPath(String fileId, String ext) { Calendar ca = Calendar.getInstance(); String year = ca.get(Calendar.YEAR) + ""; String mon = ca.get(Calendar.MONTH) + 1 + ""; String day = ca.get(Calendar.DAY_OF_MONTH) + ""; String directory = year + "/" + mon + "/" + day + "/"; // mkdirFolder(directory); return fileId + StringUtils.SYMBOL_DOT + ext; } // 上传前上设置文件夹 public boolean mkdirFolder(String directory) { AmazonS3 client = this.acquireOneClient(); PutObjectResult putObjectResult = client.putObject(bucketName, directory, new ByteArrayInputStream(new byte[0]), null); return putObjectResult != null; } } iplatform-support-mybatis/pom.xml
@@ -48,6 +48,12 @@ <artifactId>iplatform-core</artifactId> </dependency> <!-- 提供数据库jdbc支持,查询表元数据, 2024/02/20 --> <dependency> <groupId>com.walkersoft</groupId> <artifactId>walker-jdbc</artifactId> </dependency> <!--velocity代码生成使用模板 --> <!-- <dependency>--> <!-- <groupId>org.apache.velocity</groupId>--> iplatform-support-mybatis/src/main/java/com/iplatform/mybatis/service/MetaDataServiceImpl.java
New file @@ -0,0 +1,179 @@ package com.iplatform.mybatis.service; import com.iplatform.mybatis.domain.GenTable; import com.iplatform.mybatis.domain.GenTableColumn; import com.iplatform.mybatis.util.DataTypeUtils; import com.iplatform.mybatis.util.SqlUtils; import com.walker.db.DatabaseType; import com.walker.infrastructure.utils.DateUtils; import com.walker.infrastructure.utils.StringUtils; import com.walker.jdbc.JdbcInspector; import com.walker.jdbc.service.BaseServiceImpl; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Service public class MetaDataServiceImpl extends BaseServiceImpl { /** * 返回从元数据中查询的表结构信息 * @param tableName 表名称,可以是表前缀 * @param isPrecision 是否精确查找,如果是则仅返回和表名一样的表结构。 * @param packageName 包名称,必填 * @param moduleName 模块名称,选填 * @param businessName 业务名称,选填 * @param functionName 功能名称,选填 * @return * @date 2024-02-20 */ public List<GenTable> queryDatabaseTableInfo(String tableName, boolean isPrecision , String packageName, String moduleName, String businessName, String functionName){ List<GenTable> genTableList = new ArrayList<>(8); DatabaseType databaseType = JdbcInspector.getInstance().getPrimaryDatabaseType(); log.debug("databaseType = " + databaseType.toString()); if(DataTypeUtils.isOracle(databaseType)){ // oracle元数据中表名都是大写 tableName = tableName.toUpperCase(); } else { tableName = tableName.toLowerCase(); } Map<String, Object> sqlMap = new HashMap<>(); if(isPrecision){ sqlMap.put("tablename", "%" + tableName); } else { sqlMap.put("tablename", tableName + "%"); } String sql_table = ""; // String sql_pk = ""; String sql_column = ""; if (DataTypeUtils.isOracle(databaseType)) { sql_table = "select table_name from user_tables where table_name like :tablename order by table_name desc"; // sql_pk = "select col.table_name,col.column_name from user_constraints con,user_cons_columns col where con.constraint_name=col.constraint_name and con.constraint_type='P' and col.table_name like :tablename "; sql_column = SqlUtils.ORACLE_QUERY_COLUMNS; } else if(DataTypeUtils.isMysql(databaseType)) { sql_table = "select table_name from information_schema.tables where table_schema=(SELECT DATABASE()) and table_name like :tablename order by table_name desc"; // sql_pk = "select table_name,column_name from INFORMATION_SCHEMA.Columns where column_key='PRI' AND table_schema=(SELECT DATABASE()) and table_name like :tablename"; sql_column = "select table_name,column_name,data_type,NUMERIC_PRECISION data_precision,NUMERIC_SCALE data_scale, column_key from INFORMATION_SCHEMA.Columns where table_schema=(SELECT DATABASE()) and table_name like :tablename order by table_name,ordinal_position\n"; } else if(databaseType == DatabaseType.POSTGRES){ sql_table = "SELECT c.relname table_name from pg_class c, pg_namespace n where c.relkind = 'r' and n.nspname = 'public' and c.relnamespace = n.oid and c.relname like :tablename"; sql_column = SqlUtils.SQL_PG_FIELDS; log.debug("POSTGRES......"); } else { throw new UnsupportedOperationException("(po生成)不支持的数据库类型:" + databaseType); } List<Map<String, Object>> table_list = this.dao.select(sql_table, sqlMap); List<Map<String, Object>> column_list = this.dao.select(sql_column, sqlMap); log.debug("生成表结构(PO) = {}", table_list); for (Map<String, Object> table : table_list) { String table_name = table.get("table_name").toString(); String pk_name = "id"; String pk_type = "NUMBER"; List<Map<String, Object>> column_temp = new ArrayList<>(); String columnKey = null; for (Map<String, Object> column : column_list) { if(!column.get("table_name").toString().equalsIgnoreCase(table.get("table_name").toString())){ // 只有当前表字段才处理,老代码遍历所有表字段有问题。2022-09-20 continue; } // 2022-09-07 修改(后续有oracle需求还需要改) if(column.get("column_key") != null){ columnKey = column.get("column_key").toString(); if(DataTypeUtils.isPrimaryColumn(columnKey)){ // mysql主键字段是:PRI,oracle是:P,2023-03-03 修改 pk_name = column.get("column_name").toString().toLowerCase(); pk_type = column.get("data_type").toString().toLowerCase(); log.info(table_name + " 找到主键:" + pk_name + ", " + pk_type); continue; } } if ((table_name.equalsIgnoreCase(column.get("table_name").toString())) && (!column.get("column_name").toString().equalsIgnoreCase(pk_name))) { String type = column.get("data_type").toString().toLowerCase(); column.put("name", column.get("column_name").toString().toLowerCase()); if ((type.equalsIgnoreCase("number")) || (type.equalsIgnoreCase("decimal"))) { int precision = Integer.valueOf(column.get("data_precision") == null ? "0" : column.get("data_precision").toString()).intValue(); int scale = Integer.valueOf(column.get("data_scale") == null ? "0" : column.get("data_scale").toString()).intValue(); type = DataTypeUtils.getType(type, precision, scale); } column.put("type", type); column_temp.add(column); } } table.put("table_name", table_name.toLowerCase()); table.put("pk_name", pk_name); // table.put("pk_type", pk_type); table.put("pk_type", DataTypeUtils.getType(pk_type, 0, 0)); table.put("columns", column_temp); GenTable genTable = this.acquireGenTable(table, packageName, moduleName, businessName, functionName, pk_name); genTableList.add(genTable); } return genTableList; } private GenTable acquireGenTable(Map<String, Object> table , String packageName, String moduleName, String businessName, String functionName, String pkName){ GenTable genTable = new GenTable(); genTable.setCreateTime(DateUtils.getDateTimeNumber()); genTable.setTableName(table.get("table_name").toString()); genTable.setTableComment(StringUtils.EMPTY_STRING); genTable.setClassName(StringUtils.transferUnderlineName2Camel(genTable.getTableName(), true)); genTable.setTplCategory("crud"); genTable.setGenType("0"); genTable.setFunctionAuthor("shikeying"); genTable.setPackageName(packageName); // genTable.setGenPath("/"); if(StringUtils.isNotEmpty(moduleName)){ genTable.setModuleName(moduleName); } if(StringUtils.isNotEmpty(businessName)){ genTable.setBusinessName(businessName); } if(StringUtils.isNotEmpty(functionName)){ genTable.setFunctionName(functionName); } List<GenTableColumn> genTableColumnList = new ArrayList<>(); List<Map<String, Object>> columns = (List<Map<String, Object>>)table.get("columns"); GenTableColumn genTableColumn = null; boolean isPrimaryKey = false; for(Map<String, Object> map : columns){ if(StringUtils.isNotEmpty(pkName) && map.get("column_name").toString().equals(pkName)){ isPrimaryKey = true; } genTableColumn = this.acquireGenColumn(map, isPrimaryKey); if(isPrimaryKey){ genTable.setPkColumn(genTableColumn); } genTableColumnList.add(genTableColumn); } genTable.setColumns(genTableColumnList); return genTable; } private GenTableColumn acquireGenColumn(Map<String, Object> map, boolean isPrimaryKey){ GenTableColumn genTableColumn = new GenTableColumn(); genTableColumn.setCreateTime(DateUtils.getDateTimeNumber()); genTableColumn.setColumnName(map.get("column_name").toString()); genTableColumn.setColumnType(map.get("type").toString()); genTableColumn.setColumnComment(StringUtils.EMPTY_STRING); if(isPrimaryKey){ genTableColumn.setIsPk("1"); } genTableColumn.setJavaField(StringUtils.transferUnderlineName2Camel(genTableColumn.getColumnName(), true)); return genTableColumn; } } iplatform-support-mybatis/src/main/java/com/iplatform/mybatis/util/DataTypeUtils.java
New file @@ -0,0 +1,90 @@ package com.iplatform.mybatis.util; import com.walker.db.DatabaseType; public class DataTypeUtils { public static final String PRIMARY_KEY_MYSQL = "PRI"; public static final String PRIMARY_KEY_ORACLE = "P"; public static boolean isMysql(DatabaseType databaseType){ // if (databaseType == DatabaseType.ORACLE || databaseType == DatabaseType.DAMENG) { // return false; // } else { // return true; // } return databaseType == DatabaseType.MYSQL || databaseType == DatabaseType.SQLITE; } public static boolean isOracle(DatabaseType databaseType){ if (databaseType == DatabaseType.ORACLE || databaseType == DatabaseType.DAMENG) { return true; } return false; } public static boolean isPrimaryColumn(String columnKey){ if(columnKey.equalsIgnoreCase(PRIMARY_KEY_MYSQL) || columnKey.equalsIgnoreCase(PRIMARY_KEY_ORACLE)){ return true; } return false; } public static String getType(String type_name, int column_size, int decimal_digits) { if (type_name.contains("CHAR") || type_name.toLowerCase().indexOf("varchar") >= 0 || type_name.equalsIgnoreCase("nvarchar2") // PG数据库字符串字段类型,2023-10-10 || type_name.indexOf("character") >= 0) return "string"; if (("NUMBER".equalsIgnoreCase(type_name)) || ("DECIMAL".equalsIgnoreCase(type_name))) { if (decimal_digits == 0) { if (column_size > 0 && column_size <= 8) { return "int"; } return "long"; } if (column_size < 14) { return "double"; } return "big_decimal"; } // 2023-10-10 postgresql if(type_name.equalsIgnoreCase("integer")){ if(column_size > 4){ // 8 位表示长整形 return "long"; } else { return "int"; } } if(type_name.indexOf("numeric") >= 0){ return "double"; } if (("DATE".equalsIgnoreCase(type_name)) || ("DATETIME".equalsIgnoreCase(type_name)) || (type_name.startsWith("TIMESTAMP"))) return "date"; if ("INT".equalsIgnoreCase(type_name)) return "int"; if (("Long".equalsIgnoreCase(type_name)) || ("BIGINT".equalsIgnoreCase(type_name))) return "long"; if ("FLOAT".equalsIgnoreCase(type_name)) return "float"; if ("SMALLINT".equalsIgnoreCase(type_name)) return "int"; if ("TINYINT".equalsIgnoreCase(type_name)) return "byte"; if ("DOUBLE".equalsIgnoreCase(type_name) || type_name.indexOf("double") >= 0) return "double"; if (("CLOB".equalsIgnoreCase(type_name)) || ("TEXT".equalsIgnoreCase(type_name)) || ("MEDIUMTEXT".equalsIgnoreCase(type_name)) || ("LONGTEXT".equalsIgnoreCase(type_name))) // return "materialized_clob"; return "string"; if (type_name.contains("BLOB")) { return "materialized_blob"; } throw new RuntimeException("类型 " + type_name + " 不支持! "); } } iplatform-support-mybatis/src/main/java/com/iplatform/mybatis/util/SqlUtils.java
New file @@ -0,0 +1,29 @@ package com.iplatform.mybatis.util; public class SqlUtils { public static final String SQL_PG_FIELDS = "SELECT\n" + "\tC.relname table_name,\n" + "\tA.attname AS column_name, A.attlen data_precision,\n" + "\tformat_type ( A.atttypid, A.atttypmod ) AS data_type,\n" + "\tcol_description ( A.attrelid, A.attnum ) AS COMMENT, 0 AS data_scale,\n" + "(CASE WHEN ( SELECT COUNT(*) FROM pg_constraint WHERE conrelid = a.attrelid AND conkey[1]= attnum AND contype = 'p' ) > 0 THEN\n" + " 'PRI' ELSE '' \n" + " END ) AS column_key\n" + "FROM\n" + "\tpg_class AS C,\n" + "\tpg_attribute AS A,\n" + "\tpg_tables AS B\n" + "WHERE A.attrelid = C.oid\n" + " and C.relname=B.tablename\n" + " AND A.attnum > 0\n" + " AND B.schemaname = 'public' and c.relname like :tablename"; public static final String ORACLE_QUERY_COLUMNS = new StringBuilder("select t1.*, ucc.constraint_name, uc.constraint_type column_key from (") .append("select c.table_name, c.column_name, c.data_type, c.data_length, c.data_precision, c.data_scale, c.nullable, c.column_id, s.comments ") .append("from user_tab_columns c, user_col_comments s ") .append("where c.table_name like :tablename and c.table_name = s.table_name and c.column_name = s.column_name order by c.column_id") .append(") t1 ") .append("left join user_cons_columns ucc on ucc.table_name=t1.table_name and ucc.column_name=t1.column_name ") .append("left join user_constraints uc on uc.constraint_name=ucc.constraint_name").toString(); } iplatform-test-mybatis/pom.xml
New file @@ -0,0 +1,33 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>iplatform</artifactId> <groupId>com.iplatform</groupId> <version>2.7.18</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>iplatform-test-mybatis</artifactId> <name>iplatform-test-mybatis</name> <packaging>jar</packaging> <properties> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.iplatform</groupId> <artifactId>iplatform-support-mybatis</artifactId> </dependency> </dependencies> </project> iplatform-test-mybatis/src/main/java/com/iplatform/test/Test1.java
New file @@ -0,0 +1,4 @@ package com.iplatform.test; public class Test1 { } iplatform-test-mybatis/src/main/java/com/iplatform/test/controller/EbUserController.java
New file @@ -0,0 +1,107 @@ package com.iplatform.test.controller; import java.util.List; import java.util.Arrays; import com.insurance.common.annotation.RepeatSubmit; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.insurance.common.annotation.Log; import com.insurance.common.core.controller.BaseController; import com.insurance.common.core.domain.AjaxResult; import com.insurance.common.enums.BusinessType; import com.iplatform.test.domain.vo.EbUserVo; import com.iplatform.test.domain.bo.EbUserBo; import com.iplatform.test.domain.bo.EbUserQueryBo; import com.iplatform.test.service.IEbUserService; import com.insurance.common.utils.poi.ExcelUtil; import com.insurance.common.core.page.TableDataInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; /** * 【请填写功能名称】Controller * * @author shikeying * @date 2024-02-20 */ @Api(value = "【请填写功能名称】控制器", tags = {"【请填写功能名称】管理"}) @RequiredArgsConstructor(onConstructor_ = @Autowired) @RestController @RequestMapping("/${moduleName}/${businessName}") public class EbUserController extends BaseController { private final IEbUserService iEbUserService; @ApiOperation("查询【请填写功能名称】列表") @GetMapping("/list") public TableDataInfo list(EbUserQueryBo bo) { startPage(); List<EbUserVo> list = iEbUserService.queryList(bo); return getDataTable(list); } @ApiOperation("导出【请填写功能名称】列表") //@PreAuthorize("@ss.hasPermi('null:null:export')") @Log(title = "【请填写功能名称】", businessType = BusinessType.EXPORT) @GetMapping("/export") @RepeatSubmit public AjaxResult export(EbUserQueryBo bo) { List<EbUserVo> list = iEbUserService.queryList(bo); ExcelUtil<EbUserVo> util = new ExcelUtil<EbUserVo>(EbUserVo.class); return util.exportExcel(list, "【请填写功能名称】"); } @ApiOperation("获取【请填写功能名称】详细信息") @GetMapping("/{${pkColumn.javaField}}") public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}" ) ${pkColumn.javaType} ${pkColumn.javaField}) { return AjaxResult.success(iEbUserService.queryById(${pkColumn.javaField})); } @ApiOperation("新增【请填写功能名称】") //@PreAuthorize("@ss.hasPermi('null:null:add')") @Log(title = "【请填写功能名称】", businessType = BusinessType.INSERT) @PostMapping("/add") @RepeatSubmit public AjaxResult add(@RequestBody EbUserBo bo) { return toAjax(iEbUserService.insertByBo(bo) ? 1 : 0); } @ApiOperation("修改【请填写功能名称】") //@PreAuthorize("@ss.hasPermi('null:null:edit')") @Log(title = "【请填写功能名称】", businessType = BusinessType.UPDATE) @PostMapping("/upd") @RepeatSubmit public AjaxResult upd(@RequestBody EbUserBo bo) { return toAjax(iEbUserService.updateByBo(bo) ? 1 : 0); } @ApiOperation("删除【请填写功能名称】") //@PreAuthorize("@ss.hasPermi('null:null:remove')") @Log(title = "【请填写功能名称】" , businessType = BusinessType.DELETE) @DeleteMapping("/{${pkColumn.javaField}s}") @RepeatSubmit public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) { return toAjax(iEbUserService.deleteByIds(Arrays.asList(${pkColumn.javaField}s)) ? 1 : 0); } } iplatform-test-mybatis/src/main/java/com/iplatform/test/domain/EbUser.java
New file @@ -0,0 +1,158 @@ package com.iplatform.test.domain; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; //import io.swagger.annotations.ApiModel; //import io.swagger.annotations.ApiModelProperty; /** * 【请填写功能名称】对象 eb_user * * @author shikeying * @date 2024-02-20 */ @Data @NoArgsConstructor @Accessors(chain = true) @TableName("eb_user") //@ApiModel("【请填写功能名称】实体对象") public class EbUser implements Serializable { private static final long serialVersionUID=1L; @ApiModelProperty("") private $column.javaType Account; @ApiModelProperty("") private $column.javaType Pwd; @ApiModelProperty("") private $column.javaType RealName; @ApiModelProperty("") private $column.javaType Birthday; @ApiModelProperty("") private $column.javaType IdentityCardNo; @ApiModelProperty("") private $column.javaType TagId; @ApiModelProperty("") private $column.javaType Nickname; @ApiModelProperty("") private $column.javaType Avatar; @ApiModelProperty("") private $column.javaType Phone; @ApiModelProperty("") private $column.javaType Country; @ApiModelProperty("") private $column.javaType Province; @ApiModelProperty("") private $column.javaType City; @ApiModelProperty("") private $column.javaType District; @ApiModelProperty("") private $column.javaType Address; @ApiModelProperty("") private $column.javaType Sex; @ApiModelProperty("") private $column.javaType Integral; @ApiModelProperty("") private $column.javaType Experience; @ApiModelProperty("") private $column.javaType NowMoney; @ApiModelProperty("") private $column.javaType BrokeragePrice; @ApiModelProperty("") private $column.javaType Level; @ApiModelProperty("") private $column.javaType SignNum; @ApiModelProperty("") private $column.javaType IsWechatPublic; @ApiModelProperty("") private $column.javaType IsWechatRoutine; @ApiModelProperty("") private $column.javaType PayCount; @ApiModelProperty("") private $column.javaType IsPromoter; @ApiModelProperty("") private $column.javaType PromoterTime; @ApiModelProperty("") private $column.javaType SpreadUid; @ApiModelProperty("") private $column.javaType SpreadTime; @ApiModelProperty("") private $column.javaType SpreadCount; @ApiModelProperty("") private $column.javaType RegisterType; @ApiModelProperty("") private $column.javaType AddIp; @ApiModelProperty("") private $column.javaType LastIp; @ApiModelProperty("") private $column.javaType LastLoginTime; @ApiModelProperty("") private $column.javaType Status; @ApiModelProperty("") private $column.javaType Mark; @ApiModelProperty("") private $column.javaType CreateTime; @ApiModelProperty("") private $column.javaType UpdateTime; @ApiModelProperty("") private $column.javaType IsLogoff; @ApiModelProperty("") private $column.javaType LogoffTime; @ApiModelProperty("") private $column.javaType IsWechatIos; @ApiModelProperty("") private $column.javaType IsWechatAndroid; @ApiModelProperty("") private $column.javaType IsBindingIos; @ApiModelProperty("") private $column.javaType MoneySign; } iplatform-test-mybatis/src/main/java/com/iplatform/test/domain/bo/EbUserBo.java
New file @@ -0,0 +1,20 @@ package com.iplatform.test.domain.bo; //import io.swagger.annotations.ApiModel; //import io.swagger.annotations.ApiModelProperty; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.util.Date; /** * 【请填写功能名称】编辑对象 eb_user * * @author shikeying * @date 2024-02-20 */ @Data //@ApiModel("【请填写功能名称】操作对象") public class EbUserBo { } iplatform-test-mybatis/src/main/java/com/iplatform/test/domain/bo/EbUserQueryBo.java
New file @@ -0,0 +1,36 @@ package com.iplatform.test.domain.bo; import com.insurance.common.core.domain.BaseQuery; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; /** * 【请填写功能名称】分页查询对象 eb_user * * @author shikeying * @date 2024-02-20 */ @EqualsAndHashCode(callSuper = true) @Data //@ApiModel("【请填写功能名称】分页查询对象") public class EbUserQueryBo extends BaseQuery{ /** 分页大小 */ @ApiModelProperty("分页大小") private Integer pageSize; /** 当前页数 */ @ApiModelProperty("当前页数") private Integer pageNum; /** 排序列 */ @ApiModelProperty("排序列") private String orderByColumn; /** 排序的方向desc或者asc */ @ApiModelProperty(value = "排序的方向", example = "asc,desc") private String isAsc; } iplatform-test-mybatis/src/main/java/com/iplatform/test/domain/vo/EbUserVo.java
New file @@ -0,0 +1,25 @@ package com.iplatform.test.domain.vo; import com.iplatform.mybatis.Excel; import com.fasterxml.jackson.annotation.JsonFormat; //import io.swagger.annotations.ApiModel; //import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 【请填写功能名称】视图对象 mall_package * * @author shikeying * @date 2024-02-20 */ @Data //@ApiModel("【请填写功能名称】视图对象") public class EbUserVo { private static final long serialVersionUID = 1L; /** $pkColumn.columnComment */ //@ApiModelProperty("$pkColumn.columnComment") private ${pkColumn.javaType} ${pkColumn.javaField}; } iplatform-test-mybatis/src/main/java/com/iplatform/test/mapper/EbUserMapper.java
New file @@ -0,0 +1,14 @@ package com.iplatform.test.mapper; import com.iplatform.test.domain.EbUser; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * 【请填写功能名称】Mapper接口 * * @author shikeying * @date 2024-02-20 */ public interface EbUserMapper extends BaseMapper<EbUser> { } iplatform-test-mybatis/src/main/java/com/iplatform/test/service/IEbUserService.java
New file @@ -0,0 +1,53 @@ package com.iplatform.test.service; import com.iplatform.test.domain.EbUser; import com.iplatform.test.domain.vo.EbUserVo; import com.iplatform.test.domain.bo.EbUserBo; import com.iplatform.test.domain.bo.EbUserQueryBo; import com.baomidou.mybatisplus.extension.service.IService; import com.iplatform.mybatis.IBaseService; import java.util.Collection; import java.util.List; /** * 【请填写功能名称】Service接口 * * @author shikeying * @date 2024-02-20 */ public interface IEbUserService extends IBaseService<EbUser> { /** * 查询列表 */ List<EbUserVo> queryList(EbUserQueryBo bo); /** * 查询单个 * @return EbUserVo */ EbUserVo queryById(${pkColumn.javaType} ${pkColumn.javaField}); /** * 根据新增业务对象插入【请填写功能名称】 * @param bo 【请填写功能名称】新增业务对象 * @return true成功 false失败 */ Boolean insertByBo(EbUserBo bo); /** * 根据编辑业务对象修改【请填写功能名称】 * @param bo 【请填写功能名称】编辑业务对象 * @return true成功 false失败 */ Boolean updateByBo(EbUserBo bo); /** * 校验并删除数据 * @param ids 主键集合 * @return true成功 false失败 */ Boolean deleteByIds(Collection<Long> ids); } iplatform-test-mybatis/src/main/java/com/iplatform/test/service/impl/EbUserServiceImpl.java
New file @@ -0,0 +1,100 @@ package com.iplatform.test.service.impl; import lombok.RequiredArgsConstructor; import cn.hutool.core.convert.Convert; import com.iplatform.core.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.iplatform.test.domain.vo.EbUserVo; import com.iplatform.test.domain.bo.EbUserBo; import com.iplatform.test.domain.bo.EbUserQueryBo; import com.iplatform.test.domain.EbUser; import com.iplatform.test.mapper.EbUserMapper; import com.iplatform.test.service.IEbUserService; import java.util.Collection; import java.util.List; /** * 【请填写功能名称】Service业务层处理 * * @author shikeying * @date 2024-02-20 */ @Service @RequiredArgsConstructor(onConstructor_ = @Autowired) public class EbUserServiceImpl extends ServiceImpl<EbUserMapper, EbUser> implements IEbUserService { @Override//列表查询 public List<EbUserVo> queryList(EbUserQueryBo bo) { QueryWrapper<EbUser> qw = getQw(bo); List<EbUser> list = this.list(qw); return Convert.toList(EbUserVo.class , list); } @Override//id查询 public EbUserVo queryById(${pkColumn.javaType} ${pkColumn.javaField}) { EbUser db = this.baseMapper.selectById(${pkColumn.javaField}); return Convert.convert(EbUserVo.class , db); } @Override//添加 @Transactional public Boolean insertByBo(EbUserBo bo) { EbUser add = Convert.convert(EbUser.class, bo); validEntityBeforeSave(add); return this.save(add); } @Override//修改 @Transactional public Boolean updateByBo(EbUserBo bo) { EbUser update = Convert.convert(EbUser.class, bo); validEntityBeforeSave(update); return this.updateById(update); } @Override//删除 @Transactional public Boolean deleteByIds(Collection<Long> ids) { //做一些业务上的校验,判断是否需要校验 return this.removeByIds(ids); } //------------------------------------------------------------------------------------- //保存前校验 private void validEntityBeforeSave(EbUser entity) { //做一些数据校验,如唯一约束 } //获取查询参数 private QueryWrapper<EbUser> getQw(EbUserQueryBo bo) { QueryWrapper<EbUser> qw = Wrappers.query(); if (StringUtils.isNotEmpty(bo.getIsAsc()) && StringUtils.isNotEmpty(bo.getOrderByColumn())){ if ("acs".equals(bo.getIsAsc())) { qw.orderByAsc(bo.getOrderByColumn()); } else if ("desc".equals(bo.getIsAsc())) { qw.orderByDesc(bo.getOrderByColumn()); } } return qw; } } iplatform-test-mybatis/src/test/java/com/iplatform/AppTest.java
New file @@ -0,0 +1,20 @@ package com.iplatform; import static org.junit.Assert.assertTrue; import org.junit.Test; /** * Unit test for simple App. */ public class AppTest { /** * Rigorous Test :-) */ @Test public void shouldAnswerWithTrue() { assertTrue( true ); } } pom.xml
@@ -27,6 +27,7 @@ <module>ishop-mobile</module> <module>iplatform-base-tcp-client</module> <module>iplatform-support-mybatis</module> <module>iplatform-test-mybatis</module> </modules> <parent> @@ -221,6 +222,13 @@ <version>${iplatform.version}</version> </dependency> <!-- mybatis示例模块,2024-02-19 --> <dependency> <groupId>com.iplatform</groupId> <artifactId>iplatform-test-mybatis</artifactId> <version>${iplatform.version}</version> </dependency> <!-- 推送实现模块,2023-04-24 --> <dependency> <groupId>com.walkersoft</groupId>