去除 fastjson2 依赖

This commit is contained in:
2025-12-31 00:50:33 +08:00
parent a731d0c996
commit 24323e246f
20 changed files with 176 additions and 179 deletions

14
pom.xml
View File

@@ -178,20 +178,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.23</version>
</dependency>
<!--
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.14.1</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15to18 --> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15to18 -->
<!-- sha224 哈希套件 --> <!-- sha224 哈希套件 -->

View File

@@ -186,7 +186,7 @@ public class Rk {
* @return * @return
*/ */
public static String prepareDogHash(String email) { public static String prepareDogHash(String email) {
if (email == null) email = "";
email = email.toLowerCase(Locale.ENGLISH); email = email.toLowerCase(Locale.ENGLISH);
RBucket<String> gravatarHashBucket = redisson.getBucket(getGravatarKey(EMAIL_HASH_PREFIX + email)); RBucket<String> gravatarHashBucket = redisson.getBucket(getGravatarKey(EMAIL_HASH_PREFIX + email));

View File

@@ -3,6 +3,7 @@ package me.qwq.doghouse.config;
import java.util.Set; import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -21,11 +22,13 @@ import me.qwq.doghouse.service.ConfigService;
/** /**
* Doghouse 配置项 * Doghouse 配置项
* <p>
* 指定 RedisCacheManager 序列化器后需要重新指定启用 CacheProperties 的自动装配
* @author Doghole * @author Doghole
* *
*/ */
@Configuration @Configuration
@EnableConfigurationProperties(DoghouseProperties.class) @EnableConfigurationProperties({DoghouseProperties.class, CacheProperties.class})
@Import(ConfigAutoRegistrar.class) @Import(ConfigAutoRegistrar.class)
public class DoghouseConfig implements WebMvcConfigurer { public class DoghouseConfig implements WebMvcConfigurer {
@@ -90,4 +93,5 @@ public class DoghouseConfig implements WebMvcConfigurer {
resolver.setCheckExistence(true); // 文件不存在就跳过,交给下一个 resolver resolver.setCheckExistence(true); // 文件不存在就跳过,交给下一个 resolver
return resolver; return resolver;
} }
} }

View File

@@ -1,6 +1,5 @@
package me.qwq.doghouse.controller.admin; package me.qwq.doghouse.controller.admin;
import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
@@ -18,6 +17,8 @@ import me.qwq.doghouse.pojo.dto.LayPageReq;
import me.qwq.doghouse.pojo.dto.LayPageResp; import me.qwq.doghouse.pojo.dto.LayPageResp;
import me.qwq.doghouse.pojo.dto.R; import me.qwq.doghouse.pojo.dto.R;
import me.qwq.doghouse.service.AssetService; import me.qwq.doghouse.service.AssetService;
import me.qwq.doghouse.util.DateUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;

View File

@@ -1,10 +1,11 @@
package me.qwq.doghouse.controller.admin.post; package me.qwq.doghouse.controller.admin.post;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@@ -56,12 +57,18 @@ public abstract class AbstractAdminPostController<C extends IPostTypeConfig<C>,
@Autowired @Autowired
AssetService assetService; AssetService assetService;
@Autowired @Autowired
MetaService metaService; MetaService metaService;
@Autowired @Autowired
RelationshipService relationshipService; RelationshipService relationshipService;
@Autowired @Autowired
PostTypeComponent postTypeComponent; PostTypeComponent postTypeComponent;
@Autowired
ObjectMapper objectMapper;
C postTypeConfig; C postTypeConfig;
@@ -136,9 +143,10 @@ public abstract class AbstractAdminPostController<C extends IPostTypeConfig<C>,
/** /**
* 编辑 * 编辑
* @throws JsonProcessingException
*/ */
@GetMapping("/edit") @GetMapping("/edit")
public String edit(@RequestParam(required = false) Long postId) { public String edit(@RequestParam(required = false) Long postId) throws JsonProcessingException {
PostTypeEnum postType = getPostTypeConfig().getPostType(); PostTypeEnum postType = getPostTypeConfig().getPostType();
@@ -148,7 +156,7 @@ public abstract class AbstractAdminPostController<C extends IPostTypeConfig<C>,
request.setAttribute("title", "编辑 - " + post.getPostTitle()); request.setAttribute("title", "编辑 - " + post.getPostTitle());
List<Asset> assets = assetService.list( List<Asset> assets = assetService.list(
new LambdaQueryWrapper<Asset>().eq(Asset::getFromPostId, postId)); new LambdaQueryWrapper<Asset>().eq(Asset::getFromPostId, postId));
request.setAttribute("assets", StringEscapeUtils.escapeEcmaScript(JSONObject.toJSONString(assets))); request.setAttribute("assets", StringEscapeUtils.escapeEcmaScript(objectMapper.writeValueAsString(assets)));
} }
else { else {
request.setAttribute("title", "新增" + postType.getNote()); request.setAttribute("title", "新增" + postType.getNote());

View File

@@ -20,14 +20,13 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.qwq.dogface.Dogface; import me.qwq.dogface.Dogface;
import me.qwq.doghouse.component.Rk; import me.qwq.doghouse.component.Rk;
import me.qwq.doghouse.exception.PageNotFoundException; import me.qwq.doghouse.exception.PageNotFoundException;
import me.qwq.doghouse.pojo.dto.DailyPostCommentStats;
import me.qwq.doghouse.pojo.dto.R; import me.qwq.doghouse.pojo.dto.R;
import me.qwq.doghouse.service.CommentService; import me.qwq.doghouse.service.CommentService;
import me.qwq.doghouse.service.StatisticsService; import me.qwq.doghouse.service.StatisticsService;
@@ -132,7 +131,7 @@ public class ApiControllerV1 {
} }
@GetMapping(path="/getPassDaysStatistics", produces="application/json") @GetMapping(path="/getPassDaysStatistics", produces="application/json")
public JSONObject getPassDaysStatistics(Integer passDays) { public DailyPostCommentStats getPassDaysStatistics(Integer passDays) {
return statisticsService.getPostAndCommentCountsWithDates(passDays, null); return statisticsService.getPostAndCommentCountsWithDates(passDays, null);
} }
@@ -163,11 +162,11 @@ public class ApiControllerV1 {
svgRoot.setAttribute("viewBox", String.format("0 0 %d %d", w, h)); svgRoot.setAttribute("viewBox", String.format("0 0 %d %d", w, h));
// 获取 n 日以来的文章和评论统计 // 获取 n 日以来的文章和评论统计
JSONObject jo = statisticsService.getPostAndCommentCountsWithDates(total, null); DailyPostCommentStats s = statisticsService.getPostAndCommentCountsWithDates(total, null);
List<String> dates = jo.getList("dates", String.class); List<String> dates = s.dates();
List<Integer> postCounts = jo.getList("postCounts", Integer.class); List<Integer> postCounts = s.postCounts();
List<Integer> commentCounts = jo.getList("commentCounts", Integer.class); List<Integer> commentCounts = s.commentCounts();
for (int col = 0; col < cols; col++) { for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {

View File

@@ -1,5 +1,8 @@
package me.qwq.doghouse.controller.api.v2; package me.qwq.doghouse.controller.api.v2;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@@ -8,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.databind.JsonNode;
import me.qwq.dogface.Dogface; import me.qwq.dogface.Dogface;
import me.qwq.doghouse.controller.common.BaseController; import me.qwq.doghouse.controller.common.BaseController;
@@ -38,8 +41,8 @@ public class CommentApiControllerV2 extends BaseController {
Dogface dogface; Dogface dogface;
@PostMapping("/preview") @PostMapping("/preview")
public R<?> preview(@RequestBody JSONObject jo) { public R<?> preview(@RequestBody JsonNode jo) {
String markDown = MarkDownUtils.commentToHtml(jo.getString("content")); String markDown = MarkDownUtils.commentToHtml(jo.get("content").asText());
return R.ok(markDown); return R.ok(markDown);
} }
@@ -54,16 +57,16 @@ public class CommentApiControllerV2 extends BaseController {
throw RException.badRequest("非法请求"); throw RException.badRequest("非法请求");
} }
JSONObject jo = new JSONObject(); Map<String, Object> dto = new HashMap<>();
jo.put("author", commentForEdit.getAuthor()); dto.put("author", commentForEdit.getAuthor());
jo.put("isMarkdown", commentForEdit.isMarkdown()); dto.put("isMarkdown", commentForEdit.isMarkdown());
jo.put("email", commentForEdit.getEmail()); dto.put("email", commentForEdit.getEmail());
jo.put("url", commentForEdit.getUrl()); dto.put("url", commentForEdit.getUrl());
jo.put("content", commentForEdit.getContent()); dto.put("content", commentForEdit.getContent());
jo.put("subscribeReply", commentForEdit.isSubscribeReply()); dto.put("subscribeReply", commentForEdit.isSubscribeReply());
jo.put("commentStatu", commentForEdit.getCommentStatus()); dto.put("commentStatu", commentForEdit.getCommentStatus());
jo.put("id", commentForEdit.getId()); dto.put("id", commentForEdit.getId());
return R.ok(jo); return R.ok(dto);
} }
} }

View File

@@ -1,7 +1,6 @@
package me.qwq.doghouse.controller.blog; package me.qwq.doghouse.controller.blog;
import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -18,6 +17,7 @@ import me.qwq.doghouse.interfaces.IPostTypeConfig;
import me.qwq.doghouse.pojo.dto.PageQuery; import me.qwq.doghouse.pojo.dto.PageQuery;
import me.qwq.doghouse.service.*; import me.qwq.doghouse.service.*;
import me.qwq.doghouse.service.post.PostService; import me.qwq.doghouse.service.post.PostService;
import me.qwq.doghouse.util.DateUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document; import org.jdom2.Document;

View File

@@ -1,7 +1,9 @@
package me.qwq.doghouse.controller.blog.post; package me.qwq.doghouse.controller.blog.post;
import com.alibaba.fastjson2.JSON; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.entity.config.WikiConfig; import me.qwq.doghouse.entity.config.WikiConfig;
import me.qwq.doghouse.entity.Post; import me.qwq.doghouse.entity.Post;
@@ -9,6 +11,7 @@ import me.qwq.doghouse.pojo.bo.PostPassJar;
import me.qwq.doghouse.service.post.WikiService; import me.qwq.doghouse.service.post.WikiService;
import me.qwq.doghouse.util.EscapeUnescapeUtils; import me.qwq.doghouse.util.EscapeUnescapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@@ -28,6 +31,9 @@ import java.util.List;
@RequestMapping("/wiki") @RequestMapping("/wiki")
public class WikiPaginationController extends AbstractPaginationController<WikiConfig, WikiService> { public class WikiPaginationController extends AbstractPaginationController<WikiConfig, WikiService> {
@Autowired
ObjectMapper objectMapper;
/** /**
* 首页 * 首页
*/ */
@@ -44,9 +50,10 @@ public class WikiPaginationController extends AbstractPaginationController<WikiC
* Wiki 树形菜单点击 * Wiki 树形菜单点击
* @param postId * @param postId
* @return * @return
* @throws JsonProcessingException
*/ */
@GetMapping({"/list", "/list/", "/list/{postId}"}) @GetMapping({"/list", "/list/", "/list/{postId}"})
public String listFrontWikisOnly(@PathVariable(name="postId", required=false) Long postId) { public String listFrontWikisOnly(@PathVariable(name="postId", required=false) Long postId) throws JsonProcessingException {
request.setAttribute("wikis", listFrontWikis(postId)); request.setAttribute("wikis", listFrontWikis(postId));
return postTypeComponent.getTemplatePath(getPostType(), "side-only"); return postTypeComponent.getTemplatePath(getPostType(), "side-only");
} }
@@ -56,10 +63,11 @@ public class WikiPaginationController extends AbstractPaginationController<WikiC
* 放在控制器这里只是方便前端模板调用,并且能获得 service 的缓存能力 * 放在控制器这里只是方便前端模板调用,并且能获得 service 的缓存能力
* @param postId * @param postId
* @return * @return
* @throws JsonProcessingException
*/ */
public List<Post> listFrontWikis(Long postId) { public List<Post> listFrontWikis(Long postId) throws JsonProcessingException {
List<Long> unfolded = WikiService.getUnfoldedWikis(request); List<Long> unfolded = WikiService.getUnfoldedWikis(request);
String unfoldedStr = unfolded == null ? "[]" : JSON.toJSONString(unfolded); String unfoldedStr = unfolded == null ? "[]" : objectMapper.writeValueAsString(unfolded);
unfoldedStr = EscapeUnescapeUtils.escape(unfoldedStr); unfoldedStr = EscapeUnescapeUtils.escape(unfoldedStr);
Cookie unfoldedCookie = new Cookie(WikiService.UNFOLDED_WIKIS, unfoldedStr); Cookie unfoldedCookie = new Cookie(WikiService.UNFOLDED_WIKIS, unfoldedStr);
unfoldedCookie.setPath("/"); unfoldedCookie.setPath("/");

View File

@@ -27,7 +27,6 @@ import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import me.qwq.doghouse.enums.PostStatusEnum; import me.qwq.doghouse.enums.PostStatusEnum;
import me.qwq.doghouse.enums.PostTypeEnum; import me.qwq.doghouse.enums.PostTypeEnum;
import me.qwq.doghouse.interfaces.IAvatarUrl;
import me.qwq.doghouse.interfaces.IFriendlyName; import me.qwq.doghouse.interfaces.IFriendlyName;
import me.qwq.doghouse.interfaces.IPostPassMess; import me.qwq.doghouse.interfaces.IPostPassMess;
import me.qwq.doghouse.validator.FriendlyNameValid; import me.qwq.doghouse.validator.FriendlyNameValid;
@@ -41,7 +40,7 @@ import me.qwq.doghouse.validator.FriendlyNameValid;
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@Accessors(chain = true) @Accessors(chain = true)
@FriendlyNameValid @FriendlyNameValid
public class Post extends Model<Post> implements Serializable, IPostPassMess<Post>, ITreeView<Post>, IAvatarUrl, IFriendlyName { public class Post extends Model<Post> implements Serializable, IPostPassMess<Post>, ITreeView<Post>, IFriendlyName {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -1,39 +0,0 @@
package me.qwq.doghouse.entity.config;
import java.io.Serializable;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import jodd.io.FileUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.annotation.ConfigInfo;
import me.qwq.doghouse.interfaces.IConfig;
@SuppressWarnings("serial")
@Data
@Accessors(chain=true)
@ConfigInfo(field="markdown", name="Markdown 设置", initDefault=true)
@Slf4j
public class MarkdownConfig implements Serializable, IConfig<MarkdownConfig> {
private static final String DEFAULT_MERMAID_CONFIG = "";
private String mermaidConfig = DEFAULT_MERMAID_CONFIG;
public MarkdownConfig afterSaving() {
if (StringUtils.isNotBlank(mermaidConfig)) {
try {
JSONObject jo = JSONObject.parse(mermaidConfig);
FileUtil.writeString("./conf/mermaid/config.json", jo.toJSONString());
} catch (Exception e) {
log.warn("Save mermaid self-defined css failed", e);
}
}
return this;
}
}

View File

@@ -0,0 +1,10 @@
package me.qwq.doghouse.pojo.dto;
import java.io.Serializable;
import java.util.List;
public record DailyPostCommentStats(
List<String> dates,
List<Integer> postCounts,
List<Integer> commentCounts
) implements Serializable {}

View File

@@ -7,7 +7,8 @@ import me.qwq.doghouse.entity.RawConfig;
import me.qwq.doghouse.interfaces.IConfig; import me.qwq.doghouse.interfaces.IConfig;
import me.qwq.doghouse.util.SpringContextHolder; import me.qwq.doghouse.util.SpringContextHolder;
import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap; import com.google.common.collect.HashBiMap;
@@ -40,6 +41,9 @@ public class ConfigService extends BaseServiceImpl<ConfigMapper, RawConfig> {
@Autowired @Autowired
Reflections reflections; Reflections reflections;
@Autowired
private ObjectMapper objectMapper;
/** /**
* 从 * 从
* <b><code> field </code></b> * <b><code> field </code></b>
@@ -198,8 +202,15 @@ public class ConfigService extends BaseServiceImpl<ConfigMapper, RawConfig> {
} }
return null; return null;
} }
T iConfig = T iConfig;
JSONObject.parseObject(rawConfig.getConfigValue(), clazz); try {
iConfig = objectMapper.readValue(rawConfig.getConfigValue(), clazz);
}
catch (JsonProcessingException e) {
throw new IllegalStateException(
"Failed to deserialize config: " + info.field(), e
);
}
setCache(iConfig); setCache(iConfig);
return iConfig; return iConfig;
} }
@@ -222,7 +233,15 @@ public class ConfigService extends BaseServiceImpl<ConfigMapper, RawConfig> {
else { else {
rawConfig.setUpdateTime(LocalDateTime.now()); rawConfig.setUpdateTime(LocalDateTime.now());
} }
rawConfig.setConfigValue(JSONObject.toJSONString(iConfig)); try {
rawConfig.setConfigValue(
objectMapper.writeValueAsString(iConfig)
);
} catch (JsonProcessingException e) {
throw new IllegalStateException(
"Failed to serialize config: " + info.field(), e
);
}
iConfig.beforeSaving(); iConfig.beforeSaving();
if (saveOrUpdate(rawConfig)) { if (saveOrUpdate(rawConfig)) {

View File

@@ -4,15 +4,13 @@ import java.text.DecimalFormat;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.alibaba.fastjson2.JSONObject;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.Getter; import lombok.Getter;
@@ -25,6 +23,7 @@ import me.qwq.doghouse.entity.Post;
import me.qwq.doghouse.enums.CommentStatusEnum; import me.qwq.doghouse.enums.CommentStatusEnum;
import me.qwq.doghouse.enums.PostStatusEnum; import me.qwq.doghouse.enums.PostStatusEnum;
import me.qwq.doghouse.enums.PostTypeEnum; import me.qwq.doghouse.enums.PostTypeEnum;
import me.qwq.doghouse.pojo.dto.DailyPostCommentStats;
import me.qwq.doghouse.service.post.PostService; import me.qwq.doghouse.service.post.PostService;
@Service @Service
@@ -86,15 +85,24 @@ public class StatisticsService {
*/ */
@CacheEvictionTask @CacheEvictionTask
@Cacheable(value=CacheConstants.Statistics.DAILY_POST_AND_COMMENT_COUNTS) @Cacheable(value=CacheConstants.Statistics.DAILY_POST_AND_COMMENT_COUNTS)
public JSONObject getPostAndCommentCountsWithDates(Integer passDays, PostTypeEnum postType) { public DailyPostCommentStats getPostAndCommentCountsWithDates(Integer passDays, PostTypeEnum postType) {
JSONObject jo = new JSONObject(); Map<String, String> map =
Map<String, String> map = mapper.getPostAndCommentCountsWithDates(passDays, postType); mapper.getPostAndCommentCountsWithDates(passDays, postType);
jo.put("dates", map.get("dates").split(","));
jo.put("postCounts", Arrays.asList(map.get("postCounts").split(",")).stream() List<String> dates =
.map(s -> Integer.valueOf(s)).collect(Collectors.toList())); Arrays.asList(map.get("dates").split(","));
jo.put("commentCounts", Arrays.asList(map.get("commentCounts").split(",")).stream()
.map(s -> Integer.valueOf(s)).collect(Collectors.toList())); List<Integer> postCounts =
return jo; Arrays.stream(map.get("postCounts").split(","))
.map(Integer::valueOf)
.toList();
List<Integer> commentCounts =
Arrays.stream(map.get("commentCounts").split(","))
.map(Integer::valueOf)
.toList();
return new DailyPostCommentStats(dates, postCounts, commentCounts);
} }
public PostStatistic getPostStatistic(Post post) { public PostStatistic getPostStatistic(Post post) {

View File

@@ -25,7 +25,8 @@ import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.function.ThrowingSupplier; import org.springframework.util.function.ThrowingSupplier;
import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.config.DoghouseProperties; import me.qwq.doghouse.config.DoghouseProperties;
@@ -43,6 +44,8 @@ public class ThemeService {
private volatile List<ThemeInfo> cachedThemes = Collections.emptyList(); private volatile List<ThemeInfo> cachedThemes = Collections.emptyList();
private List<ThemeInfo> internalThemes = new ArrayList<>(); private List<ThemeInfo> internalThemes = new ArrayList<>();
@Autowired
private ObjectMapper objectMapper;
@Autowired @Autowired
DoghouseProperties doghouseProperties; DoghouseProperties doghouseProperties;
@@ -294,7 +297,7 @@ public class ThemeService {
*/ */
private ThemeInfo getThemeInfo(Resource config) throws IOException { private ThemeInfo getThemeInfo(Resource config) throws IOException {
String json = config.getContentAsString(StandardCharsets.UTF_8); String json = config.getContentAsString(StandardCharsets.UTF_8);
ThemeInfo themeInfo = JSONObject.parseObject(json, ThemeInfo.class); ThemeInfo themeInfo = objectMapper.readValue(json, ThemeInfo.class);
// uri: .../templates/blog/bleaching/config.json // uri: .../templates/blog/bleaching/config.json
// folderName: bleaching // folderName: bleaching
@@ -331,7 +334,7 @@ public class ThemeService {
*/ */
private ThemeInfo getThemeInfo(Path configPath) throws IOException { private ThemeInfo getThemeInfo(Path configPath) throws IOException {
String json = Files.readString(configPath); String json = Files.readString(configPath);
ThemeInfo themeInfo = JSONObject.parseObject(json, ThemeInfo.class); ThemeInfo themeInfo = objectMapper.readValue(json, ThemeInfo.class);
Path path = configPath.getParent(); Path path = configPath.getParent();
themeInfo.setDirectory(path.toString()); themeInfo.setDirectory(path.toString());

View File

@@ -13,10 +13,11 @@ import me.qwq.doghouse.pojo.dto.LayPageReq;
import me.qwq.doghouse.util.CookieUtils; import me.qwq.doghouse.util.CookieUtils;
import me.qwq.doghouse.util.SessionUtils; import me.qwq.doghouse.util.SessionUtils;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.enums.DefaultFuncEnum; import com.github.yulichang.wrapper.enums.DefaultFuncEnum;
@@ -669,8 +670,10 @@ public class WikiService extends AbstractPostService<WikiService, WikiConfig> {
Cookie cookie = CookieUtils.getCookie(request, UNFOLDED_WIKIS); Cookie cookie = CookieUtils.getCookie(request, UNFOLDED_WIKIS);
if (cookie == null) new ArrayList<>(); if (cookie == null) new ArrayList<>();
try { try {
JSONArray ja = JSONArray.parse(cookie.getValue()); return new ObjectMapper().readValue(
return ja.toJavaList(Long.class); cookie.getValue(),
new TypeReference<List<Long>>() {}
);
} }
catch (Exception e) { catch (Exception e) {
return null; return null;

View File

@@ -0,0 +1,37 @@
package me.qwq.doghouse.util;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public final class DateUtils {
// 缓存 formatter行为接近 fastjson2
private static final Map<String, DateTimeFormatter> FORMATTER_CACHE =
new ConcurrentHashMap<>();
private DateUtils() {
}
/**
* 格式化 LocalDateTime
*
* @param dateTime LocalDateTime
* @param pattern 日期格式,如 yyyy-MM-dd HH:mm:ss
* @return 格式化后的字符串
*/
public static String format(LocalDateTime dateTime, String pattern) {
if (dateTime == null) {
return null;
}
if (pattern == null || pattern.isEmpty()) {
throw new IllegalArgumentException("pattern must not be null or empty");
}
DateTimeFormatter formatter =
FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
return dateTime.format(formatter);
}
}

View File

@@ -1,70 +0,0 @@
package me.qwq.doghouse.util;
import java.io.*;
import java.nio.file.*;
import java.util.Base64;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StreamUtils;
public class ImageBase64Utils {
/**
* 从文件系统路径读取图片并转 base64
*/
public static String fromFileSystem(Path imagePath) throws IOException {
if (imagePath == null || !Files.exists(imagePath)) {
return null;
}
byte[] bytes = Files.readAllBytes(imagePath);
String mimeType = Files.probeContentType(imagePath);
return toDataUrl(bytes, mimeType);
}
/**
* 从 classpath 读取图片并转 base64支持 jar 内)
*/
public static String fromClasspath(String classpathLocation) throws IOException {
ClassPathResource resource = new ClassPathResource(classpathLocation);
if (!resource.exists()) {
return null;
}
byte[] bytes;
try (InputStream is = resource.getInputStream()) {
bytes = StreamUtils.copyToByteArray(is);
}
String mimeType = guessMimeType(classpathLocation);
return toDataUrl(bytes, mimeType);
}
/**
* 生成 data:image/...;base64,...
*/
private static String toDataUrl(byte[] bytes, String mimeType) {
if (bytes == null || bytes.length == 0) {
return null;
}
if (mimeType == null) {
mimeType = "image/png"; // 兜底
}
String base64 = Base64.getEncoder().encodeToString(bytes);
return "data:" + mimeType + ";base64," + base64;
}
/**
* 根据文件名猜测 MIME
*/
private static String guessMimeType(String filename) {
String lower = filename.toLowerCase();
if (lower.endsWith(".png")) return "image/png";
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
if (lower.endsWith(".gif")) return "image/gif";
if (lower.endsWith(".webp")) return "image/webp";
return "image/png";
}
}

View File

@@ -0,0 +1,18 @@
package me.qwq.doghouse.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import me.qwq.doghouse.annotation.StaticAttribute;
@StaticAttribute
public final class JsonUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
public static String toJson(Object o) {
try {
return MAPPER.writeValueAsString(o);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -80,7 +80,7 @@
<ul class="tags-ul"> <ul class="tags-ul">
<th:block th:each="tag, i : ${@metaService.listMetaCount(MetaTypeEnum.TAG, null)}"> <th:block th:each="tag, i : ${@metaService.listMetaCount(MetaTypeEnum.TAG, null)}">
<li <li
th:with="tagJson=${T(com.alibaba.fastjson2.JSONObject).toJSONString(tag)}" th:with="tagJson=${JsonUtils.toJson(tag)}"
th:attr="mid=${tag.mid},tag=${tagJson}"> th:attr="mid=${tag.mid},tag=${tagJson}">
<a <a
th:href="@{${'/admin/v2/post/?tagId=' + tag.mid}}" th:href="@{${'/admin/v2/post/?tagId=' + tag.mid}}"