Эх сурвалжийг харах

更新一些优化点,支持HEIC和获取文章增加缓存

fangzhen 1 долоо хоног өмнө
parent
commit
fcbcdde76b

+ 10 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -150,26 +150,32 @@ public class CommonController {
             // 上传文件路径
             String fileName = OssUtils.uploadMultipartFile(file);
             System.out.println(fileName);
-
+            String fileLastType = "";
             if ("image".equalsIgnoreCase(fileType)) {
                 String fileName_copy = fileName;
                 //对文件进行统一转换
                 if (fileName_copy.contains(".png") || fileName_copy.contains(".PNG")) {
                     fileName_copy += "?x-oss-process=image/format,png";
+                    fileLastType = ".png";
                 } else if (fileName_copy.contains(".jpg") || fileName_copy.contains(".JPG")) {
                     fileName_copy += "?x-oss-process=image/format,jpg";
+                    fileLastType = ".jpg";
                 } else if (fileName_copy.contains(".gif") || fileName_copy.contains(".GIF")) {
                     fileName_copy += "?x-oss-process=image/format,gif";
+                    fileLastType = ".gif";
                 } else if (fileName_copy.contains(".tiff")) {
                     fileName_copy += "?x-oss-process=image/format,tiff";
-                } else if (fileName_copy.contains(".heic")) {
+                    fileLastType = ".tiff";
+                } else if (fileName_copy.contains(".heic") || fileName_copy.contains(".HEIC")) {
                     fileName_copy += "?x-oss-process=image/format,png";
-                } else if (fileName_copy.contains(".avif")) {
+                    fileLastType = ".png";
+                } else if (fileName_copy.contains(".avif") || fileName_copy.contains(".AVIF")) {
                     fileName_copy += "?x-oss-process=image/format,png";
+                    fileLastType = ".png";
                 }
 
                 //下载转化后的图片
-                String tempSourceFile = System.getProperty("java.io.tmpdir") + File.separator + "source_" + FileUtils.getName(fileName);
+                String tempSourceFile = System.getProperty("java.io.tmpdir") + File.separator + "source_" + FileUtils.getName(fileName).replaceAll("\\.(.*)", "") + fileLastType;
                 byte[] image = ImageUtils.getImage(fileName_copy);
                 ImageUtils.saveImageToLocal(image, tempSourceFile);
                 // 上传加水印的文件到OSS

+ 2 - 0
ruoyi-admin/src/main/resources/application.yml

@@ -65,6 +65,8 @@ spring:
     restart:
       # 热部署开关
       enabled: true
+  session:
+    store-type: redis
   # redis 配置
   redis:
     # 地址 47.122.10.161 121.4.140.159

+ 41 - 11
ruoyi-admin/src/main/resources/logback.xml

@@ -17,40 +17,60 @@
 	    <file>${log.path}/sys-info.log</file>
         <!-- 循环政策:基于时间创建日志文件 -->
 		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 日志文件名格式 -->
-			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志文件名格式,添加.gz后缀实现自动压缩 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
 			<!-- 日志最大的历史 60天 -->
 			<maxHistory>60</maxHistory>
+			<!-- 日志文件总大小上限,超过后会删除旧文件,单位可以是KB、MB或GB -->
+			<totalSizeCap>1GB</totalSizeCap>
 		</rollingPolicy>
 		<encoder>
 			<pattern>${log.pattern}</pattern>
 		</encoder>
-		<!-- 移除过滤器,接受所有级别的日志 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
 	</appender>
 
 	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
 	    <file>${log.path}/sys-error.log</file>
         <!-- 循环政策:基于时间创建日志文件 -->
         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 日志文件名格式 -->
-            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志文件名格式,添加.gz后缀实现自动压缩 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
 			<!-- 日志最大的历史 60天 -->
 			<maxHistory>60</maxHistory>
+			<!-- 日志文件总大小上限 -->
+			<totalSizeCap>1GB</totalSizeCap>
         </rollingPolicy>
         <encoder>
             <pattern>${log.pattern}</pattern>
         </encoder>
-        <!-- 移除过滤器,接受所有级别的日志 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<!-- 过滤的级别 -->
+			<level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+			<onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+			<onMismatch>DENY</onMismatch>
+		</filter>
     </appender>
 
 	<!-- 用户访问日志输出  -->
     <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
 		<file>${log.path}/sys-user.log</file>
         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 按天回滚 daily -->
-            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 按天回滚 daily,添加.gz后缀实现自动压缩 -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
             <!-- 日志最大的历史 60天 -->
             <maxHistory>60</maxHistory>
+            <!-- 日志文件总大小上限 -->
+            <totalSizeCap>2GB</totalSizeCap>
         </rollingPolicy>
         <encoder>
             <pattern>${log.pattern}</pattern>
@@ -58,12 +78,22 @@
     </appender>
 
 	<!-- 系统模块日志级别控制  -->
-	<logger name="com.ruoyi" level="debug" />
+	<logger name="com.ruoyi" level="info" />
 	<!-- Spring日志级别控制  -->
-	<logger name="org.springframework" level="info" />
+	<logger name="org.springframework" level="warn" />
+	<!-- MyBatis日志级别控制  -->
+	<logger name="org.mybatis" level="warn" />
+	<!-- Druid日志级别控制  -->
+	<logger name="com.alibaba.druid" level="warn" />
+	<!-- Hibernate验证日志级别控制  -->
+	<logger name="org.hibernate.validator" level="warn" />
+	<!-- Tomcat日志级别控制  -->
+	<logger name="org.apache.catalina" level="warn" />
+	<!-- Undertow日志级别控制  -->
+	<logger name="io.undertow" level="warn" />
 
 	<!-- 根日志级别控制 -->
-	<root level="debug">
+	<root level="info">
 		<appender-ref ref="console" />
 		<appender-ref ref="file_info" />
 		<appender-ref ref="file_error" />

+ 8 - 3
ruoyi-common/pom.xml

@@ -52,13 +52,13 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
-  
+
         <!-- JSON工具类 -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
         </dependency>
-        
+
         <!-- 阿里JSON解析器 -->
         <dependency>
             <groupId>com.alibaba.fastjson2</groupId>
@@ -101,6 +101,11 @@
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.session</groupId>
+            <artifactId>spring-session-data-redis</artifactId>
+        </dependency>
+
         <!-- pool 对象池 -->
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -178,4 +183,4 @@
         </dependency>
     </dependencies>
 
-</project>
+</project>

+ 100 - 6
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/CommunityArticleController.java

@@ -37,6 +37,7 @@ import org.springframework.web.bind.annotation.*;
 import java.io.File;
 import java.text.ParseException;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -124,7 +125,7 @@ public class CommunityArticleController extends BaseController {
     private CommunityReportController communityReportController;
 
     private static final String CACHE_PREFIX = "article:list:"; // 缓存前缀
-    private static final long CACHE_EXPIRE_TIME = 30; // 缓存过期时间(分钟)
+    private static final Integer CACHE_EXPIRE_TIME = 30; // 缓存过期时间(分钟)
     @Autowired
     private CommunityUserLikeMapper communityUserLikeMapper;
     @Autowired
@@ -153,9 +154,58 @@ public class CommunityArticleController extends BaseController {
                                    int pageNum,
                                    int pageSize,
                                    int searchType) {
-        // 将参数拼接为唯一键(例如:article:list:userId=1:page=1:searchType=1)
-        return String.format("%suserId=%d:page=%d:size=%d:searchType=%d",
-                CACHE_PREFIX, userId, pageNum, pageSize, searchType);
+        StringBuilder keyBuilder = new StringBuilder(CACHE_PREFIX);
+
+        // 添加用户ID
+        keyBuilder.append("userId=").append(userId != null ? userId : 0).append(":");
+
+        // 添加文章查询条件(如果有)
+        if (article != null) {
+            if (article.getClassIds() != null && !article.getClassIds().isEmpty()) {
+                // 直接使用逗号连接数字,避免使用String.valueOf()可能产生的"[1]"格式
+                StringBuilder classIdsBuilder = new StringBuilder();
+                boolean first = true;
+                for (Long classId : article.getClassIds()) {
+                    if (!first) {
+                        classIdsBuilder.append(",");
+                    }
+                    classIdsBuilder.append(classId);
+                    first = false;
+                }
+                keyBuilder.append("classIds=").append(classIdsBuilder.toString()).append(":");
+            }
+            if (article.getCircleId() != null) {
+                keyBuilder.append("circleId=").append(article.getCircleId()).append(":");
+            }
+            if (article.getTitle() != null) {
+                keyBuilder.append("title=").append(article.getTitle()).append(":");
+            }
+            // 可以根据需要添加更多条件
+        }
+
+        // 添加分页和搜索类型信息
+        keyBuilder.append("page=").append(pageNum).append(":")
+                 .append("size=").append(pageSize).append(":")
+                 .append("searchType=").append(searchType);
+
+        return keyBuilder.toString();
+    }
+
+    /**
+     * 清除文章列表相关的所有缓存
+     */
+    private void clearArticleListCache() {
+        try {
+            // 获取所有以CACHE_PREFIX开头的缓存键
+            Collection<String> keys = redisCache.keys(CACHE_PREFIX + "*");
+            if (keys != null && !keys.isEmpty()) {
+                // 删除所有匹配的缓存
+                redisCache.deleteObject(keys);
+                log.info("已清除{}个文章列表缓存", keys.size());
+            }
+        } catch (Exception e) {
+            log.error("清除文章列表缓存失败", e);
+        }
     }
 
     /**
@@ -172,14 +222,48 @@ public class CommunityArticleController extends BaseController {
         if (userId == null) {
             userId = SecurityUtils.getUserId();
         }
+
+        // 生成缓存键
+        String cacheKey = generateCacheKey(userId, communityArticle, pageNum, pageSize, searchType);
+
         try {
+            // 尝试从缓存中获取数据
+            TableDataInfo cachedData = null;
+            try {
+                cachedData = redisCache.getCacheObject(cacheKey);
+                if (cachedData != null) {
+                    log.info("从缓存中获取文章列表数据, key: {}", cacheKey);
+                    return cachedData;
+                }
+            } catch (Exception e) {
+                // 如果从缓存获取数据时出错,记录错误并继续从数据库获取
+                log.error("从缓存获取数据失败: {}", e.getMessage(), e);
+                // 清除可能损坏的缓存
+                try {
+                    redisCache.deleteObject(cacheKey);
+                    log.info("已清除可能损坏的缓存: {}", cacheKey);
+                } catch (Exception ex) {
+                    log.error("清除缓存失败: {}", ex.getMessage());
+                }
+            }
+
+            // 缓存中没有数据或获取缓存失败,从数据库查询
+            log.info("从数据库中获取文章列表数据");
             rspData = new TableDataInfo();
             List<CommunityArticleVo> list = communityArticleService.selectCommunityArticleList(userId, rspData, communityArticle, pageNum, pageSize, searchType);
             rspData.setCode(HttpStatus.SUCCESS);
             rspData.setMsg("查询成功");
             rspData.setRows(list);
+
+            // 将查询结果存入缓存
+            try {
+                redisCache.setCacheObject(cacheKey, rspData, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
+                log.info("文章列表数据已缓存, key: {}, 过期时间: {}分钟", cacheKey, CACHE_EXPIRE_TIME);
+            } catch (Exception e) {
+                log.error("缓存数据失败: {}", e.getMessage(), e);
+            }
         } catch (Exception e) {
-            log.info(e.getMessage());
+            log.error("获取文章列表失败: {}", e.getMessage(), e);
             throw new ProjectException();
         }
         return rspData;
@@ -283,6 +367,10 @@ public class CommunityArticleController extends BaseController {
             }
 
             communityArticleService.insertCommunityArticle(communityArticle);
+
+            // 清除文章列表缓存,确保新发布的文章能够立即显示
+            clearArticleListCache();
+            log.info("文章发布成功,已清除文章列表缓存");
         } catch (Exception e) {
             log.info(e.getMessage());
             throw new ProjectException();
@@ -319,12 +407,15 @@ public class CommunityArticleController extends BaseController {
 
             communityArticleService.editCommunityArticle(communityArticle);
 
+            // 清除文章列表缓存,确保编辑后的文章能够立即显示
+            clearArticleListCache();
+            log.info("文章编辑成功,已清除文章列表缓存");
         } catch (Exception e) {
             // e.printStackTrace();
             log.info(e.getMessage());
             throw new ProjectException();
         }
-        return AjaxResult.success("文章发布成功!");
+        return AjaxResult.success("文章编辑成功!");
     }
 
     /**
@@ -354,6 +445,9 @@ public class CommunityArticleController extends BaseController {
                     .set("update_by", SecurityUtils.getUserId())
                     .eq("article_id", id));
             if (result1 && result2 >= 0) {
+                // 清除文章列表缓存,确保删除的文章不再显示
+                clearArticleListCache();
+                log.info("文章删除成功,已清除文章列表缓存");
                 return success("删除成功!");
             }
         } catch (Exception e) {