xml <dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.23</version>
</dependency>
java//单页pdf
public static String pdfToImage(String pdfBase64) throws IOException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(pdfBase64));
PDDocument document = PDDocument.load(inputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PDFRenderer renderer = new PDFRenderer(document);
for(int i = 0; i < document.getNumberOfPages(); i++) {
BufferedImage image = renderer.renderImageWithDPI(i, 300);
ImageIO.write(image, "png", outputStream);
}
byte[] imageBytes = outputStream.toByteArray();
String imageBase64 = Base64.getEncoder().encodeToString(imageBytes);
document.close();
return imageBase64;
}
java//多页pdf
public static String[] pdfToImages(String pdfBase64) throws IOException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(pdfBase64));
PDDocument document = PDDocument.load(inputStream);
String imageBase64[] = new String[document.getNumberOfPages()];
for(int i = 0; i < document.getNumberOfPages(); i++) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PDFRenderer renderer = new PDFRenderer(document);
BufferedImage image = renderer.renderImageWithDPI(i, 300);
ImageIO.write(image, "png", outputStream);
byte[] imageBytes = outputStream.toByteArray();
imageBase64[i] = Base64.getEncoder().encodeToString(imageBytes);
}
document.close();
return imageBase64;
}
java//多线程的方式
public static String[] pdfToImagesByMultiThreading(String pdfBase64) throws IOException, ExecutionException, InterruptedException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(pdfBase64));
PDDocument document = PDDocument.load(inputStream);
int pages = document.getNumberOfPages();
int core=Runtime.getRuntime().availableProcessors();
// 创建一个固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(core>pages?pages:core);
List<CompletableFuture<String>> futures = new ArrayList<>();
for (int i = 0; i < pages; i++) {
final int pageIndex = i;
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PDFRenderer renderer = new PDFRenderer(document);
try {
BufferedImage image = renderer.renderImageWithDPI(pageIndex, 300);
ImageIO.write(image, "jpg", outputStream);
} catch (IOException e) {
e.printStackTrace();
throw new BusinessException(ResultCodeEnum.ERR_0x1000.getCode(),"pdf转换出错"+e.getMessage());
}
byte[] imageBytes = outputStream.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
}, executorService);
futures.add(future);
}
// 等待所有任务完成并收集结果
CompletableFuture<String>[] arrayFutures = futures.toArray(new CompletableFuture[0]);
CompletableFuture.allOf(arrayFutures).join(); // 等待所有任务完成
// 关闭线程池(在实际应用中考虑在服务停止时关闭)
executorService.shutdown();
document.close();
// 等待所有任务完成并收集结果
String[] imageBase64 = new String[pages];
for (int i = 0; i < pages; i++) {
imageBase64[i] = futures.get(i).get();
}
return imageBase64;
}
在JDK1.7中引入了一种新的Fork/Join线程池,它可以将一个大的任务拆分成多个小的任务并行执行并汇总执行结果。 Fork/Join采用的是分而治之的基本思想,分而治之就是将一个复杂的任务,按照规定的阈值划分成多个简单的小任务,然后将这些小任务的结果再进行汇总返回,得到最终的任务。
ForkJoinPool是用于运行ForkJoinTasks的线程池,实现了Executor接口。 可以通过new ForkJoinPool()直接创建ForkJoinPool对象。
javapublic ForkJoinPool() {
this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
defaultForkJoinWorkerThreadFactory, null, false);
}
public ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
boolean asyncMode){
this(checkParallelism(parallelism),
checkFactory(factory),
handler,
asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
"ForkJoinPool-" + nextPoolId() + "-worker-");
checkPermission();
}
通过查看构造方法源码我们可以发现,在创建ForkJoinPool时,有以下4个参数:
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。 默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
使用redis集群时,从机在redis.windows.conf中修改port为6380,启动后还是使用的是6379,导致窗口闪退,启动失败
未读取到redis.windows.conf中的信息,还是使用的是默认的配置信息
进入redis目录下,打开命令行输入:
redis-server.exe ./redis.windows.conf
即可启动成功
Zuul 是 Netflix 提供的一个基于 JVM 的网关服务,其主要作用是将所有请求转发到相应的后端服务。Zuul 主要有以下几个特点:
在Zuul的组件中,主要由以下几个部分组成:
核心模块:包含了Zuul的核心代码,负责接收和处理外部请求,并进行路由、过滤等操作。其中,核心模块还包含了Zuul的主要配置类和启动类,用于对整个系统进行配置和启动。
路由模块:负责请求的路由功能,可以根据不同的路径或请求头信息对请求进行分发,并将请求发送到后端对应的服务实例中。
过滤器模块:提供了基于拦截器的过滤功能,可以对请求进行鉴权、限流、重试等操作,并对响应进行处理和转换。
发现模块:用于注册和发现后端服务实例,可以通过各种服务发现机制(如Eureka、Consul等)实现服务的自动发现和负载均衡。
监控模块:提供了一系列的监控指标和报告,可以帮助用户对系统进行实时监控和分析,以便及时发现和排查问题。