From ed8868672ae1804a4061f43b8fd98fa66728a440 Mon Sep 17 00:00:00 2001 From: dante <1062325367@qq.com> Date: Sat, 26 Jun 2021 22:43:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A9=E7=94=A8future=E5=9B=9E=E8=B0=83?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=B9=B6=E5=8F=91=E8=B0=83=E7=94=A8=E6=97=B6?= =?UTF-8?q?=E6=9C=89=E5=A4=9A=E4=B8=AA=E7=BA=BF=E7=A8=8B=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E5=8E=BB=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9F=A5=E8=AF=A2=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E6=B6=88=E8=80=97=E9=A2=9D=E5=A4=96=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E3=80=82=E7=BB=8F=E8=BF=87=E6=B5=8B=E8=AF=95=E5=9C=A8?= =?UTF-8?q?8=E4=B8=AA=E7=BA=BF=E7=A8=8B=E5=B9=B6=E5=8F=91=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=97=B6=E6=80=A7=E8=83=BD=E6=8F=90=E5=8D=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/UserDetailsServiceImpl.java | 120 ++++++++++++++---- .../test/java/me/zhengjie/LoginCacheTest.java | 16 ++- 2 files changed, 107 insertions(+), 29 deletions(-) diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java index c3657d1d..c85dd658 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java @@ -30,7 +30,8 @@ import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; /** * @author Zheng Jie @@ -53,42 +54,109 @@ public class UserDetailsServiceImpl implements UserDetailsService { * * @see {@link UserCacheClean} */ - static Map userDtoCache = new ConcurrentHashMap<>(); + final static Map> userDtoCache = new ConcurrentHashMap<>(); + public static ExecutorService executor = newThreadPool(); @Override public JwtUserDto loadUserByUsername(String username) { - boolean searchDb = true; JwtUserDto jwtUserDto = null; - if (loginProperties.isCacheEnable() && userDtoCache.containsKey(username)) { - jwtUserDto = userDtoCache.get(username); + Future future=userDtoCache.get(username); + if(!loginProperties.isCacheEnable()){ + UserDto user; + try { + user = userService.findByName(username); + } catch (EntityNotFoundException e) { + // SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException + throw new UsernameNotFoundException("", e); + } + if (user == null) { + throw new UsernameNotFoundException(""); + } else { + if (!user.getEnabled()) { + throw new BadRequestException("账号未激活!"); + } + jwtUserDto = new JwtUserDto( + user, + dataService.getDeptIds(user), + roleService.mapToGrantedAuthorities(user) + ); + } + return jwtUserDto; + } + + if (future!=null) { + try { + jwtUserDto=future.get(); + }catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e.getMessage()); + } // 检查dataScope是否修改 List dataScopes = jwtUserDto.getDataScopes(); dataScopes.clear(); dataScopes.addAll(dataService.getDeptIds(jwtUserDto.getUser())); - searchDb = false; - } - if (searchDb) { - UserDto user; - try { - user = userService.findByName(username); - } catch (EntityNotFoundException e) { - // SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException - throw new UsernameNotFoundException("", e); + }else{ + Callable call=()->getJwtBySearchDB(username); + FutureTask ft=new FutureTask<>(call); + future=userDtoCache.putIfAbsent(username,ft); + if(future==null){ + future=ft; + executor.submit(ft); } - if (user == null) { - throw new UsernameNotFoundException(""); - } else { - if (!user.getEnabled()) { - throw new BadRequestException("账号未激活!"); - } - jwtUserDto = new JwtUserDto( - user, - dataService.getDeptIds(user), - roleService.mapToGrantedAuthorities(user) - ); - userDtoCache.put(username, jwtUserDto); + try{ + return future.get(); + }catch(CancellationException e){ + userDtoCache.remove(username); + }catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e.getMessage()); } } return jwtUserDto; } + + private JwtUserDto getJwtBySearchDB(String username) { + UserDto user; + try { + user = userService.findByName(username); + } catch (EntityNotFoundException e) { + // SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException + throw new UsernameNotFoundException("", e); + } + if (user == null) { + throw new UsernameNotFoundException(""); + } else { + if (!user.getEnabled()) { + throw new BadRequestException("账号未激活!"); + } + JwtUserDto jwtUserDto = new JwtUserDto( + user, + dataService.getDeptIds(user), + roleService.mapToGrantedAuthorities(user) + ); + return jwtUserDto; + } + + } + + public static ExecutorService newThreadPool() { + ThreadFactory namedThreadFactory = new ThreadFactory() { + final AtomicInteger sequence = new AtomicInteger(1); + + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + int seq = this.sequence.getAndIncrement(); + thread.setName("future-task-thread" + (seq > 1 ? "-" + seq : "")); + if (!thread.isDaemon()) { + thread.setDaemon(true); + } + + return thread; + } + }; + return new ThreadPoolExecutor(8, 200, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(1024), + namedThreadFactory, + new ThreadPoolExecutor.AbortPolicy()); + } } diff --git a/eladmin-system/src/test/java/me/zhengjie/LoginCacheTest.java b/eladmin-system/src/test/java/me/zhengjie/LoginCacheTest.java index 4d7f55c8..ef608495 100644 --- a/eladmin-system/src/test/java/me/zhengjie/LoginCacheTest.java +++ b/eladmin-system/src/test/java/me/zhengjie/LoginCacheTest.java @@ -5,7 +5,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; + import javax.annotation.Resource; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -13,14 +17,19 @@ public class LoginCacheTest { @Resource(name = "userDetailsService") private UserDetailsServiceImpl userDetailsService; + ExecutorService executor = Executors.newCachedThreadPool(); @Test - public void testCache() { + public void testCache() throws InterruptedException { long start1 = System.currentTimeMillis(); - int size = 10000; + int size = 1000; + CountDownLatch latch = new CountDownLatch(size); for (int i = 0; i < size; i++) { - userDetailsService.loadUserByUsername("admin"); + executor.submit(() -> userDetailsService.loadUserByUsername("admin")); + latch.countDown(); } + latch.await(); + long end1 = System.currentTimeMillis(); //关闭缓存 userDetailsService.setEnableCache(false); @@ -31,4 +40,5 @@ public class LoginCacheTest { long end2 = System.currentTimeMillis(); System.out.print("使用缓存:" + (end1 - start1) + "毫秒\n 不使用缓存:" + (end2 - start2) + "毫秒"); } + }