Browse Source

优化用户保存逻辑

zhou-hao 3 years ago
parent
commit
438543f12b

+ 16 - 7
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java

@@ -3,6 +3,7 @@ package org.hswebframework.web.system.authorization.defaults.service;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.collections4.CollectionUtils;
 import org.hswebframework.ezorm.core.param.QueryParam;
+import org.hswebframework.ezorm.rdb.exception.DuplicateKeyException;
 import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
 import org.hswebframework.web.api.crud.entity.TransactionManagers;
 import org.hswebframework.web.crud.service.GenericReactiveCrudService;
@@ -63,7 +64,7 @@ public class DefaultReactiveUserService extends GenericReactiveCrudService<UserE
                     }
                     return findById(userEntity.getId())
                             .flatMap(ignore -> doUpdate(userEntity))
-                            .switchIfEmpty(doAdd(userEntity));
+                            .switchIfEmpty(Mono.error(NotFoundException::new));
                 }).thenReturn(true);
     }
 
@@ -76,14 +77,22 @@ public class DefaultReactiveUserService extends GenericReactiveCrudService<UserE
                     userEntity.generateId();
                     userEntity.setSalt(IDGenerator.RANDOM.generate());
                     userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword(), userEntity.getSalt()));
-                    return Mono
-                            .just(userEntity)
+                    return this
+                            .createQuery()
+                            .where(userEntity::getUsername)
+                            .fetch()
+                            .doOnNext(u -> {
+                                throw new org.hswebframework.web.exception.ValidationException("用户已存在");
+                            })
+                            .then(Mono.just(userEntity))
                             .doOnNext(e -> e.tryValidate(CreateGroup.class))
-                            .as(getRepository()::save)
+                            .as(getRepository()::insert)
+                            .onErrorMap(DuplicateKeyException.class, e -> {
+                                throw new org.hswebframework.web.exception.ValidationException("用户已存在");
+                            })
                             .thenReturn(userEntity)
-                            .flatMap(user -> new UserCreatedEvent(user)
-                                    .publish(eventPublisher)
-                                    .thenReturn(user));
+                            .flatMap(user -> new UserCreatedEvent(user).publish(eventPublisher))
+                            .thenReturn(userEntity);
                 });
 
     }

+ 50 - 18
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveUserServiceTest.java

@@ -1,5 +1,6 @@
 package org.hswebframework.web.system.authorization.defaults.service.reactive;
 
+import org.hswebframework.web.exception.ValidationException;
 import org.hswebframework.web.system.authorization.api.entity.UserEntity;
 import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService;
 import org.junit.Assert;
@@ -10,8 +11,11 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit4.SpringRunner;
 import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
 import reactor.test.StepVerifier;
 
+import java.util.function.Supplier;
+
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = ReactiveTestApplication.class)
 public class DefaultReactiveUserServiceTest {
@@ -19,6 +23,34 @@ public class DefaultReactiveUserServiceTest {
     @Autowired
     private ReactiveUserService userService;
 
+
+    @Test
+    public void testParallel() {
+        Supplier<UserEntity> userBuilder = () -> {
+            UserEntity userEntity = userService
+                    .newUserInstance()
+                    .blockOptional()
+                    .orElseThrow(NullPointerException::new);
+            userEntity.setName("test");
+            userEntity.setUsername("parallel");
+            userEntity.setPassword("parallel");
+            return userEntity;
+        };
+
+        Mono
+                .zip(
+                        userService
+                                .saveUser(Mono.just(userBuilder.get()))
+                                .subscribeOn(Schedulers.newSingle("newSingle")),
+                        userService
+                                .saveUser(Mono.just(userBuilder.get()))
+                                .subscribeOn(Schedulers.newSingle("newSingle"))
+                )
+                .as(StepVerifier::create)
+                .expectError(ValidationException.class)
+                .verify();
+    }
+
     @Test
     public void testCrud() {
         UserEntity userEntity = userService.newUserInstance().blockOptional().orElseThrow(NullPointerException::new);
@@ -27,38 +59,38 @@ public class DefaultReactiveUserServiceTest {
         userEntity.setPassword("admin");
 
         userService.saveUser(Mono.just(userEntity))
-                .as(StepVerifier::create)
-                .expectNext(true)
-                .verifyComplete();
+                   .as(StepVerifier::create)
+                   .expectNext(true)
+                   .verifyComplete();
 
         Assert.assertNotNull(userEntity.getId());
 
         userEntity.setUsername("admin2");
         userEntity.setPassword("admin2");
         userService.saveUser(Mono.just(userEntity))
-                .as(StepVerifier::create)
-                .expectNext(true)
-                .verifyComplete();
+                   .as(StepVerifier::create)
+                   .expectNext(true)
+                   .verifyComplete();
 
         userService.changeState(Mono.just(userEntity.getId()), (byte) 1)
-                .as(StepVerifier::create)
-                .expectNext(1)
-                .verifyComplete();
+                   .as(StepVerifier::create)
+                   .expectNext(1)
+                   .verifyComplete();
 
         userService.changePassword(userEntity.getId(), "admin2", "admin")
-                .as(StepVerifier::create)
-                .expectNext(true)
-                .verifyComplete();
+                   .as(StepVerifier::create)
+                   .expectNext(true)
+                   .verifyComplete();
 
         userService.findByUsernameAndPassword("admin", "admin")
-                .as(StepVerifier::create)
-                .expectNextCount(1)
-                .verifyComplete();
+                   .as(StepVerifier::create)
+                   .expectNextCount(1)
+                   .verifyComplete();
 
         userService.deleteUser(userEntity.getId())
-                .as(StepVerifier::create)
-                .expectNext(true)
-                .verifyComplete();
+                   .as(StepVerifier::create)
+                   .expectNext(true)
+                   .verifyComplete();
 
     }