xiongzhu 3 lat temu
rodzic
commit
c79347670f

+ 15 - 0
src/main/java/com/izouma/nineth/annotations/RedisLock.java

@@ -0,0 +1,15 @@
+package com.izouma.nineth.annotations;
+
+import java.lang.annotation.*;
+import java.util.concurrent.TimeUnit;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RedisLock {
+    String value();
+
+    long expire() default 10;
+
+    TimeUnit unit() default TimeUnit.SECONDS;
+}

+ 1 - 1
src/main/java/com/izouma/nineth/aspect/DebounceAspect.java

@@ -39,7 +39,7 @@ public class DebounceAspect {
     }
 
     @Around(value = "debouncePointCut() && @annotation(debounce)")
-    public synchronized void debounce(ProceedingJoinPoint joinPoint, Debounce debounce) {
+    public void debounce(ProceedingJoinPoint joinPoint, Debounce debounce) {
         ExpressionParser parser = new SpelExpressionParser();
         EvaluationContext context = new StandardEvaluationContext(joinPoint.getSignature());
         MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

+ 67 - 0
src/main/java/com/izouma/nineth/aspect/RedisLockAspect.java

@@ -0,0 +1,67 @@
+package com.izouma.nineth.aspect;
+
+import com.izouma.nineth.annotations.RedisLock;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.DefaultParameterNameDiscoverer;
+import org.springframework.data.redis.core.BoundValueOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.expression.EvaluationContext;
+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 java.lang.reflect.Method;
+import java.util.Optional;
+
+@Aspect
+@Component
+@Slf4j
+public class RedisLockAspect {
+
+    private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    @Pointcut("@annotation(com.izouma.nineth.annotations.RedisLock)")
+    public void redisLockPointCut() {
+    }
+
+    @Around(value = "redisLockPointCut() && @annotation(redisLock)")
+    public void redisLock(ProceedingJoinPoint joinPoint, RedisLock redisLock) {
+        ExpressionParser parser = new SpelExpressionParser();
+        EvaluationContext context = new StandardEvaluationContext(joinPoint.getSignature());
+        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+        Method method = methodSignature.getMethod();
+        String[] paramNames = nameDiscoverer.getParameterNames(method);
+        Object[] args = joinPoint.getArgs();
+        for (int i = 0; i < args.length; i++) {
+            context.setVariable(paramNames[i], args[i]);
+        }
+        String key = redisLock.value();
+        try {
+            key = Optional.ofNullable(parser.parseExpression(redisLock.value()).getValue(context))
+                    .map(Object::toString)
+                    .orElse("default");
+        } catch (Exception e) {
+        }
+        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(key);
+        Boolean success = ops.setIfAbsent(1, redisLock.expire(), redisLock.unit());
+        if (Boolean.TRUE.equals(success)) {
+            try {
+                joinPoint.proceed();
+            } catch (Throwable e) {
+                e.printStackTrace();
+            }
+            redisTemplate.delete(key);
+        }
+    }
+
+}

+ 55 - 5
src/main/java/com/izouma/nineth/config/CacheConfig.java

@@ -6,6 +6,8 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import com.izouma.nineth.JsonView.UserView;
@@ -24,6 +26,10 @@ import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
 import org.springframework.data.redis.serializer.RedisSerializationContext;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
 
 @Configuration
 @AutoConfigureAfter({RedisAutoConfiguration.class, CacheAutoConfiguration.class})
@@ -49,6 +55,10 @@ public class CacheConfig {
         mapper.registerModule(new JavaTimeModule());
         mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
         mapper.setConfig(mapper.getSerializationConfig().withView(UserView.Redis.class));
+        SimpleModule simpleModule = new SimpleModule();
+        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
+        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
+        mapper.registerModule(simpleModule);
 
         serializer.setObjectMapper(mapper);
 
@@ -61,11 +71,51 @@ public class CacheConfig {
         return template;
     }
 
+    //    @Bean
+//    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
+//        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
+//        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
+//                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
+//        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
+//    }
     @Bean
-    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
-        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
-        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
-                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
-        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
+    public RedisCacheManager userRedisCacheManager(RedisConnectionFactory connectionFactory) {
+        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL,
+                JsonTypeInfo.As.WRAPPER_ARRAY);
+        mapper.registerModule(new Hibernate5Module()
+                .enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING));
+        mapper.registerModule(new JavaTimeModule());
+        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+        mapper.setConfig(mapper.getSerializationConfig().withView(UserView.Redis.class));
+        SimpleModule simpleModule = new SimpleModule();
+        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
+        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
+        mapper.registerModule(simpleModule);
+
+        serializer.setObjectMapper(mapper);
+
+        Map<String, RedisCacheConfiguration> cacheNamesConfigurationMap = new HashMap<>();
+        cacheNamesConfigurationMap.put("collectionList", RedisCacheConfiguration.defaultCacheConfig()
+                .entryTtl(Duration.ofSeconds(10))
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)));
+        cacheNamesConfigurationMap.put("collection", RedisCacheConfiguration.defaultCacheConfig()
+                .entryTtl(Duration.ofMinutes(10)));
+
+        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
+
+        RedisCacheManager redisCacheManager = RedisCacheManager.builder()
+                .cacheWriter(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory))
+                .withInitialCacheConfigurations(cacheNamesConfigurationMap)
+                .cacheDefaults(cacheConfiguration)
+
+                .build();
+
+        return redisCacheManager;
     }
 }

+ 2 - 0
src/main/java/com/izouma/nineth/dto/PageQuery.java

@@ -1,11 +1,13 @@
 package com.izouma.nineth.dto;
 
 import lombok.Data;
+import lombok.ToString;
 
 import java.util.HashMap;
 import java.util.Map;
 
 @Data
+@ToString
 public class PageQuery {
     private int                 page  = 0;
     private int                 size  = 20;

+ 27 - 0
src/main/java/com/izouma/nineth/dto/PageWrapper.java

@@ -0,0 +1,27 @@
+package com.izouma.nineth.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageWrapper<T> {
+    private List<T> content;
+
+    private int page;
+
+    private int size;
+
+    private long total;
+
+    public Page<T> toPage() {
+        return new PageImpl<>(content, PageRequest.of(page, size), total);
+    }
+}

+ 4 - 0
src/main/java/com/izouma/nineth/service/CacheService.java

@@ -36,4 +36,8 @@ public class CacheService {
     @CacheEvict(value = "recommend", allEntries = true)
     public void clearRecommend() {
     }
+
+    @CacheEvict(value = "collectionList", allEntries = true)
+    public void clearCollectionList() {
+    }
 }

+ 7 - 6
src/main/java/com/izouma/nineth/service/CollectionService.java

@@ -6,10 +6,7 @@ import com.izouma.nineth.config.GeneralProperties;
 import com.izouma.nineth.config.RedisKeys;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.domain.*;
-import com.izouma.nineth.dto.CollectionDTO;
-import com.izouma.nineth.dto.CollectionStockAndSale;
-import com.izouma.nineth.dto.CreateBlindBox;
-import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.dto.*;
 import com.izouma.nineth.enums.CollectionSource;
 import com.izouma.nineth.enums.CollectionType;
 import com.izouma.nineth.enums.OrderStatus;
@@ -25,6 +22,7 @@ import org.apache.commons.lang3.Range;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.springframework.beans.BeanUtils;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.core.env.Environment;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
@@ -85,7 +83,8 @@ public class CollectionService {
         }
     }
 
-    public Page<Collection> all(PageQuery pageQuery) {
+    @Cacheable(value = "collectionList", key = "#pageQuery.hashCode()")
+    public PageWrapper<Collection> all(PageQuery pageQuery) {
         pageQuery.getQuery().put("del", false);
         String type = MapUtils.getString(pageQuery.getQuery(), "type", "DEFAULT");
         pageQuery.getQuery().remove("type");
@@ -115,7 +114,9 @@ public class CollectionService {
             }
             return criteriaBuilder.and(and.toArray(new Predicate[0]));
         });
-        return collectionRepo.findAll(specification, pageRequest);
+        Page<Collection> page = collectionRepo.findAll(specification, pageRequest);
+        return new PageWrapper<>(page.getContent(), page.getPageable().getPageNumber(),
+                page.getPageable().getPageSize(), page.getTotalElements());
     }
 
     public Collection create(Collection record) {

+ 33 - 31
src/main/java/com/izouma/nineth/service/IdentityAuthService.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.github.kevinsawicki.http.HttpRequest;
+import com.izouma.nineth.annotations.RedisLock;
 import com.izouma.nineth.domain.IdentityAuth;
 import com.izouma.nineth.domain.User;
 import com.izouma.nineth.dto.PageQuery;
@@ -12,12 +13,13 @@ import com.izouma.nineth.repo.UserRepo;
 import com.izouma.nineth.utils.JpaUtils;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.env.Environment;
 import org.springframework.data.domain.Page;
-import org.springframework.data.redis.core.BoundValueOperations;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -31,6 +33,7 @@ public class IdentityAuthService {
     private UserRepo                      userRepo;
     private AdapayService                 adapayService;
     private RedisTemplate<String, Object> redisTemplate;
+    private Environment                   env;
 
     public Page<IdentityAuth> all(PageQuery pageQuery) {
         return identityAuthRepo.findAll(JpaUtils.toSpecification(pageQuery, IdentityAuth.class), JpaUtils.toPageRequest(pageQuery));
@@ -54,7 +57,7 @@ public class IdentityAuthService {
         userRepo.save(user);
     }
 
-    public void audit(Long id, AuthStatus status) {
+    public void audit(Long id, AuthStatus status, String reason) {
         IdentityAuth auth = identityAuthRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("申请不存在"));
         if (auth.getStatus() != AuthStatus.PENDING) {
             throw new BusinessException("已经审核过");
@@ -64,6 +67,8 @@ public class IdentityAuthService {
             user.setAuthId(auth.getId());
         }
         auth.setStatus(status);
+        auth.setReason(reason);
+        auth.setAutoValidated(true);
         identityAuthRepo.save(auth);
         user.setAuthStatus(status);
         userRepo.save(user);
@@ -103,37 +108,34 @@ public class IdentityAuthService {
     }
 
     @Scheduled(fixedRate = 60000)
+    @RedisLock(value = "autoValidate", expire = 30, unit = TimeUnit.MINUTES)
     public void autoValidate() {
-        BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps("autoValidate");
-        Boolean b = ops.setIfAbsent(1, 1, TimeUnit.HOURS);
-        if (Boolean.TRUE.equals(b)) {
-            try {
-                List<IdentityAuth> list = identityAuthRepo.findByStatusAndAutoValidated(AuthStatus.PENDING, false);
-                list.parallelStream().forEach(identityAuth -> {
-                    int count = identityAuthRepo.countByIdNoAndStatus(identityAuth.getIdNo(), AuthStatus.SUCCESS);
-                    boolean success = false;
-                    String reason = null;
-                    if (count >= 3) {
-                        success = false;
-                        reason = "同一身份证注册超过3个";
-                    } else {
-                        try {
-                            User user = userRepo.findById(identityAuth.getUserId())
-                                    .orElseThrow(new BusinessException("用户不存在"));
-                            validate(identityAuth.getRealName(), user.getPhone(), identityAuth.getIdNo());
-                            success = true;
-                        } catch (Exception e) {
-                            reason = e.getMessage();
-                        }
+        log.info("autoValidate");
+        if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
+            return;
+        }
+        try {
+            List<IdentityAuth> list = identityAuthRepo.findByStatusAndAutoValidated(AuthStatus.PENDING, false);
+            list.parallelStream().forEach(identityAuth -> {
+                int count = identityAuthRepo.countByIdNoAndStatus(identityAuth.getIdNo(), AuthStatus.SUCCESS);
+                boolean success = false;
+                String reason = null;
+                if (count >= 3) {
+                    success = false;
+                    reason = "同一身份证注册超过3个";
+                } else {
+                    try {
+                        User user = userRepo.findById(identityAuth.getUserId())
+                                .orElseThrow(new BusinessException("用户不存在"));
+                        validate(identityAuth.getRealName(), user.getPhone(), identityAuth.getIdNo());
+                        success = true;
+                    } catch (Exception e) {
+                        reason = e.getMessage();
                     }
-                    identityAuth.setAutoValidated(true);
-                    identityAuth.setReason(reason);
-                    identityAuth.setStatus(success ? AuthStatus.SUCCESS : AuthStatus.PENDING);
-                    identityAuthRepo.save(identityAuth);
-                });
-            } catch (Exception ignored) {
-            }
-            redisTemplate.delete("autoValidate");
+                }
+                audit(identityAuth.getId(), success ? AuthStatus.SUCCESS : AuthStatus.PENDING, reason);
+            });
+        } catch (Exception ignored) {
         }
     }
 }

+ 1 - 1
src/main/java/com/izouma/nineth/web/CollectionController.java

@@ -48,7 +48,7 @@ public class CollectionController extends BaseController {
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<CollectionDTO> all(@RequestBody PageQuery pageQuery) {
-        return collectionService.toDTO(collectionService.all(pageQuery));
+        return collectionService.toDTO(collectionService.all(pageQuery).toPage());
     }
 
     @GetMapping("/get/{id}")

+ 3 - 3
src/main/java/com/izouma/nineth/web/IdentityAuthController.java

@@ -61,13 +61,13 @@ public class IdentityAuthController extends BaseController {
     @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
     @PostMapping("/pass")
     public void audit(@RequestParam Long id) {
-        identityAuthService.audit(id, AuthStatus.SUCCESS);
+        identityAuthService.audit(id, AuthStatus.SUCCESS, null);
     }
 
     @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
     @PostMapping("/deny")
-    public void deny(@RequestParam Long id) {
-        identityAuthService.audit(id, AuthStatus.FAIL);
+    public void deny(@RequestParam Long id, @RequestParam(required = false) String reason) {
+        identityAuthService.audit(id, AuthStatus.FAIL, reason);
     }
 
     @ApiOperation("查找重复身份证")

+ 1 - 0
src/main/vue/src/views/IdentityAuthList.vue

@@ -107,6 +107,7 @@
             </el-table-column>
             <el-table-column prop="status" label="审核状态" :formatter="statusFormatter" width="120" align="center">
             </el-table-column>
+            <el-table-column prop="createdAt" label="时间" width="150">
             <el-table-column label="操作" align="center" fixed="right" width="210">
                 <template slot-scope="{ row }">
                     <el-button @click="repeat(row)" type="success" size="mini" plain> 查重 </el-button>

+ 12 - 0
src/test/java/com/izouma/nineth/CommonTest.java

@@ -8,6 +8,7 @@ import com.izouma.nineth.config.Constants;
 import com.izouma.nineth.domain.BaseEntity;
 import com.izouma.nineth.domain.BlindBoxItem;
 import com.izouma.nineth.domain.User;
+import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.utils.AESEncryptUtil;
 import com.izouma.nineth.utils.TokenUtils;
 import com.izouma.nineth.web.BaseController;
@@ -452,4 +453,15 @@ public class CommonTest {
         final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator('=').split(qs);
         System.out.println(map);
     }
+
+    @Test
+    public void aasdf() {
+        System.out.println(new ArrayList<>(10).size());
+
+        PageQuery p1 = new PageQuery();
+        PageQuery p2 = new PageQuery();
+        p1.setPage(2);
+        System.out.println(p1.hashCode());
+        System.out.println(p2.hashCode());
+    }
 }

+ 1 - 2
src/test/java/com/izouma/nineth/service/IdentityAuthServiceTest.java

@@ -4,8 +4,6 @@ import com.izouma.nineth.ApplicationTests;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import static org.junit.Assert.*;
-
 public class IdentityAuthServiceTest extends ApplicationTests {
     @Autowired
     private IdentityAuthService identityAuthService;
@@ -15,4 +13,5 @@ public class IdentityAuthServiceTest extends ApplicationTests {
         identityAuthService.validate("熊竹", "15077886171", "321002199408304611");
         identityAuthService.validate("熊竹", "15077886171", "321002199408304614");
     }
+
 }