- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个简单的应用程序,它将公开一个名为 'getAllDeviceData'
的 RESTFul GET 端点,它将简单地返回从数据库中的设备表中获取的所有设备数据的列表。
对于每个请求,我都会通过验证 HttpServletRequest.getUserPrincipal()
方法来验证用户身份。为了加速这个过程,我使用了带有 lambda 表达式的并行流。
在 ParallelStream 中,我调用另一个名为 'getDeviceData'
的方法,在其中进行身份验证并从数据库获取数据。
问题是,当并行流进程调用 getDeviceDat
方法时,我收到 NullPointer 异常,并且无法完成并行流。
原因是,HttpServletRequest.getUserPrincipal()
在方法内为 null。但它实际上存在于 'getAllDeviceData'
中(lambda 表达式所在的位置)。
如果我将 'parallelStream()'
替换为 'stream()'
,则不会出现任何问题,但在这种情况下,并行性质不存在。
@Override
@ResponseBody
@RequestMapping(value = "getAllDeviceData", method = RequestMethod.GET, consumes = "*")
public List<List<Data>> getAllDeviceData(
@RequestParam(value = "recordLimit", required = false) final Integer recordLimit,
final HttpServletRequest request) {
final List<Device> deviceList = deviceService.getAllDevices();
final List<List<Data>> dataList = deviceList.parallelStream().map(device -> getDeviceData(recordLimit, device.getDeviceId(), request)).collect(Collectors.toList());
return alerts;
}
private List<Data> getDeviceData(@RequestParam(value = "recordLimit", required = false) Integer recordLimit, String deviceId, HttpServletRequest request) {
if(request.getUserPrincipal() == null){
logger.info("User Principle Null - 1");
}else {
logger.info("User Principle Not Null - 1");
}
authService.doAuthenticate(request);
// if authrnticated proceed with following...
List<Data> deviceData = deviceService.getGetDeviceData(deviceId);
return deviceData;
}
但是,我观察到了一些事情。
查看上述应用程序的以下日志(不需要的部分已被省略)。
其中,主线程(例如:http-nio-7070-exec-2
等 - 这是该应用程序服务器线程池的主线程)工作正常,因为它打印出 '用户原则不为空 - 1',但是,在并行流的分解线程中,例如 ForkJoinPool.commonPool-worker-2
等。HTTPServletRequest.getUserPrincipal()
正在变为 null。
2018-01-15 15:28:06,897 INFO [http-nio-7070-exec-2] User Principle Not Null - 1
2018-01-15 15:28:06,897 INFO [ForkJoinPool.commonPool-worker-2] User Principle Null - 1
2018-01-15 15:28:06,906 INFO [ForkJoinPool.commonPool-worker-3] User Principle Null - 1
2018-01-15 15:28:06,955 INFO [ForkJoinPool.commonPool-worker-2] User Principle Null - 1
2018-01-15 15:28:06,955 INFO [ForkJoinPool.commonPool-worker-1] User Principle Null - 1
2018-01-15 15:28:06,957 INFO [ForkJoinPool.commonPool-worker-2] User Principle Null - 1
2018-01-15 15:28:06,959 INFO [ForkJoinPool.commonPool-worker-3] User Principle Null - 1
2018-01-15 15:28:07,064 INFO [ForkJoinPool.commonPool-worker-2] User Principle Null - 1
2018-01-15 15:28:07,076 INFO [http-nio-7070-exec-2] User Principle Not Null -1
2018-01-15 15:28:07,078 INFO [ForkJoinPool.commonPool-worker-1] User Principle Null - 1
我对 lambda 表达式和并行流还很陌生。请帮助我了解这里的问题是什么。
Java 详细信息:
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
最佳答案
根本原因是 Spring 将 SecurityContextHolderAwareRequestWrapper 实例注入(inject)到您的方法中。当调用 equest.getUserPrincipal()
时,此包装器将调用以下几行:
private Authentication getAuthentication() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
SecurityContextHolder有不同的策略。默认情况下使用MODE_THREADLOCAL
策略。这就是为什么你在主线程中有用户原则,但在 forkjoinpool 线程中没有用户原则。
-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
VM选项可以解决您的问题。 InheritableThreadLocal javadoc 和 InheritableThreadLocalSecurityContextHolderStrategy 源代码可能会给理解带来额外的值(value)。
关于java - 在 Java 8 中将 HttpServletRequest 与 ParallelStream 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48273368/
这个问题已经有答案了: How do I write a correct micro-benchmark in Java? (11 个回答) 已关闭 5 年前。 我正在对 Java 聚合操作进行一些性
我发现我对并行流提供的一致性保证略有挣扎: 1. myList.parallelStream().map(mymapper).forEach(myFn) 2. // Is myFn guarantee
我有一个方法可以并行计算列表中数字的平方并将它们相加: public static double sumSquared(List values) { return values
这个问题已经有答案了: How do Java 8 parallel streams behave on a thrown exception? (1 个回答) 已关闭 4 年前。 我正在研究java
通常当使用 Java 8 的 parallelStream() 时,结果是通过默认的、通用的 fork-join 池(即 ForkJoinPool.commonPool())执行。 这显然是不可取的,
Java 8 parallelStream 似乎使用了比系统属性 java.util.concurrent.ForkJoinPool.common.parallelism 指定的线程更多的线程。这些单
我有以下代码,有时它的行为不确定。例如,我在那里传递了 3 个事件,而输出只有两个!你能解释一下这种行为的原因吗? public List getEventResponse(final List ev
Java8并行流(parallelStream)注意点 在最初使用并行流的时候,查询列表会偶尔性报空指针异常,这令我非常纳闷 代码是这样的: ?
使用示例可能更容易解释我想要做的事情。假设我必须遵循两个数组: int firstArray[] = {1, 2, 3, 4, 5}; int secArray[] = {1, 2, 3, 4, 5}
我正在尝试使用 chronicleMap.parallelStream: myChronicleMap.entrySet().parallelStream().forEach((entry) -> {
我正在使用parallelStream并行上传一些文件,有些是大文件,有些是小文件。我注意到并非所有 worker 都被使用。 一开始一切都运行良好,所有线程都被使用(我将并行度选项设置为 16)。然
这个问题在这里已经有了答案: How can I turn a List of Lists into a List in Java 8? (12 个答案) 关闭 8 年前。 我想将并行流中的列表结果
我有以下代码 public void addNames(){ List names = new ArrayList names.parallelStream().foreach(name-
如果输入大小太小,库 automatically serializes the execution of the maps in the stream ,但这种自动化没有也不能考虑 map 操作的繁重
我创建了一个并行度为 25 的自定义 ForkJoinPool。 customForkJoinPool = new ForkJoinPool(25); 我有一个包含 700 个文件名的列表,我使用这样
我在 Internet 上看到了很多示例,为了使用流 API 来执行并行操作,只需像这样调用 .parallelStream() 方法: mySet .parallelStream()
考虑这个(完全人为的)Java 代码: final List s = Arrays.asList(1, 2, 3); final int[] a = new int[1]; a[0] = 100; s
谁能告诉我为什么会这样,这是预期的行为还是错误 List a = Arrays.asList(1,1,3,3); a.parallelStream().filter(Objects::nonNull)
方法一 通常,非常快,并且效果很好。 public static int loops = 500; private static ExecutorService customPool = Execut
默认情况下,parallelStream 内的 commonPool 大小应为 cpu_cores - 1。 但是,在我的应用程序中,它始终大于硬件 cpu_cores。 VisualVM 截图: 很
我是一名优秀的程序员,十分优秀!