refactor(utils): 重构工具类并添加新功能
- 重命名ApiResponseUtil为ApiResponseUtils,MarkdownAST保持不变,PaginationUtil为PaginationUtils,SecurityUtil为SecurityUtils- 添加MarkdownUtils类,分离Markdown相关功能 - 新增SearchUtils类,用于搜索相关功能 - 添加TraceIdFilter过滤器,用于追踪ID - 新增NeedLoginAspect切面,用于登录验证- 更新相关类的引用和使用
This commit is contained in:
parent
439e7e1633
commit
ae5b7cbd1a
@ -28,6 +28,8 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
@ -49,8 +51,12 @@ dependencies {
|
||||
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.4'
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
implementation 'com.huaban:jieba-analysis:1.0.2'
|
||||
implementation 'org.aspectj:aspectjweaver:1.9.19'
|
||||
implementation 'org.springframework:spring-aop:6.1.0'
|
||||
implementation 'javax.servlet:javax.servlet-api:4.0.1'
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,10 @@ package com.example.copykamanotes;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = "com.example.copykamanotes")
|
||||
@EnableScheduling
|
||||
public class NotesApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package com.example.copykamanotes.aspect;
|
||||
|
||||
import com.example.copykamanotes.annotation.NeedLogin;
|
||||
import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class NeedLoginAspect {
|
||||
|
||||
@Autowired
|
||||
private RequestScopeData requestScopeData;
|
||||
|
||||
@Around("@annotation(needLogin)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, NeedLogin needLogin) throws Throwable {
|
||||
|
||||
if (!requestScopeData.isLogin()) {
|
||||
return ApiResponseUtils.error("请先登录");
|
||||
}
|
||||
|
||||
if (requestScopeData.getUserId() == null ) {
|
||||
return ApiResponseUtils.error("用户不存在");
|
||||
}
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
@ -23,7 +24,7 @@ public class SecurityConfig {
|
||||
.requestMatchers("/api/**").permitAll() // 允许 /api/** 路径下的所有请求
|
||||
.anyRequest().authenticated() // 其他请求需要认证
|
||||
)
|
||||
.csrf(csrf -> csrf.disable()); // 根据需要禁用 CSRF
|
||||
.csrf(AbstractHttpConfigurer::disable); // 根据需要禁用 CSRF
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
package com.example.copykamanotes.config;
|
||||
|
||||
import com.example.copykamanotes.filter.TraceIdFilter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import com.example.copykamanotes.interceptor.TokenInterceptor;
|
||||
@ -13,6 +18,14 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
@Autowired
|
||||
private TokenInterceptor tokenInterceptor;
|
||||
|
||||
@Value("${upload.path:D:/kamaNotes/upload")
|
||||
private String uploadPath;
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/images/**")
|
||||
.addResourceLocations("file:" + uploadPath + "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加拦截器, 拦截所有请求,除了登录和注册
|
||||
@ -35,4 +48,11 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
.maxAge(3600);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TraceIdFilter> traceIdFilter() {
|
||||
FilterRegistrationBean<TraceIdFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new TraceIdFilter());
|
||||
registrationBean.addUrlPatterns("/*");
|
||||
return registrationBean;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.copykamanotes.filter;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TraceIdFilter implements Filter {
|
||||
private static final String TRACE_ID_KEY = "trace_id";
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
MDC.remove(TRACE_ID_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
Filter.super.init(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Filter.super.destroy();
|
||||
}
|
||||
}
|
||||
@ -16,9 +16,9 @@ import com.example.copykamanotes.service.NoteLikeService;
|
||||
import com.example.copykamanotes.service.NoteService;
|
||||
import com.example.copykamanotes.service.QuestionService;
|
||||
import com.example.copykamanotes.service.UserService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtil;
|
||||
import com.example.copykamanotes.utils.MarkdownUtil;
|
||||
import com.example.copykamanotes.utils.PaginationUtil;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import com.example.copykamanotes.utils.MarkdownUtils;
|
||||
import com.example.copykamanotes.utils.PaginationUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -48,7 +48,7 @@ public class NoteServiceImpl implements NoteService {
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<NoteVO>> getNotes(NoteQueryParams noteQueryParams) {
|
||||
int offset = PaginationUtil.calculateOffset(noteQueryParams.getPage(), noteQueryParams.getPageSize());
|
||||
int offset = PaginationUtils.calculateOffset(noteQueryParams.getPage(), noteQueryParams.getPageSize());
|
||||
|
||||
int total = noteMapper.countNotes(noteQueryParams);
|
||||
|
||||
@ -105,9 +105,9 @@ public class NoteServiceImpl implements NoteService {
|
||||
userActionsVO.setIsCollected(true);
|
||||
}
|
||||
|
||||
if (MarkdownUtil.needCollapsed(note.getContent())) {
|
||||
if (MarkdownUtils.needCollapsed(note.getContent())) {
|
||||
noteVO.setNeedCollapsed(true);
|
||||
noteVO.setDisplayContent(MarkdownUtil.extractIntroduction(note.getContent()));
|
||||
noteVO.setDisplayContent(MarkdownUtils.extractIntroduction(note.getContent()));
|
||||
} else {
|
||||
noteVO.setNeedCollapsed(false);
|
||||
}
|
||||
@ -116,9 +116,9 @@ public class NoteServiceImpl implements NoteService {
|
||||
return noteVO;
|
||||
}).toList();
|
||||
|
||||
return ApiResponseUtil.success("获取笔记列表成功", noteVOs, pagination);
|
||||
return ApiResponseUtils.success("获取笔记列表成功", noteVOs, pagination);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtil.error("获取笔记列表失败");
|
||||
return ApiResponseUtils.error("获取笔记列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.vo.upload.ImageVO;
|
||||
import com.example.copykamanotes.service.FileService;
|
||||
import com.example.copykamanotes.service.UploadService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtil;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -20,6 +20,6 @@ public class UploadServiceImpl implements UploadService {
|
||||
String url = fileService.uploadImage(file);
|
||||
ImageVO imageVO = new ImageVO();
|
||||
imageVO.setUrl(url);
|
||||
return ApiResponseUtil.success("上传成功", imageVO);
|
||||
return ApiResponseUtils.success("上传成功", imageVO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,10 +17,9 @@ import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.service.EmailService;
|
||||
import com.example.copykamanotes.service.FileService;
|
||||
import com.example.copykamanotes.service.UserService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtil;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import com.example.copykamanotes.utils.JwtUtil;
|
||||
import com.example.copykamanotes.utils.PaginationUtil;
|
||||
import com.google.protobuf.Api;
|
||||
import com.example.copykamanotes.utils.PaginationUtils;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -62,14 +61,14 @@ public class UserServiceImpl implements UserService {
|
||||
public ApiResponse<RegisterVO> register(RegisterRequest registerRequest) {
|
||||
User existingUser = userMapper.findByAccount(registerRequest.getAccount());
|
||||
if (existingUser != null) {
|
||||
return ApiResponseUtil.error("账号重复");
|
||||
return ApiResponseUtils.error("账号重复");
|
||||
}
|
||||
|
||||
if (registerRequest.getEmail() != null && !registerRequest.getEmail().isEmpty()) {
|
||||
// 验证邮箱是否重复
|
||||
existingUser = userMapper.findByEmail(registerRequest.getEmail());
|
||||
if (existingUser != null) {
|
||||
return ApiResponseUtil.error("邮箱重复");
|
||||
return ApiResponseUtils.error("邮箱重复");
|
||||
}
|
||||
|
||||
// if (registerRequest.getVerifyCode() == null || registerRequest.getVerifyCode().isEmpty()) {
|
||||
@ -95,10 +94,10 @@ public class UserServiceImpl implements UserService {
|
||||
BeanUtils.copyProperties(user, registerVO);
|
||||
|
||||
userMapper.updateLastLoginAt(user.getUserId());
|
||||
return ApiResponseUtil.success("注册成功", registerVO, token);
|
||||
return ApiResponseUtils.success("注册成功", registerVO, token);
|
||||
} catch (Exception e) {
|
||||
log.error("注册失败", e);
|
||||
return ApiResponseUtil.error("注册失败,请稍后再试");
|
||||
return ApiResponseUtils.error("注册失败,请稍后再试");
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,15 +110,15 @@ public class UserServiceImpl implements UserService {
|
||||
} else if (loginRequest.getEmail() != null && !loginRequest.getEmail().isEmpty()) {
|
||||
user = userMapper.findByEmail(loginRequest.getEmail());
|
||||
} else {
|
||||
return ApiResponseUtil.error("账号或邮箱不能为空");
|
||||
return ApiResponseUtils.error("账号或邮箱不能为空");
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
return ApiResponseUtil.error("账号或邮箱不存在");
|
||||
return ApiResponseUtils.error("账号或邮箱不存在");
|
||||
}
|
||||
|
||||
if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
|
||||
return ApiResponseUtil.error("密码错误");
|
||||
return ApiResponseUtils.error("密码错误");
|
||||
}
|
||||
|
||||
String token = jwtUtil.generateToken(user.getUserId());
|
||||
@ -129,7 +128,7 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
userMapper.updateLastLoginAt(user.getUserId());
|
||||
|
||||
return ApiResponseUtil.success("登录成功", loginUserVO, token);
|
||||
return ApiResponseUtils.success("登录成功", loginUserVO, token);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -137,26 +136,26 @@ public class UserServiceImpl implements UserService {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
if (userId == null) {
|
||||
return ApiResponseUtil.error("未登录");
|
||||
return ApiResponseUtils.error("未登录");
|
||||
}
|
||||
|
||||
try {
|
||||
User user = userMapper.findById(userId);
|
||||
if (user == null) {
|
||||
return ApiResponseUtil.error("用户不存在");
|
||||
return ApiResponseUtils.error("用户不存在");
|
||||
}
|
||||
|
||||
String newToken = jwtUtil.generateToken(userId);
|
||||
if (newToken == null) {
|
||||
return ApiResponseUtil.error("token生成失败");
|
||||
return ApiResponseUtils.error("token生成失败");
|
||||
}
|
||||
|
||||
LoginUserVO loginUserVO = new LoginUserVO();
|
||||
BeanUtils.copyProperties(user, loginUserVO);
|
||||
return ApiResponseUtil.success("获取用户信息成功", loginUserVO, newToken);
|
||||
return ApiResponseUtils.success("获取用户信息成功", loginUserVO, newToken);
|
||||
} catch (Exception e) {
|
||||
log.error("获取用户信息失败", e);
|
||||
return ApiResponseUtil.error("获取用户信息失败");
|
||||
return ApiResponseUtils.error("获取用户信息失败");
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,12 +164,12 @@ public class UserServiceImpl implements UserService {
|
||||
User user = userMapper.findById(userId);
|
||||
|
||||
if (user == null) {
|
||||
return ApiResponseUtil.error("用户不存在");
|
||||
return ApiResponseUtils.error("用户不存在");
|
||||
}
|
||||
|
||||
UserVO userVO = new UserVO();
|
||||
BeanUtils.copyProperties(user, userVO);
|
||||
return ApiResponseUtil.success("获取用户信息成功", userVO);
|
||||
return ApiResponseUtils.success("获取用户信息成功", userVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -180,7 +179,7 @@ public class UserServiceImpl implements UserService {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
if (userId == null) {
|
||||
return ApiResponseUtil.error("未登录");
|
||||
return ApiResponseUtils.error("未登录");
|
||||
}
|
||||
|
||||
User user = new User();
|
||||
@ -189,10 +188,10 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
try {
|
||||
userMapper.update(user);
|
||||
return ApiResponseUtil.success("更新用户信息成功");
|
||||
return ApiResponseUtils.success("更新用户信息成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新用户信息失败", e);
|
||||
return ApiResponseUtil.error("更新用户信息失败");
|
||||
return ApiResponseUtils.error("更新用户信息失败");
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,15 +209,15 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
// 分页数据
|
||||
int total = userMapper.countByQueryParam(userQueryParam);
|
||||
int offset = PaginationUtil.calculateOffset(userQueryParam.getPage(), userQueryParam.getPageSize());
|
||||
int offset = PaginationUtils.calculateOffset(userQueryParam.getPage(), userQueryParam.getPageSize());
|
||||
Pagination pagination = new Pagination(userQueryParam.getPage(), userQueryParam.getPageSize(), total);
|
||||
|
||||
try {
|
||||
List<User> users = userMapper.findByQueryParam(userQueryParam, userQueryParam.getPageSize(), offset);
|
||||
|
||||
return ApiResponseUtil.success("获取用户列表成功", users, pagination);
|
||||
return ApiResponseUtils.success("获取用户列表成功", users, pagination);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtil.error(e.getMessage());
|
||||
return ApiResponseUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,10 +227,10 @@ public class UserServiceImpl implements UserService {
|
||||
String url = fileService.uploadImage(file);
|
||||
AvatarVO avatarVO = new AvatarVO();
|
||||
avatarVO.setAvatarUrl(url);
|
||||
return ApiResponseUtil.success("上传成功", avatarVO);
|
||||
return ApiResponseUtils.success("上传成功", avatarVO);
|
||||
} catch (Exception e) {
|
||||
log.error("上传失败", e);
|
||||
return ApiResponseUtil.error("上传失败");
|
||||
return ApiResponseUtils.error("上传失败");
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,27 +239,27 @@ public class UserServiceImpl implements UserService {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
if (userId == null) {
|
||||
return ApiResponseUtil.error("未登录");
|
||||
return ApiResponseUtils.error("未登录");
|
||||
}
|
||||
|
||||
User user = null;
|
||||
user = userMapper.findById(userId);
|
||||
if (user == null || !passwordEncoder.matches(oldPassword, user.getPassword())) {
|
||||
return ApiResponseUtil.error("旧密码错误");
|
||||
return ApiResponseUtils.error("旧密码错误");
|
||||
}
|
||||
|
||||
if (Objects.equals(oldPassword, newPassword)) {
|
||||
return ApiResponseUtil.error("新密码不能与旧密码相同");
|
||||
return ApiResponseUtils.error("新密码不能与旧密码相同");
|
||||
}
|
||||
|
||||
user.setPassword(passwordEncoder.encode(newPassword));
|
||||
|
||||
try {
|
||||
userMapper.updatePassword(user.getUserId(), user.getPassword());
|
||||
return ApiResponseUtil.success("更新密码成功");
|
||||
return ApiResponseUtils.success("更新密码成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新密码失败", e);
|
||||
return ApiResponseUtil.error("更新密码失败");
|
||||
return ApiResponseUtils.error("更新密码失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import com.example.copykamanotes.model.base.PaginationApiResponse;
|
||||
import com.example.copykamanotes.model.base.TokenApiResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class ApiResponseUtil {
|
||||
public class ApiResponseUtils {
|
||||
|
||||
/**
|
||||
* 构建成功的响应
|
||||
@ -44,8 +44,9 @@ public class JwtUtil {
|
||||
*/
|
||||
public Long getUserIdFromToken(String token) {
|
||||
try {
|
||||
Claims claims = Jwts.parser()
|
||||
.setSigningKey(SECRET_KEY)
|
||||
Claims claims = Jwts
|
||||
.parserBuilder()
|
||||
.setSigningKey(SECRET_KEY).build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
return Long.valueOf(claims.get("userId").toString());
|
||||
@ -60,7 +61,8 @@ public class JwtUtil {
|
||||
*/
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
|
||||
Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token);
|
||||
// Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
|
||||
@ -15,20 +15,24 @@ public class MarkdownAST {
|
||||
private final Document markdownAST;
|
||||
private final String markdownText;
|
||||
|
||||
public MarkdownAST( String markdownText) {
|
||||
// 构造函数:初始化并解析 Markdown文本
|
||||
public MarkdownAST(String markdownText) {
|
||||
this.markdownText = markdownText;
|
||||
|
||||
Parser parser = Parser.builder().build();
|
||||
// 解析 Markdown 文本
|
||||
this.markdownAST = parser.parse(markdownText);
|
||||
}
|
||||
|
||||
public String extractIntroduction(int maxChars) {
|
||||
StringBuilder introText = new StringBuilder();
|
||||
|
||||
// 遍历 AST 节点,提取文本内容
|
||||
for (Node node : markdownAST.getChildren()) {
|
||||
if (node instanceof Heading || node instanceof Paragraph) {
|
||||
// 获取节点的文本内容
|
||||
String renderedText = getNoteText(node);
|
||||
|
||||
// 计算剩余字符数,并截取文本
|
||||
int remainingChars = maxChars - introText.length();
|
||||
introText.append(renderedText, 0, Math.min(remainingChars, renderedText.length()));
|
||||
|
||||
@ -41,26 +45,30 @@ public class MarkdownAST {
|
||||
return introText.toString().trim() + "...";
|
||||
}
|
||||
|
||||
// 检查Markdown文本中是否包含图片
|
||||
public List<String> extractImages() {
|
||||
List<String> images = new ArrayList<>();
|
||||
List<String> imageUrls = new ArrayList<>();
|
||||
|
||||
for (Node node : markdownAST.getChildren()) {
|
||||
if (node instanceof Image imageNode) {
|
||||
images.add(((Image) node).getUrl().toString());
|
||||
imageUrls.add(imageNode.getUrl().toString());
|
||||
}
|
||||
}
|
||||
return images;
|
||||
return imageUrls;
|
||||
}
|
||||
|
||||
// 检查Markdown文本是否需要折叠
|
||||
public boolean shouldCollapse(int maxChars) {
|
||||
return hasImages() || markdownText.length() > maxChars;
|
||||
}
|
||||
|
||||
// 获取折叠后的Markdown文本
|
||||
public String getCollapseMarkdown() {
|
||||
String introText = extractIntroduction(150);
|
||||
return introText + "...";
|
||||
}
|
||||
|
||||
// 获取节点的文本内容
|
||||
private String getNoteText(Node node) {
|
||||
StringBuilder text = new StringBuilder();
|
||||
|
||||
@ -74,6 +82,7 @@ public class MarkdownAST {
|
||||
return text.toString();
|
||||
}
|
||||
|
||||
// 检查Markdown文本中是否包含图片
|
||||
private boolean hasImages() {
|
||||
return !extractImages().isEmpty();
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.example.copykamanotes.utils;
|
||||
|
||||
public class MarkdownUtil {
|
||||
|
||||
public static boolean needCollapsed(String markdown) {
|
||||
MarkdownAST ast = new MarkdownAST(markdown);
|
||||
return ast.shouldCollapse(250);
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
package com.example.copykamanotes.utils;
|
||||
|
||||
public class MarkdownUtils {
|
||||
public static boolean needCollapsed(String markdown) {
|
||||
MarkdownAST ast = new MarkdownAST(markdown);
|
||||
return ast.shouldCollapse(250);
|
||||
}
|
||||
|
||||
public static String extractIntroduction(String markdown) {
|
||||
MarkdownAST ast = new MarkdownAST(markdown);
|
||||
return ast.extractIntroduction(250);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.example.copykamanotes.utils;
|
||||
|
||||
public class PaginationUtil {
|
||||
public class PaginationUtils {
|
||||
/**
|
||||
* 计算分页参数
|
||||
*
|
||||
@ -0,0 +1,37 @@
|
||||
package com.example.copykamanotes.utils;
|
||||
|
||||
import com.huaban.analysis.jieba.JiebaSegmenter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SearchUtils {
|
||||
private static final JiebaSegmenter segmenter = new JiebaSegmenter();
|
||||
|
||||
/**
|
||||
* 预处理搜索关键词
|
||||
* @param keyword
|
||||
* @return
|
||||
*/
|
||||
public static String preprocessKeyword(String keyword) {
|
||||
if (!StringUtils.hasText(keyword)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
keyword = keyword.replaceAll("[\\p{P}\\p{S}]", " ");
|
||||
|
||||
List<String> words = segmenter.sentenceProcess(keyword);
|
||||
|
||||
return String.join(" ", words);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算分页的偏移量
|
||||
* @param page
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
public static int calculateOffset(int page, int pageSize) {
|
||||
return Math.max(0, (page - 1) * pageSize);
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,7 @@ import com.example.copykamanotes.model.entity.User;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class SecurityUtil {
|
||||
public class SecurityUtils {
|
||||
/**
|
||||
* 获取当前登录用户的ID
|
||||
*
|
||||
Reference in New Issue
Block a user