diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/EnableIndex.java b/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/EnableIndex.java new file mode 100644 index 0000000..4294cc4 --- /dev/null +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/EnableIndex.java @@ -0,0 +1,29 @@ +package com.blossom.backend.base.search; + +import com.blossom.backend.base.search.message.IndexMsgTypeEnum; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface EnableIndex { + + /** + * 索引操作类型, 默认值为追加 + * @return + */ + IndexMsgTypeEnum type(); + + /** + * id字段表达式 + * @return + */ + String id(); + +} diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/IndexAspect.java b/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/IndexAspect.java new file mode 100644 index 0000000..dcb49e8 --- /dev/null +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/IndexAspect.java @@ -0,0 +1,139 @@ +package com.blossom.backend.base.search; + +import com.blossom.backend.base.auth.AuthContext; +import com.blossom.backend.base.search.message.ArticleIndexMsg; +import com.blossom.backend.base.search.message.IndexMsgTypeEnum; +import com.blossom.backend.base.search.queue.IndexMsgQueue; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Method; + +@Aspect +@Component +@Slf4j +public class IndexAspect { + + /** + * 用于spl解析 + */ + private static final LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); + + @Pointcut("@annotation(com.blossom.backend.base.search.EnableIndex)") + private void cutMethod(){ + + } + + /** + * 成功返回后调用该方法,维护索引。 使用after防止事务未提交导致的数据滞后 + */ + @AfterReturning("cutMethod()") + public void afterReturning(JoinPoint joinPoint) { + // 此处进行索引处理, 降低索引维护代码侵入 + // 获取注解对象 + EnableIndex annotation = getAnnotation(joinPoint); + if (annotation == null){ + // 记录问题, 并结束逻辑 + log.error("索引切面获取注解失败!"); + return; + } + + IndexMsgTypeEnum indexMsgTypeEnum = annotation.type(); + if (indexMsgTypeEnum == null){ + log.error("获取索引消息操作类型失败"); + return; + } + String idSpEL = annotation.id(); + if (!StringUtils.hasText(idSpEL)){ + log.error("获取id表达式失败"); + return; + } + Long customerId = parse(idSpEL, joinPoint, Long.class); + if (customerId == null){ + return; + } + ArticleIndexMsg indexMsg = new ArticleIndexMsg(indexMsgTypeEnum, customerId, AuthContext.getUserId()); + try { + IndexMsgQueue.add(indexMsg); + } catch (InterruptedException e) { + // 不抛出, 暂时先记录 + log.error("索引操作失败" + e.getMessage()); + } + } + + /** + * 获取method + * @return method + */ + private Method getTargetMethod(JoinPoint joinPoint) { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature)signature; + Method agentMethod = methodSignature.getMethod(); + try { + return joinPoint.getTarget().getClass().getMethod(agentMethod.getName(),agentMethod.getParameterTypes()); + }catch (Exception e){ + // 只记录异常 + log.error("获取目标方法失败"); + } + return null; + } + + /** + * 获取注解声明对象 + * @param joinPoint + * @return + */ + private EnableIndex getAnnotation(JoinPoint joinPoint){ + // 获取方法上的注解 + MethodSignature sign = (MethodSignature) joinPoint.getSignature(); + Method method = sign.getMethod(); + return method.getAnnotation(EnableIndex.class); + } + + /** + * 解析SpEL表达式, 提供后续拓展的灵活性 + * @param spel + * @param joinPoint + * @param clazz + * @return + * @param + */ + private T parse(String spel, JoinPoint joinPoint, Class clazz){ + ExpressionParser parser = new SpelExpressionParser(); + Method method = getTargetMethod(joinPoint); + if (method == null){ + return null; + } + + String[] params = discoverer.getParameterNames(method); + if (params == null || params.length == 0){ + log.error("获取参数列表失败"); + return null; + } + + Object[] args = joinPoint.getArgs(); + EvaluationContext context = new StandardEvaluationContext(); + for (int len = 0; len < params.length; len++) { + context.setVariable(params[len], args[len]); + } + + Expression expression = parser.parseExpression(spel); + return expression.getValue(context, clazz); + } + + + +} diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/message/consumer/IndexMsgConsumer.java b/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/message/consumer/IndexMsgConsumer.java index 51cdecc..fd13b9f 100644 --- a/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/message/consumer/IndexMsgConsumer.java +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/base/search/message/consumer/IndexMsgConsumer.java @@ -21,7 +21,6 @@ import org.apache.lucene.store.FSDirectory; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import java.io.File; import java.util.concurrent.Executors; /** @@ -88,7 +87,7 @@ public class IndexMsgConsumer { } } else if (IndexMsgTypeEnum.DELETE.equals(indexMsg.getType())) { // 删除索引 - try (Directory directory = FSDirectory.open(new File(searchProperties.getPath()).toPath()); + try (Directory directory = FSDirectory.open(searchProperties.getUserIndexDirectory(userId)); IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(new StandardAnalyzer())); ) { diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleService.java b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleService.java index 307400b..b98f965 100644 --- a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleService.java +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleService.java @@ -4,10 +4,8 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.blossom.backend.base.auth.AuthContext; -import com.blossom.backend.base.search.message.ArticleIndexMsg; +import com.blossom.backend.base.search.EnableIndex; import com.blossom.backend.base.search.message.IndexMsgTypeEnum; -import com.blossom.backend.base.search.queue.IndexMsgQueue; import com.blossom.backend.server.article.TagEnum; import com.blossom.backend.server.article.draft.pojo.ArticleEntity; import com.blossom.backend.server.article.draft.pojo.ArticleQueryReq; @@ -151,16 +149,10 @@ public class ArticleService extends ServiceImpl { /** * 新增 */ + @EnableIndex(type = IndexMsgTypeEnum.ADD, id = "#req.id") @Transactional(rollbackFor = Exception.class) public ArticleEntity insert(ArticleEntity req) { baseMapper.insert(req); - ArticleIndexMsg articleIndexMsg = new ArticleIndexMsg(IndexMsgTypeEnum.ADD, req.getId(), AuthContext.getUserId()); - try { - IndexMsgQueue.add(articleIndexMsg); - } catch (InterruptedException e) { - // 不抛出, 暂时先记录 - log.error("索引更新失败" + e.getMessage()); - } return req; } @@ -168,17 +160,11 @@ public class ArticleService extends ServiceImpl { * 修改 *

该接口只能修改文章的基本信息, 正文及版本修改请使用 {@link ArticleService#updateContentById(ArticleEntity)} */ + @EnableIndex(type = IndexMsgTypeEnum.ADD, id = "#req.id") @Transactional(rollbackFor = Exception.class) public Long update(ArticleEntity req) { XzException404.throwBy(req.getId() == null, "ID不得为空"); baseMapper.updById(req); - ArticleIndexMsg articleIndexMsg = new ArticleIndexMsg(IndexMsgTypeEnum.ADD, req.getId(),AuthContext.getUserId()); - try { - IndexMsgQueue.add(articleIndexMsg); - } catch (InterruptedException e) { - // 不抛出, 暂时先记录 - log.error("索引更新失败" + e.getMessage()); - } return req.getId(); } @@ -187,6 +173,7 @@ public class ArticleService extends ServiceImpl { * * @return 返回文章字数 */ + @EnableIndex(type = IndexMsgTypeEnum.ADD, id = "#req.id") @Transactional(rollbackFor = Exception.class) public Integer updateContentById(ArticleEntity req) { XzException404.throwBy(req.getId() == null, "ID不得为空"); @@ -199,14 +186,6 @@ public class ArticleService extends ServiceImpl { baseMapper.updContentById(req); referenceService.bind(req.getUserId(), req.getId(), req.getName(), req.getReferences()); logService.insert(req.getId(), 0, req.getMarkdown()); - // 更新索引 - ArticleIndexMsg articleIndexMsg = new ArticleIndexMsg(IndexMsgTypeEnum.ADD, req.getId(), AuthContext.getUserId()); - try { - IndexMsgQueue.add(articleIndexMsg); - } catch (InterruptedException e) { - // 不抛出, 暂时先记录 - log.error("索引更新失败" + e.getMessage()); - } return req.getWords(); } @@ -218,6 +197,7 @@ public class ArticleService extends ServiceImpl { * @param id 文章ID * @since 1.10.0 删除时不校验文章内容, 被删除的文章会进入回收站, 可在回收站中查询 */ + @EnableIndex(type = IndexMsgTypeEnum.DELETE, id = "#id") @Transactional(rollbackFor = Exception.class) public void delete(Long id) { ArticleEntity article = selectById(id, false, true, true); @@ -235,14 +215,6 @@ public class ArticleService extends ServiceImpl { referenceService.delete(id); // 删除访问记录 viewService.delete(id); - // 删除索引 - ArticleIndexMsg articleIndexMsg = new ArticleIndexMsg(IndexMsgTypeEnum.DELETE, id, AuthContext.getUserId()); - try { - IndexMsgQueue.add(articleIndexMsg); - } catch (InterruptedException e) { - // 不抛出, 暂时先记录 - log.error("索引更新失败" + e.getMessage()); - } } /** diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/recycle/ArticleRecycleService.java b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/recycle/ArticleRecycleService.java index eebe9a8..c753f16 100644 --- a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/recycle/ArticleRecycleService.java +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/recycle/ArticleRecycleService.java @@ -3,13 +3,11 @@ package com.blossom.backend.server.article.recycle; import cn.hutool.core.util.ObjUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.blossom.backend.base.auth.AuthContext; import com.blossom.backend.base.param.ParamEnum; import com.blossom.backend.base.param.ParamService; import com.blossom.backend.base.param.pojo.ParamEntity; -import com.blossom.backend.base.search.message.ArticleIndexMsg; +import com.blossom.backend.base.search.EnableIndex; import com.blossom.backend.base.search.message.IndexMsgTypeEnum; -import com.blossom.backend.base.search.queue.IndexMsgQueue; import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleEntity; import com.blossom.backend.server.folder.FolderService; import com.blossom.backend.server.folder.pojo.FolderEntity; @@ -52,6 +50,7 @@ public class ArticleRecycleService extends ServiceImpl