liuyanming.lym 3 місяців тому
батько
коміт
f1053d8341

+ 3 - 1
README.md

@@ -67,4 +67,6 @@ curl --location --request POST 'http://localhost:12345/projects/create' --form '
 
 ![icon.png](icon.png)
 > 其他:本项目使用了 + [Shoulder-Framework](https://github.com/ChinaLym/shoulder-framework) (基于[Spring-Boot](https://github.com/spring-projects/spring-boot)的二次开发套件)搭建省下了不少工作量。
-> https://ai-bot.cn/sites/928.html 代码生成
+> https://ai-bot.cn/sites/928.html 代码生成
+> 审核 api?or开源?
+> https://github.com/PaddlePaddle/PaddleHub

+ 50 - 23
src/main/java/org/lym/pom/config/EnumDictionaryRegisterConfig.java

@@ -9,9 +9,16 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
 import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * todo 考虑编程界面
@@ -23,33 +30,53 @@ import java.io.IOException;
 public class EnumDictionaryRegisterConfig {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
+
     @Bean
     public DictionaryEnumRepositoryCustomizer dictionaryEnumRepositoryCustomizer() {
         return dictionaryEnumStore -> {
-            try {
-                // 加載資源  org.lym.pom.repository.mongo.enums 下的 所有.class文件
-                String packageName = "org.lym.pom.repository.mongo.enums";
-
-                PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
-                packageName = packageName.replace('.', '/');
-                String classPath = "classpath*:" + packageName + (packageName.endsWith("/") ? "" : "/") + "**/*.class";
-                Resource[] resources = resolver.getResources(classPath);
-                int count = 0;
-                for(Resource res :resources) {
-                    // 先获取resource的元信息,然后获取class元信息,最后得到 class 全路径
-                    String clsName = new SimpleMetadataReaderFactory().getMetadataReader(res).getClassMetadata().getClassName();
-                    // 通过名称加载
-                    Class<?> clazz = Class.forName(clsName);
-                    if(clazz.isEnum() && DictionaryEnum.class.isAssignableFrom(clazz)) {
+            // 加載資源  org.lym.pom.repository.mongo.enums 下的 所有.class文件
+            AtomicInteger count = new AtomicInteger();
+            loadClassInPackage("org.lym.pom.repository.mongo.enums",
+                    clazz -> clazz.isEnum() && DictionaryEnum.class.isAssignableFrom(clazz),
+                    clazz -> {
                         dictionaryEnumStore.register((Class<? extends Enum<? extends DictionaryEnum<?, ?>>>) clazz);
-                        logger.info("register " + clsName + " to DefaultDictionaryEnumStore.");
-                        count++;
-                    }
-                }
-                logger.info("register " + count + " classes DefaultDictionaryEnumStore.");
-            } catch (IOException|ClassNotFoundException e) {
-                throw new RuntimeException(e);
-            }
+                        logger.info("register " + clazz.getName() + " to DefaultDictionaryEnumStore.");
+                        count.incrementAndGet();
+                    });
+            logger.info("register " + count.get() + " classes DefaultDictionaryEnumStore.");
         };
     }
+
+    public static List<Class<?>> loadClassInPackage(String packageName, Function<Class<?>, Boolean> classFilter,
+                                                    Consumer<Class<?>> consumer) {
+
+        return Arrays.stream(EnumDictionaryRegisterConfig.readPackageAllClassResource(packageName))
+                .map(EnumDictionaryRegisterConfig::readResourceToClass)
+                .filter(classFilter::apply)
+                .peek(consumer)
+                .collect(Collectors.toList());
+    }
+
+    public static MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+
+    public static Resource[] readPackageAllClassResource(String packageName) {
+        try {
+            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+            packageName = packageName.replace('.', '/');
+            String classPath = "classpath*:" + packageName + (packageName.endsWith("/") ? "" : "/") + "**/*.class";
+            return resolver.getResources(classPath);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Class<?> readResourceToClass(Resource res) {
+        try {
+            // 先获取resource的元信息,然后获取class元信息,最后得到 class 全路径,通过名称加载
+            String clsName = metadataReaderFactory.getMetadataReader(res).getClassMetadata().getClassName();
+            return Class.forName(clsName);
+        } catch (IOException | ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

+ 100 - 0
src/main/java/org/lym/pom/config/MongoConfig.java

@@ -0,0 +1,100 @@
+package org.lym.pom.config;
+
+import cn.hutool.core.util.ReflectUtil;
+import jakarta.persistence.AttributeConverter;
+import org.shoulder.web.template.dictionary.convert.DictionaryItemDTO2DomainConverterRegister.DictionaryEnumSerialGenericConverter;
+import org.shoulder.web.template.dictionary.convert.DictionaryItemDTO2DomainConverterRegister.DictionaryItemToStrGenericConverter;
+import org.shoulder.web.template.dictionary.convert.DictionaryItemDTO2DomainConverterRegister.ToDictionaryEnumGenericConverter;
+import org.shoulder.web.template.dictionary.model.DictionaryItem;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.convert.TypeDescriptor;
+import org.springframework.core.convert.converter.GenericConverter;
+import org.springframework.data.convert.PropertyValueConverter;
+import org.springframework.data.convert.ValueConversionContext;
+import org.springframework.data.mapping.PersistentProperty;
+import org.springframework.data.mongodb.config.MongoConfigurationSupport;
+import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.lang.NonNull;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+
+@Configuration
+//@EnableMongoRepositories("org.lym.pom.repository")
+public class MongoConfig extends MongoConfigurationSupport {
+
+    @Override protected String getDatabaseName() {
+        MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter();
+        // todo
+        return "moments";
+    }
+
+    @Override
+    protected Collection<String> getMappingBasePackages() {
+        return List.of("org.lym.pom.repository");
+    }
+
+    @Override
+    public boolean autoIndexCreation() {
+        return true;
+    }
+
+    /**
+     * @param converterConfigurationAdapter never {@literal null}.
+     * @see org.springframework.data.mongodb.core.convert.MongoValueConverter
+     */
+    @Override protected void configureConverters(MongoConverterConfigurationAdapter converterConfigurationAdapter) {
+
+        converterConfigurationAdapter.configurePropertyConversions(propertyValueConverterRegistrar -> {
+            EnumDictionaryRegisterConfig.loadClassInPackage("org.lym.pom.repository.mongo",
+                    // mongodb 类
+                    clazz -> !clazz.isEnum() && Serializable.class.isAssignableFrom(clazz) && AnnotationUtils.isAnnotationDeclaredLocally(
+                            Document.class, clazz),
+                    clazz -> {
+                        // 获取
+                        for (Field field : ReflectUtil.getFields(clazz)) {
+                            if (field.getAnnotation(org.springframework.data.mongodb.core.mapping.Field.class) != null
+                                && DictionaryItem.class.isAssignableFrom(field.getType())) {
+                                // 所有字典类字段
+
+                                propertyValueConverterRegistrar.registerConverter(clazz, field.getName(), new EnumToStringConverter());
+                            }
+                        }
+                        //logger.info("register " + clazz.getName() + " fieldName.");
+                    });
+        });
+    }
+
+    //@Bean
+    //public MongoCustomConversions mongoCustomConversions() {
+    //  return MongoCustomConversions.create(config -> config.configurePropertyConversions(pvcr-> {
+    //    pvcr.registerConverter(Post.class, "", new EnumToStringConverter());
+    //  }));
+    //}
+
+    /**
+     * @see AttributeConverter
+     */
+    public static class EnumToStringConverter
+            implements PropertyValueConverter<DictionaryItem<String>, String, ValueConversionContext<? extends PersistentProperty>> {
+
+        @Override public DictionaryItem<String> read(@NonNull String value, ValueConversionContext<? extends PersistentProperty> context) {
+            Class<?> actuallyType = context.getProperty().getActualType();
+            return (DictionaryItem<String>) ToDictionaryEnumGenericConverter.INSTANCE.convert(value, TypeDescriptor.valueOf(String.class),
+                    TypeDescriptor.valueOf(actuallyType));
+        }
+
+        @Override public String write(@NonNull DictionaryItem<String> value, ValueConversionContext<? extends PersistentProperty> context) {
+            Class<?> actuallyType = context.getProperty().getActualType();
+            GenericConverter converter = actuallyType.isEnum()
+                    ? DictionaryEnumSerialGenericConverter.INSTANCE
+                    : DictionaryItemToStrGenericConverter.INSTANCE;
+            return (String) converter.convert(value, TypeDescriptor.valueOf(actuallyType), TypeDescriptor.valueOf(String.class));
+        }
+    }
+    // ...
+}

+ 5 - 0
src/main/java/org/lym/pom/repository/INotifyRecordRepository.java

@@ -1,7 +1,9 @@
 package org.lym.pom.repository;
 
+import jakarta.persistence.LockModeType;
 import org.lym.pom.entity.NotifyRecordEntity;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Lock;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
@@ -27,6 +29,9 @@ public interface INotifyRecordRepository extends JpaRepository<NotifyRecordEntit
 
     List<NotifyRecordEntity> findAllByNotified(Boolean notified);
 
+    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
+    List<NotifyRecordEntity> findByIdIn(List<String> idList);
+
     @Transactional
     void deleteByProjectIdAndNotified(Long projectId, boolean notified);
 

+ 4 - 0
src/main/java/org/lym/pom/repository/mongo/Comment.java

@@ -3,6 +3,7 @@ package org.lym.pom.repository.mongo;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.lym.pom.repository.mongo.enums.CommentStatusEnum;
 import org.shoulder.core.dto.response.PageResult;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.index.Indexed;
@@ -33,6 +34,9 @@ public class Comment implements Serializable {
     @Id
     private String id;
 
+    @Field
+    private CommentStatusEnum xxx;
+
     /**
      * 所属对象 id,可以是文章的
      * 评论的评论,该值仍然为被评论对象id

+ 2 - 0
src/main/java/org/lym/pom/repository/mongo/Follow.java

@@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.index.CompoundIndex;
 import org.springframework.data.mongodb.core.index.Indexed;
 import org.springframework.data.mongodb.core.mapping.Document;
 import org.springframework.data.mongodb.core.mapping.Field;
@@ -19,6 +20,7 @@ import java.io.Serializable;
 @AllArgsConstructor
 @NoArgsConstructor
 @Document(collection = Follow.COLLECTION_NAME)
+@CompoundIndex(name = "idx_follow", def = "{'userId': 1, 'followUserId': -1}")
 public class Follow implements Serializable {
 
     public static final String COLLECTION_NAME = "follow";

+ 5 - 3
src/main/java/org/lym/pom/repository/mongo/enums/CommentTypeEnum.java

@@ -1,5 +1,6 @@
 package org.lym.pom.repository.mongo.enums;
 
+import lombok.Getter;
 import org.lym.pom.repository.mongo.Comment;
 import org.shoulder.web.template.dictionary.model.NameAsIdDictionaryEnum;
 
@@ -9,7 +10,7 @@ import org.shoulder.web.template.dictionary.model.NameAsIdDictionaryEnum;
  * @see Comment#type
  * @author lym
  */
-public enum CommentTypeEnum implements NameAsIdDictionaryEnum<CommentTypeEnum> {
+@Getter public enum CommentTypeEnum implements NameAsIdDictionaryEnum<CommentTypeEnum> {
     TEXT(Comment.Type.TEXT),
     MARKDOWN(Comment.Type.MARKDOWN),
     WITH_IMAGE(Comment.Type.WITH_IMAGE),
@@ -21,8 +22,9 @@ public enum CommentTypeEnum implements NameAsIdDictionaryEnum<CommentTypeEnum> {
     CommentTypeEnum(String storageName) {
         this.storageName = storageName;
     }
-
-    public String getStorageName() {
+    @Override
+    public String getItemId() {
         return storageName;
     }
+
 }

+ 2 - 0
src/test/java/posts/CommentServiceImplTest.java

@@ -6,6 +6,7 @@ import org.lym.pom.PomUpdateApplication;
 import org.lym.pom.repository.mongo.Comment;
 import org.lym.pom.repository.mongo.Comment.RelatedType;
 import org.lym.pom.repository.mongo.Comment.Type;
+import org.lym.pom.repository.mongo.enums.CommentStatusEnum;
 import org.lym.pom.service.CommentService;
 import org.shoulder.core.dto.request.BasePageQuery;
 import org.shoulder.core.dto.response.PageResult;
@@ -37,6 +38,7 @@ public class CommentServiceImplTest {
 
         // 创建自评
         Comment comment = new Comment();
+        comment.setXxx(CommentStatusEnum.AUDIT);
         comment.setRelatedId(relatedId);
         comment.setRelatedType(RelatedType.MOMENT);
         comment.setRelatedUserId(publishUser);