peng
2025-10-17 a60e866f9d30de8ed50d3cd01c3979dfccb6d94b
Merge branch 'dev' into user_action
3个文件已修改
2个文件已添加
179 ■■■■■ 已修改文件
config/application.yml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
consumer/src/main/resources/application.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/cos/CDNConfigProperty.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/utils/TencentCdnUtil.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/application.yml
@@ -29,9 +29,10 @@
    type: redis
  # Redis
  redis:
    host: 42.193.1.25
    host: 127.0.0.1
#    host: 42.193.1.25
    port: 6379
    password: ycl2018
#    password: ycl2018
    database: 12
    lettuce:
      pool:
@@ -61,11 +62,13 @@
      default-datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://42.193.1.25:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
#        url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
#        url: jdbc:mysql://42.193.1.25:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
        url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
#        url: jdbc:mysql://1.95.67.54:6033/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
        username: root
        password: 321$YcYl@1970!
#        password: 123456
#        password: 321$YcYl@1970!
#        password: 6c701c021355fc70fc156824e81fbead
        password: 123456
        maxActive: 50
        initialSize: 20
        maxWait: 60000
@@ -177,7 +180,7 @@
    #缓存开启
    cache-enabled: true
    #日志
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      #逻辑删除配置字段
@@ -222,10 +225,10 @@
    faultTolerant: 3
  system:
    isDemoSite: false
  #     脱敏级别:
  #     0:不做脱敏处理
  #     1:管理端用户手机号等信息脱敏
  #     2:商家端信息脱敏(为2时,表示管理端,商家端同时脱敏)
    #     脱敏级别:
    #     0:不做脱敏处理
    #     1:管理端用户手机号等信息脱敏
    #     2:商家端信息脱敏(为2时,表示管理端,商家端同时脱敏)
    sensitiveLevel: 1
  statistics:
@@ -286,6 +289,8 @@
      comment-group: lmk_comment_group
      video-topic: lmk_video_topic  # 视频
      video-group: lmk_video_group
      prize-topic: lmk_prize_topic  # 抽奖
      prize-group: lmk_prize_group
      msg-ext-topic: shop_lili_msg_topic
      msg-ext-group: shop_lili_msg_group
      goods-topic: shop_lili_goods_topic
@@ -328,7 +333,8 @@
  durationSeconds: 1800  # STS临时访问凭证有效期,单位秒,默认1800s,主账号最长2小时,子账号(ARM用户)36小时
  bucket: lmk-1356772813
  region: ap-chengdu
  endpoint: https://lmk-1356772813.cos.ap-chengdu.myqcloud.com  # 访问域名
#  endpoint: https://lmk-1356772813.cos.ap-chengdu.myqcloud.com  # 访问域名
  endpoint: https://media.meiyikuang.com  # cdn访问域名
  urlExpireMinute: 360  # 预签名url有效时间(分钟)
  actions:  # sts的权限
    - cos:GetBucketACL
@@ -354,3 +360,8 @@
    - cos:UploadPartCopy
  resources: # 能操作哪些资源
    - qcs::cos::uid/1356772813:lmk-1356772813/*
cdn:
    secretId: AKIDhIqIbhrwsfJm397vhLp570iEZheQ0OYX
    secretKey: pQnyzmS4aCi9Skz2tWyFLG0Xu64saBcs
    cdnDomain: https://media.meiyikuang.com
consumer/src/main/resources/application.yml
@@ -67,9 +67,9 @@
      default-datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
        url: jdbc:mysql://1.95.67.54:6033/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
        password: 6c701c021355fc70fc156824e81fbead
        maxActive: 20
        initialSize: 5
        maxWait: 60000
framework/src/main/java/cn/lili/cos/CDNConfigProperty.java
New file
@@ -0,0 +1,51 @@
package cn.lili.cos;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
 * 读取配置文件关于cos的配置
 *
 * @author:xp
 * @date:2025/5/16 16:23
 */
@Configuration
@ConfigurationProperties(prefix = "cdn")
public class CDNConfigProperty {
    /**
     * 腾讯ARM用户的secretId
     */
    private String secretId;
    /**
     * 腾讯ARM用户的secretKey
     */
    private String secretKey;
    private String cdnDomain;
    public String getSecretId() {
        return secretId;
    }
    public void setSecretId(String secretId) {
        this.secretId = secretId;
    }
    public String getSecretKey() {
        return secretKey;
    }
    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }
    public String getCdnDomain() {
        return cdnDomain;
    }
    public void setCdnDomain(String cdnDomain) {
        this.cdnDomain = cdnDomain;
    }
}
framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java
@@ -26,6 +26,7 @@
import cn.lili.rocketmq.tags.CommentTagsEnum;
import cn.lili.rocketmq.tags.VideoTagsEnum;
import cn.lili.utils.COSUtil;
import cn.lili.utils.TencentCdnUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.lili.modules.lmk.mapper.VideoMapper;
@@ -92,6 +93,7 @@
    private final RocketMQTemplate rocketMQTemplate;
    private final ThumbsUpRecordService thumbsUpRecordService;
    private final ElasticsearchOperations restTemplate;
    private final TencentCdnUtil cdnUtil;
    @Qualifier("videoEsServiceImpl")
    private final EsService esService;
@@ -588,6 +590,9 @@
            video.setAuditPassTime(new Date());
            fields.put("status", VideoStatusEnum.PUBLISHED.getValue());
            // 调cdn预热
            cdnUtil.pushUrlsCache(new String[]{video.getCoverUrl(), video.getVideoFileKey()});
        } else {
            video.setStatus(VideoStatusEnum.REJECT.getValue());
            fields.put("status", VideoStatusEnum.REJECT.getValue());
@@ -600,6 +605,7 @@
        dto.setFields(fields);
        String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_UPDATE_SOME_FIELD.name();
        rocketMQTemplate.asyncSend(destination, JSON.toJSONString(dto), RocketmqSendCallbackBuilder.commonCallback());
        return Result.ok();
    }
@@ -738,7 +744,7 @@
                v.setCollectNum(this.getCollectNum(v.getId(), v.getCollectNum()));
                v.setThumbsUpNum(this.getThumbsUpNum(v.getId(), v.getThumbsUpNum()));
                String authorAvatar = v.getAuthorAvatar();
                if (StringUtils.isNotBlank(authorAvatar)&&!authorAvatar.contains("http")) {
                if (StringUtils.isNotBlank(authorAvatar) && !authorAvatar.contains("http")) {
                    v.setAuthorAvatar(cosUtil.getPreviewUrl(v.getAuthorAvatar()));
                }
                if (VideoContentTypeEnum.VIDEO.getValue().equals(v.getVideoContentType())) {
@@ -860,7 +866,6 @@
    }
    /**
     *
     * @param page
     * @param videoId videoId推荐的视频id
     */
@@ -1541,7 +1546,7 @@
                    v.setAuthorAvatar(cosUtil.getPreviewUrl(v.getAuthorAvatar()));
                    if (VideoContentTypeEnum.VIDEO.getValue().equals(v.getVideoContentType())) {
                        v.setVideoUrl(cosUtil.getPreviewUrl(v.getVideoFileKey()));
                        if(StringUtils.isNotBlank(v.getCoverFileKey())){
                        if (StringUtils.isNotBlank(v.getCoverFileKey())) {
                            v.setCoverUrl(cosUtil.getPreviewUrl(v.getCoverFileKey()));
                        }
framework/src/main/java/cn/lili/utils/TencentCdnUtil.java
New file
@@ -0,0 +1,78 @@
package cn.lili.utils;
import cn.lili.cos.CDNConfigProperty;
import com.tencentcloudapi.cdn.v20180606.CdnClient;
import com.tencentcloudapi.cdn.v20180606.models.DescribePushTasksRequest;
import com.tencentcloudapi.cdn.v20180606.models.DescribePushTasksResponse;
import com.tencentcloudapi.cdn.v20180606.models.PushUrlsCacheRequest;
import com.tencentcloudapi.cdn.v20180606.models.PushUrlsCacheResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Arrays;
@Slf4j
@Service
@RequiredArgsConstructor
public class TencentCdnUtil {
    private final CDNConfigProperty cdnConfigProperty;
    public void pushUrlsCache(String[] urls) {
        try {
            // 预处理URLs,添加CDN域名
            String[] processedUrls = processUrlsWithCdnDomain(urls);
            log.info("cdn链接:{}", Arrays.toString(processedUrls));
            // 为了保护密钥安全,建议将密钥设置在环境变量中或者配置文件中,请参考本文凭证管理章节。
            // 硬编码密钥到代码中有可能随代码泄露而暴露,有安全隐患,并不推荐。
            Credential cred = new Credential(cdnConfigProperty.getSecretId(), cdnConfigProperty.getSecretKey());
            CdnClient client = new CdnClient(cred, "ap-guangzhou");
            PushUrlsCacheRequest req = new PushUrlsCacheRequest();
            req.setUrls(processedUrls);
            PushUrlsCacheResponse resp = client.PushUrlsCache(req);
            log.info("cdn预热返回:{}", client.gson.toJson(resp));
        } catch (TencentCloudSDKException e) {
            log.warn("cdn预热失败:{}", e.toString());
        }
    }
    /**
     * 处理URL列表,在每个URL前添加CDN域名
     *
     * @param urls 原始URL列表
     * @return 添加了CDN域名的完整URL列表
     */
    public String[] processUrlsWithCdnDomain(String[] urls) {
        if (urls == null || urls.length == 0) {
            return urls;
        }
        String cdnDomain = cdnConfigProperty.getCdnDomain();
        if (cdnDomain == null || cdnDomain.isEmpty()) {
            return urls;
        }
        String[] processedUrls = new String[urls.length];
        for (int i = 0; i < urls.length; i++) {
            // 如果URL已经包含协议,则直接拼接
            if (urls[i].startsWith("http://") || urls[i].startsWith("https://")) {
                processedUrls[i] = urls[i];
            } else {
                // 确保cdnDomain末尾没有斜杠,urls开头没有斜杠
                String domain = cdnDomain.endsWith("/") ? cdnDomain.substring(0, cdnDomain.length() - 1) : cdnDomain;
                String path = urls[i].startsWith("/") ? urls[i].substring(1) : urls[i];
                processedUrls[i] = domain + "/" + path;
            }
        }
        return processedUrls;
    }
}