diff --git a/ruoyi-common/ruoyi-common-oss/pom.xml b/ruoyi-common/ruoyi-common-oss/pom.xml index 09a994f8e..5f3c8cfdc 100644 --- a/ruoyi-common/ruoyi-common-oss/pom.xml +++ b/ruoyi-common/ruoyi-common-oss/pom.xml @@ -23,34 +23,8 @@ - com.qiniu - qiniu-java-sdk - ${qiniu.version} - - - com.aliyun.oss - aliyun-sdk-oss - ${aliyun.oss.version} - - - com.qcloud - cos_api - ${qcloud.cos.version} - - - org.slf4j - slf4j-log4j12 - - - org.bouncycastle - bcprov-jdk15on - - - - - io.minio - minio - ${minio.version} + com.amazonaws + aws-java-sdk-s3 diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java index 3e5730e4c..8566ec58c 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java @@ -8,31 +8,41 @@ import java.util.List; * * @author Lion Li */ -public class OssConstant { +public interface OssConstant { /** * OSS模块KEY */ - public static final String SYS_OSS_KEY = "sys_oss:"; + String SYS_OSS_KEY = "sys_oss:"; /** * 对象存储配置KEY */ - public static final String OSS_CONFIG_KEY = "OssConfig"; + String OSS_CONFIG_KEY = "OssConfig"; /** * 缓存配置KEY */ - public static final String CACHE_CONFIG_KEY = SYS_OSS_KEY + OSS_CONFIG_KEY; + String CACHE_CONFIG_KEY = SYS_OSS_KEY + OSS_CONFIG_KEY; /** * 预览列表资源开关Key */ - public static final String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource"; + String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource"; /** * 系统数据ids */ - public static final List SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4); + List SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4); + + /** + * 云服务商 + */ + String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu"}; + + /** + * https 状态 + */ + String IS_HTTPS = "Y"; } diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java deleted file mode 100644 index cc2813813..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.ruoyi.common.oss.enumd; - -import com.ruoyi.common.oss.service.impl.AliyunOssStrategy; -import com.ruoyi.common.oss.service.impl.MinioOssStrategy; -import com.ruoyi.common.oss.service.impl.QcloudOssStrategy; -import com.ruoyi.common.oss.service.impl.QiniuOssStrategy; -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 对象存储服务商枚举 - * - * @author Lion Li - */ -@Getter -@AllArgsConstructor -public enum OssEnumd { - - /** - * 七牛云 - */ - QINIU("qiniu", QiniuOssStrategy.class), - - /** - * 阿里云 - */ - ALIYUN("aliyun", AliyunOssStrategy.class), - - /** - * 腾讯云 - */ - QCLOUD("qcloud", QcloudOssStrategy.class), - - /** - * minio - */ - MINIO("minio", MinioOssStrategy.class); - - private final String value; - - private final Class beanClass; - - public static OssEnumd find(String value) { - for (OssEnumd enumd : values()) { - if (enumd.getValue().equals(value)) { - return enumd; - } - } - return null; - } - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java index 704874bdf..c019d3bf4 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java @@ -1,19 +1,3 @@ -/* - * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the dreamlu.net developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: Chill 庄骞 (smallchill@163.com) - */ package com.ruoyi.common.oss.enumd; import lombok.AllArgsConstructor; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java index 107d646d0..c609ced31 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java @@ -1,17 +1,17 @@ package com.ruoyi.common.oss.factory; import com.ruoyi.common.core.utils.JsonUtils; -import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.oss.constant.OssConstant; -import com.ruoyi.common.oss.enumd.OssEnumd; +import com.ruoyi.common.oss.core.OssClient; import com.ruoyi.common.oss.exception.OssException; import com.ruoyi.common.oss.properties.OssProperties; -import com.ruoyi.common.oss.service.IOssStrategy; -import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy; import com.ruoyi.common.redis.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * 文件上传Factory * @@ -20,17 +20,19 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class OssFactory { + private static final Map CLIENT_CACHE = new ConcurrentHashMap<>(); + /** * 初始化工厂 */ public static void init() { log.info("初始化OSS工厂"); - RedisUtils.subscribe(OssConstant.CACHE_CONFIG_KEY, String.class, type -> { - AbstractOssStrategy strategy = getStrategy(type); + RedisUtils.subscribe(OssConstant.CACHE_CONFIG_KEY, String.class, configKey -> { + OssClient client = getClient(configKey); // 未初始化不处理 - if (strategy.isInit) { - refresh(type); - log.info("订阅刷新OSS配置 => " + type); + if (client != null) { + refresh(configKey); + log.info("订阅刷新OSS配置 => " + configKey); } }); } @@ -38,42 +40,38 @@ public class OssFactory { /** * 获取默认实例 */ - public static IOssStrategy instance() { + public static OssClient instance() { // 获取redis 默认类型 - String type = RedisUtils.getCacheObject(OssConstant.CACHE_CONFIG_KEY); - if (StringUtils.isEmpty(type)) { + String configKey = RedisUtils.getCacheObject(OssConstant.CACHE_CONFIG_KEY); + if (StringUtils.isEmpty(configKey)) { throw new OssException("文件存储服务类型无法找到!"); } - return instance(type); + return instance(configKey); } /** * 根据类型获取实例 */ - public static IOssStrategy instance(String type) { - OssEnumd enumd = OssEnumd.find(type); - if (enumd == null) { - throw new OssException("文件存储服务类型无法找到!"); + public static OssClient instance(String configKey) { + OssClient client = getClient(configKey); + if (client == null) { + refresh(configKey); + return getClient(configKey); } - AbstractOssStrategy strategy = getStrategy(type); - if (!strategy.isInit) { - refresh(type); - } - return strategy; + return client; } - private static void refresh(String type) { - Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + type); + private static void refresh(String configKey) { + Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + configKey); OssProperties properties = JsonUtils.parseObject(json.toString(), OssProperties.class); if (properties == null) { - throw new OssException("系统异常, '" + type + "'配置信息不存在!"); + throw new OssException("系统异常, '" + configKey + "'配置信息不存在!"); } - getStrategy(type).init(properties); + CLIENT_CACHE.put(configKey, new OssClient(configKey, properties)); } - private static AbstractOssStrategy getStrategy(String type) { - OssEnumd enumd = OssEnumd.find(type); - return (AbstractOssStrategy) SpringUtils.getBean(enumd.getBeanClass()); + private static OssClient getClient(String configKey) { + return CLIENT_CACHE.get(configKey); } } diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java index 2975f9510..78b62ab4c 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java @@ -15,6 +15,11 @@ public class OssProperties { */ private String endpoint; + /** + * 自定义域名 + */ + private String domain; + /** * 前缀 */ diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java deleted file mode 100644 index ca7f76294..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.ruoyi.common.oss.service; - - -import com.ruoyi.common.oss.entity.UploadResult; -import com.ruoyi.common.oss.enumd.OssEnumd; - -import java.io.InputStream; - -/** - * 对象存储策略 - * - * @author Lion Li - */ -public interface IOssStrategy { - - /** - * 创建存储桶 - */ - void createBucket(); - - /** - * 获取服务商类型 - * @return 对象存储服务商枚举 - */ - OssEnumd getServiceType(); - - /** - * 文件上传 - * - * @param data 文件字节数组 - * @param path 文件路径,包含文件名 - * @param contentType 文件类型 - * @return 返回http地址 - */ - UploadResult upload(byte[] data, String path, String contentType); - - /** - * 文件删除 - * - * @param path 文件路径,包含文件名 - */ - void delete(String path); - - /** - * 文件上传 - * - * @param data 文件字节数组 - * @param suffix 后缀 - * @param contentType 文件类型 - * @return 返回http地址 - */ - UploadResult uploadSuffix(byte[] data, String suffix, String contentType); - - /** - * 文件上传 - * - * @param inputStream 字节流 - * @param path 文件路径,包含文件名 - * @param contentType 文件类型 - * @return 返回http地址 - */ - UploadResult upload(InputStream inputStream, String path, String contentType); - - /** - * 文件上传 - * - * @param inputStream 字节流 - * @param suffix 后缀 - * @param contentType 文件类型 - * @return 返回http地址 - */ - UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType); - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java deleted file mode 100644 index f1aaa315f..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.common.oss.service.abstractd; - -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.IdUtil; -import com.ruoyi.common.core.utils.DateUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.oss.entity.UploadResult; -import com.ruoyi.common.oss.enumd.OssEnumd; -import com.ruoyi.common.oss.properties.OssProperties; -import com.ruoyi.common.oss.service.IOssStrategy; - -import java.io.InputStream; - -/** - * 对象存储策略(支持七牛、阿里云、腾讯云、minio) - * - * @author Lion Li - */ -public abstract class AbstractOssStrategy implements IOssStrategy { - - protected OssProperties properties; - public boolean isInit = false; - - public void init(OssProperties properties) { - this.properties = properties; - } - - @Override - public abstract void createBucket(); - - @Override - public abstract OssEnumd getServiceType(); - - public String getPath(String prefix, String suffix) { - // 生成uuid - String uuid = IdUtil.fastSimpleUUID(); - // 文件路径 - String path = DateUtils.datePath() + "/" + uuid; - if (StringUtils.isNotBlank(prefix)) { - path = prefix + "/" + path; - } - return path + suffix; - } - - @Override - public abstract UploadResult upload(byte[] data, String path, String contentType); - - @Override - public abstract void delete(String path); - - @Override - public UploadResult upload(InputStream inputStream, String path, String contentType) { - byte[] data = IoUtil.readBytes(inputStream); - return this.upload(data, path, contentType); - } - - @Override - public abstract UploadResult uploadSuffix(byte[] data, String suffix, String contentType); - - @Override - public abstract UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType); - - /** - * 获取域名访问链接 - * - * @return 域名访问链接 - */ - public abstract String getEndpointLink(); -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java deleted file mode 100644 index f0d3fb355..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.ruoyi.common.oss.service.impl; - -import com.aliyun.oss.ClientConfiguration; -import com.aliyun.oss.OSSClient; -import com.aliyun.oss.common.auth.DefaultCredentialProvider; -import com.aliyun.oss.model.CannedAccessControlList; -import com.aliyun.oss.model.CreateBucketRequest; -import com.aliyun.oss.model.ObjectMetadata; -import com.aliyun.oss.model.PutObjectRequest; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.oss.entity.UploadResult; -import com.ruoyi.common.oss.enumd.OssEnumd; -import com.ruoyi.common.oss.exception.OssException; -import com.ruoyi.common.oss.properties.OssProperties; -import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy; -import org.springframework.stereotype.Component; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -/** - * 阿里云存储策略 - * - * @author Lion Li - */ -@Component -public class AliyunOssStrategy extends AbstractOssStrategy { - - private OSSClient client; - - @Override - public void init(OssProperties ossProperties) { - super.init(ossProperties); - try { - ClientConfiguration configuration = new ClientConfiguration(); - DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider( - properties.getAccessKey(), properties.getSecretKey()); - client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration); - createBucket(); - } catch (Exception e) { - throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]"); - } - isInit = true; - } - - @Override - public void createBucket() { - try { - String bucketName = properties.getBucketName(); - if (client.doesBucketExist(bucketName)) { - return; - } - CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); - createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); - client.createBucket(createBucketRequest); - } catch (Exception e) { - throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]"); - } - } - - @Override - public OssEnumd getServiceType() { - return OssEnumd.ALIYUN; - } - - @Override - public UploadResult upload(byte[] data, String path, String contentType) { - return upload(new ByteArrayInputStream(data), path, contentType); - } - - @Override - public UploadResult upload(InputStream inputStream, String path, String contentType) { - try { - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentType(contentType); - client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata)); - } catch (Exception e) { - throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]"); - } - return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build(); } - - @Override - public void delete(String path) { - path = path.replace(getEndpointLink() + "/", ""); - try { - client.deleteObject(properties.getBucketName(), path); - } catch (Exception e) { - throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]"); - } - } - - @Override - public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { - return upload(data, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public String getEndpointLink() { - String endpoint = properties.getEndpoint(); - StringBuilder sb = new StringBuilder(endpoint); - if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) { - sb.insert(7, properties.getBucketName() + "."); - } else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) { - sb.insert(8, properties.getBucketName() + "."); - } else { - throw new OssException("Endpoint配置错误"); - } - return sb.toString(); - } -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java deleted file mode 100644 index 60c1ea7b5..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.ruoyi.common.oss.service.impl; - -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.oss.entity.UploadResult; -import com.ruoyi.common.oss.enumd.OssEnumd; -import com.ruoyi.common.oss.enumd.PolicyType; -import com.ruoyi.common.oss.exception.OssException; -import com.ruoyi.common.oss.properties.OssProperties; -import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy; -import io.minio.*; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -/** - * minio存储策略 - * - * @author Lion Li - */ -@Component -public class MinioOssStrategy extends AbstractOssStrategy { - - private MinioClient minioClient; - - @Override - public void init(OssProperties ossProperties) { - super.init(ossProperties); - try { - minioClient = MinioClient.builder() - .endpoint(properties.getEndpoint()) - .credentials(properties.getAccessKey(), properties.getSecretKey()) - .build(); - createBucket(); - } catch (Exception e) { - throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]"); - } - isInit = true; - } - - @Override - public void createBucket() { - try { - String bucketName = properties.getBucketName(); - boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); - if (exists) { - return; - } - // 不存在就创建桶 - minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); - minioClient.setBucketPolicy(SetBucketPolicyArgs.builder() - .bucket(bucketName) - .config(getPolicy(bucketName, PolicyType.READ)) - .build()); - } catch (Exception e) { - throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]"); - } - } - - @Override - public OssEnumd getServiceType() { - return OssEnumd.MINIO; - } - - @Override - public UploadResult upload(byte[] data, String path, String contentType) { - return upload(new ByteArrayInputStream(data), path, contentType); - } - - @Override - public UploadResult upload(InputStream inputStream, String path, String contentType) { - try { - // 解决 inputStream.available() 在 socket 下传输延迟问题 导致获取数值不精确 - Thread.sleep(1000); - minioClient.putObject(PutObjectArgs.builder() - .bucket(properties.getBucketName()) - .object(path) - .contentType(StringUtils.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE)) - .stream(inputStream, inputStream.available(), -1) - .build()); - } catch (Exception e) { - throw new OssException("上传文件失败,请核对Minio配置信息:[" + e.getMessage() + "]"); - } - return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build(); - } - - @Override - public void delete(String path) { - path = path.replace(getEndpointLink() + "/", ""); - try { - minioClient.removeObject(RemoveObjectArgs.builder() - .bucket(properties.getBucketName()) - .object(path) - .build()); - } catch (Exception e) { - throw new OssException(e.getMessage()); - } - } - - @Override - public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { - return upload(data, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public String getEndpointLink() { - return properties.getEndpoint() + "/" + properties.getBucketName(); - } - - private String getPolicy(String bucketName, PolicyType policyType) { - StringBuilder builder = new StringBuilder(); - builder.append("{\n"); - builder.append(" \"Statement\": [\n"); - builder.append(" {\n"); - builder.append(" \"Action\": [\n"); - if (policyType == PolicyType.WRITE) { - builder.append(" \"s3:GetBucketLocation\",\n"); - builder.append(" \"s3:ListBucketMultipartUploads\"\n"); - } else if (policyType == PolicyType.READ_WRITE) { - builder.append(" \"s3:GetBucketLocation\",\n"); - builder.append(" \"s3:ListBucket\",\n"); - builder.append(" \"s3:ListBucketMultipartUploads\"\n"); - } else { - builder.append(" \"s3:GetBucketLocation\"\n"); - } - builder.append(" ],\n"); - builder.append(" \"Effect\": \"Allow\",\n"); - builder.append(" \"Principal\": \"*\",\n"); - builder.append(" \"Resource\": \"arn:aws:s3:::"); - builder.append(bucketName); - builder.append("\"\n"); - builder.append(" },\n"); - if (PolicyType.READ.equals(policyType)) { - builder.append(" {\n"); - builder.append(" \"Action\": [\n"); - builder.append(" \"s3:ListBucket\"\n"); - builder.append(" ],\n"); - builder.append(" \"Effect\": \"Deny\",\n"); - builder.append(" \"Principal\": \"*\",\n"); - builder.append(" \"Resource\": \"arn:aws:s3:::"); - builder.append(bucketName); - builder.append("\"\n"); - builder.append(" },\n"); - } - builder.append(" {\n"); - builder.append(" \"Action\": "); - switch (policyType) { - case WRITE: - builder.append("[\n"); - builder.append(" \"s3:AbortMultipartUpload\",\n"); - builder.append(" \"s3:DeleteObject\",\n"); - builder.append(" \"s3:ListMultipartUploadParts\",\n"); - builder.append(" \"s3:PutObject\"\n"); - builder.append(" ],\n"); - break; - case READ_WRITE: - builder.append("[\n"); - builder.append(" \"s3:AbortMultipartUpload\",\n"); - builder.append(" \"s3:DeleteObject\",\n"); - builder.append(" \"s3:GetObject\",\n"); - builder.append(" \"s3:ListMultipartUploadParts\",\n"); - builder.append(" \"s3:PutObject\"\n"); - builder.append(" ],\n"); - break; - default: - builder.append("\"s3:GetObject\",\n"); - break; - } - builder.append(" \"Effect\": \"Allow\",\n"); - builder.append(" \"Principal\": \"*\",\n"); - builder.append(" \"Resource\": \"arn:aws:s3:::"); - builder.append(bucketName); - builder.append("/*\"\n"); - builder.append(" }\n"); - builder.append(" ],\n"); - builder.append(" \"Version\": \"2012-10-17\"\n"); - builder.append("}\n"); - return builder.toString(); - } -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java deleted file mode 100644 index 6c19b346e..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.ruoyi.common.oss.service.impl; - -import com.qcloud.cos.COSClient; -import com.qcloud.cos.ClientConfig; -import com.qcloud.cos.auth.BasicCOSCredentials; -import com.qcloud.cos.auth.COSCredentials; -import com.qcloud.cos.http.HttpProtocol; -import com.qcloud.cos.model.*; -import com.qcloud.cos.region.Region; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.oss.entity.UploadResult; -import com.ruoyi.common.oss.enumd.OssEnumd; -import com.ruoyi.common.oss.exception.OssException; -import com.ruoyi.common.oss.properties.OssProperties; -import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy; -import org.springframework.stereotype.Component; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -/** - * 腾讯云存储策略 - * - * @author Lion Li - */ -@Component -public class QcloudOssStrategy extends AbstractOssStrategy { - - private COSClient client; - - @Override - public void init(OssProperties ossProperties) { - super.init(ossProperties); - try { - COSCredentials credentials = new BasicCOSCredentials( - properties.getAccessKey(), properties.getSecretKey()); - // 初始化客户端配置 - ClientConfig clientConfig = new ClientConfig(); - // 设置bucket所在的区域,华南:gz 华北:tj 华东:sh - clientConfig.setRegion(new Region(properties.getRegion())); - if ("Y".equals(properties.getIsHttps())) { - clientConfig.setHttpProtocol(HttpProtocol.https); - } else { - clientConfig.setHttpProtocol(HttpProtocol.http); - } - client = new COSClient(credentials, clientConfig); - createBucket(); - } catch (Exception e) { - throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]"); - } - isInit = true; - } - - @Override - public void createBucket() { - try { - String bucketName = properties.getBucketName(); - if (client.doesBucketExist(bucketName)) { - return; - } - CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); - createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead); - client.createBucket(createBucketRequest); - } catch (Exception e) { - throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]"); - } - } - - @Override - public OssEnumd getServiceType() { - return OssEnumd.QCLOUD; - } - - @Override - public UploadResult upload(byte[] data, String path, String contentType) { - return upload(new ByteArrayInputStream(data), path, contentType); - } - - @Override - public UploadResult upload(InputStream inputStream, String path, String contentType) { - try { - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentType(contentType); - client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata)); - } catch (Exception e) { - throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]"); - } - return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build(); - } - - @Override - public void delete(String path) { - path = path.replace(getEndpointLink() + "/", ""); - try { - client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path)); - } catch (Exception e) { - throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]"); - } - } - - @Override - public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { - return upload(data, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public String getEndpointLink() { - String endpoint = properties.getEndpoint(); - StringBuilder sb = new StringBuilder(endpoint); - if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) { - sb.insert(7, properties.getBucketName() + "."); - } else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) { - sb.insert(8, properties.getBucketName() + "."); - } else { - throw new OssException("Endpoint配置错误"); - } - return sb.toString(); - } -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java deleted file mode 100644 index e35ed2402..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.ruoyi.common.oss.service.impl; - -import cn.hutool.core.util.ArrayUtil; -import com.qiniu.http.Response; -import com.qiniu.storage.BucketManager; -import com.qiniu.storage.Configuration; -import com.qiniu.storage.Region; -import com.qiniu.storage.UploadManager; -import com.qiniu.util.Auth; -import com.ruoyi.common.oss.entity.UploadResult; -import com.ruoyi.common.oss.enumd.OssEnumd; -import com.ruoyi.common.oss.exception.OssException; -import com.ruoyi.common.oss.properties.OssProperties; -import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy; -import org.springframework.stereotype.Component; - -import java.io.InputStream; - -/** - * 七牛云存储策略 - * - * @author Lion Li - */ -@Component -public class QiniuOssStrategy extends AbstractOssStrategy { - - private UploadManager uploadManager; - private BucketManager bucketManager; - private Auth auth; - - - @Override - public void init(OssProperties ossProperties) { - super.init(ossProperties); - try { - Configuration config = new Configuration(getRegion(properties.getRegion())); - // https设置 - config.useHttpsDomains = false; - config.useHttpsDomains = "Y".equals(properties.getIsHttps()); - uploadManager = new UploadManager(config); - auth = Auth.create(properties.getAccessKey(), properties.getSecretKey()); - bucketManager = new BucketManager(auth, config); - createBucket(); - } catch (Exception e) { - throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]"); - } - isInit = true; - } - - @Override - public void createBucket() { - try { - String bucketName = properties.getBucketName(); - if (ArrayUtil.contains(bucketManager.buckets(), bucketName)) { - return; - } - bucketManager.createBucket(bucketName, properties.getRegion()); - } catch (Exception e) { - throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]"); - } - } - - @Override - public OssEnumd getServiceType() { - return OssEnumd.QINIU; - } - - @Override - public UploadResult upload(byte[] data, String path, String contentType) { - try { - String token = auth.uploadToken(properties.getBucketName()); - Response res = uploadManager.put(data, path, token, null, contentType, false); - if (!res.isOK()) { - throw new RuntimeException("上传七牛出错:" + res.error); - } - } catch (Exception e) { - throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]"); - } - return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build(); - } - - @Override - public void delete(String path) { - try { - path = path.replace(getEndpointLink() + "/", ""); - Response res = bucketManager.delete(properties.getBucketName(), path); - if (!res.isOK()) { - throw new RuntimeException("删除七牛文件出错:" + res.error); - } - } catch (Exception e) { - throw new OssException(e.getMessage()); - } - } - - @Override - public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { - return upload(data, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType); - } - - @Override - public String getEndpointLink() { - return properties.getEndpoint(); - } - - private Region getRegion(String region) { - switch (region) { - case "z0": - return Region.region0(); - case "z1": - return Region.region1(); - case "z2": - return Region.region2(); - case "na0": - return Region.regionNa0(); - case "as0": - return Region.regionAs0(); - default: - return Region.autoRegion(); - } - } - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories index 1d4e49695..ab43764ea 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories +++ b/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories @@ -1,5 +1 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.ruoyi.common.oss.service.impl.AliyunOssStrategy,\ - com.ruoyi.common.oss.service.impl.MinioOssStrategy,\ - com.ruoyi.common.oss.service.impl.QcloudOssStrategy,\ - com.ruoyi.common.oss.service.impl.QiniuOssStrategy +org.springframework.boot.autoconfigure.EnableAutoConfiguration= diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/SysOssConfig.java b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/SysOssConfig.java index 08cc89fa1..869648c21 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/SysOssConfig.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/SysOssConfig.java @@ -52,6 +52,12 @@ public class SysOssConfig extends BaseEntity { */ private String endpoint; + /** + * 自定义域名 + */ + private String domain; + + /** * 是否https(0否 1是) */ diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/bo/SysOssConfigBo.java b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/bo/SysOssConfigBo.java index b1b722509..cc7acba90 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/bo/SysOssConfigBo.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/bo/SysOssConfigBo.java @@ -35,8 +35,8 @@ public class SysOssConfigBo extends BaseEntity { /** * 配置key */ - @ApiModelProperty(value = "configKey", required = true) - @NotBlank(message = "configKey不能为空", groups = {AddGroup.class, EditGroup.class}) + @ApiModelProperty(value = "配置key", required = true) + @NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "configKey长度必须介于2和20 之间") private String configKey; @@ -59,8 +59,8 @@ public class SysOssConfigBo extends BaseEntity { /** * 桶名称 */ - @ApiModelProperty(value = "bucketName", required = true) - @NotBlank(message = "bucketName不能为空", groups = {AddGroup.class, EditGroup.class}) + @ApiModelProperty(value = "桶名称", required = true) + @NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "bucketName长度必须介于2和100之间") private String bucketName; @@ -73,11 +73,17 @@ public class SysOssConfigBo extends BaseEntity { /** * 访问站点 */ - @ApiModelProperty(value = "endpoint", required = true) - @NotBlank(message = "endpoint不能为空", groups = {AddGroup.class, EditGroup.class}) + @ApiModelProperty(value = "访问站点", required = true) + @NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "endpoint长度必须介于2和100之间") private String endpoint; + /** + * 自定义域名 + */ + @ApiModelProperty("自定义域名") + private String domain; + /** * 是否https(Y=是,N=否) */ @@ -93,7 +99,7 @@ public class SysOssConfigBo extends BaseEntity { /** * 域 */ - @ApiModelProperty(value = "region") + @ApiModelProperty(value = "域") private String region; /** diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/vo/SysOssConfigVo.java b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/vo/SysOssConfigVo.java index 31d754c13..d5e2db629 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/vo/SysOssConfigVo.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/domain/vo/SysOssConfigVo.java @@ -60,6 +60,12 @@ public class SysOssConfigVo { @ApiModelProperty("访问站点") private String endpoint; + /** + * 自定义域名 + */ + @ApiModelProperty("自定义域名") + private String domain; + /** * 是否https(Y=是,N=否) */ diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/dubbo/RemoteFileServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/dubbo/RemoteFileServiceImpl.java index 045450403..13f880151 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/dubbo/RemoteFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/dubbo/RemoteFileServiceImpl.java @@ -2,9 +2,9 @@ package com.ruoyi.resource.dubbo; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.oss.core.OssClient; import com.ruoyi.common.oss.entity.UploadResult; import com.ruoyi.common.oss.factory.OssFactory; -import com.ruoyi.common.oss.service.IOssStrategy; import com.ruoyi.resource.api.RemoteFileService; import com.ruoyi.resource.api.domain.SysFile; import com.ruoyi.resource.domain.SysOss; @@ -36,7 +36,7 @@ public class RemoteFileServiceImpl implements RemoteFileService { public SysFile upload(String name, String originalFilename, String contentType, byte[] file) throws ServiceException { try { String suffix = StringUtils.substring(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length()); - IOssStrategy storage = OssFactory.instance(); + OssClient storage = OssFactory.instance(); UploadResult uploadResult = storage.uploadSuffix(file, suffix, contentType); // 保存文件信息 SysOss oss = new SysOss(); @@ -44,7 +44,7 @@ public class RemoteFileServiceImpl implements RemoteFileService { oss.setFileSuffix(suffix); oss.setFileName(uploadResult.getFilename()); oss.setOriginalName(originalFilename); - oss.setService(storage.getServiceType().getValue()); + oss.setService(storage.getConfigKey()); sysOssMapper.insert(oss); SysFile sysFile = new SysFile(); sysFile.setName(uploadResult.getFilename()); diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/service/impl/SysOssServiceImpl.java index 9c2051482..5ff496f0e 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/com/ruoyi/resource/service/impl/SysOssServiceImpl.java @@ -7,9 +7,9 @@ import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.mybatis.core.page.PageQuery; import com.ruoyi.common.mybatis.core.page.TableDataInfo; +import com.ruoyi.common.oss.core.OssClient; import com.ruoyi.common.oss.entity.UploadResult; import com.ruoyi.common.oss.factory.OssFactory; -import com.ruoyi.common.oss.service.IOssStrategy; import com.ruoyi.resource.domain.SysOss; import com.ruoyi.resource.domain.bo.SysOssBo; import com.ruoyi.resource.domain.vo.SysOssVo; @@ -65,7 +65,7 @@ public class SysOssServiceImpl implements ISysOssService { public SysOss upload(MultipartFile file) { String originalfileName = file.getOriginalFilename(); String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); - IOssStrategy storage = OssFactory.instance(); + OssClient storage = OssFactory.instance(); UploadResult uploadResult; try { uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType()); @@ -78,7 +78,7 @@ public class SysOssServiceImpl implements ISysOssService { oss.setFileSuffix(suffix); oss.setFileName(uploadResult.getFilename()); oss.setOriginalName(originalfileName); - oss.setService(storage.getServiceType().getValue()); + oss.setService(storage.getConfigKey()); baseMapper.insert(oss); return oss; } @@ -90,7 +90,7 @@ public class SysOssServiceImpl implements ISysOssService { } List list = baseMapper.selectBatchIds(ids); for (SysOss sysOss : list) { - IOssStrategy storage = OssFactory.instance(sysOss.getService()); + OssClient storage = OssFactory.instance(sysOss.getService()); storage.delete(sysOss.getUrl()); } return baseMapper.deleteBatchIds(ids) > 0; diff --git a/ruoyi-ui/src/views/system/oss/config.vue b/ruoyi-ui/src/views/system/oss/config.vue index 152727efd..54ad98cb1 100644 --- a/ruoyi-ui/src/views/system/oss/config.vue +++ b/ruoyi-ui/src/views/system/oss/config.vue @@ -2,14 +2,13 @@
- - - + + @@ -122,18 +122,14 @@ - - - + + + + @@ -204,14 +200,6 @@ export default { total: 0, // 对象存储配置表格数据 ossConfigList: [], - // configKeyOptions - configKeyOptions: [], - configKeyDatas: [ - { configKey: "minio", label: "Minio" }, - { configKey: "qiniu", label: "七牛云" }, - { configKey: "aliyun", label: "阿里云" }, - { configKey: "qcloud", label: "腾讯云" }, - ], // 弹出层标题 title: "", // 是否显示弹出层 @@ -276,7 +264,6 @@ export default { }, created() { this.getList(); - this.configKeyOptions = this.configKeyDatas; }, methods: { /** 查询对象存储配置列表 */ @@ -303,6 +290,7 @@ export default { bucketName: undefined, prefix: undefined, endpoint: undefined, + domain: undefined, isHttps: "N", region: undefined, status: "1", diff --git a/sql/ry-cloud.sql b/sql/ry-cloud.sql index 415d7dee6..b5dbfcaf8 100644 --- a/sql/ry-cloud.sql +++ b/sql/ry-cloud.sql @@ -612,6 +612,7 @@ create table sys_oss_config ( bucket_name varchar(255) default '' comment '桶名称', prefix varchar(255) default '' comment '前缀', endpoint varchar(255) default '' comment '访问站点', + domain varchar(255) default '' comment '自定义域名', is_https char(1) default 'N' comment '是否https(Y=是,N=否)', region varchar(255) default '' comment '域', status char(1) default '1' comment '状态(0=正常,1=停用)', @@ -624,10 +625,11 @@ create table sys_oss_config ( primary key (oss_config_id) ) engine=innodb comment='对象存储配置表'; -insert into sys_oss_config values (1, 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', 'http://localhost:9000', 'N', '', '0', '', 'admin', sysdate(), 'admin', sysdate(), NULL); -insert into sys_oss_config values (2, 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'http://XXX.XXXX.com', 'N', 'z0', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); -insert into sys_oss_config values (3, 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'http://oss-cn-beijing.aliyuncs.com', 'N', '', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); -insert into sys_oss_config values (4, 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'http://cos.ap-beijing.myqcloud.com', 'N', 'ap-beijing', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); +insert into sys_oss_config values (1, 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', 'localhost:9000', '','N', '', '0', '', 'admin', sysdate(), 'admin', sysdate(), NULL); +insert into sys_oss_config values (2, 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '','N', '', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); +insert into sys_oss_config values (3, 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '','N', '', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); +insert into sys_oss_config values (4, 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); +insert into sys_oss_config values (5, 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', 'localhost:9000', '','N', '', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL); -- ---------------------------- -- 18、代码生成业务表