Java PDF Arrow Annotations - Hướng Dẫn Đầy Đủ & Thực Hành Tốt Nhất (2025)

Giới thiệu

Bạn đã bao giờ gặp khó khăn trong việc khiến đội ngũ của mình tập trung vào các phần cụ thể của tài liệu PDF trong quá trình đánh giá chưa? Bạn không phải là người duy nhất. Dù bạn đang quản lý tài liệu kỹ thuật, hợp đồng pháp lý, hay các thông số dự án, việc chỉ ra các khu vực cụ thể để thảo luận có thể gây bực bội nếu không có công cụ phù hợp.

Đây là giải pháp: Java PDF arrow annotations sử dụng GroupDocs.Annotation API. Cách tiếp cận mạnh mẽ này cho phép bạn lập trình add arrow to pdf các tệp, giúp việc cộng tác trở nên liền mạch và chuyên nghiệp. Bạn có thể nhận bản dùng thử qua trang giấy phép tạm thời của GroupDocs.

Câu trả lời nhanh

  • Thư viện nào cho phép tôi add arrow to pdf trong Java? GroupDocs.Annotation for Java.
  • Tôi có cần giấy phép cho môi trường sản xuất không? Có, giấy phép thương mại loại bỏ watermark và mở khóa toàn bộ tính năng. Xem GroupDocs pricing page để biết chi tiết.
  • Phiên bản Java nào được khuyến nghị? JDK 11 cung cấp hiệu năng tốt nhất và hỗ trợ lâu dài.
  • Tôi có thể thêm nhiều mũi tên trong một tài liệu không? Chắc chắn – chỉ cần tạo nhiều đối tượng ArrowAnnotation và thêm chúng vào cùng một Annotator.
  • Xử lý hàng loạt có được hỗ trợ không? Có, bạn có thể lặp qua các tài liệu và tái sử dụng cùng một thể hiện Annotator sau khi giải phóng đúng cách.

add arrow to pdf là gì?

Hoạt động add arrow to pdf vẽ một dấu chỉ hướng trên một trang PDF để làm nổi bật hoặc chỉ vào một vùng cụ thể. Các arrow annotation được lưu dưới dạng đối tượng PDF, vì vậy chúng vẫn hiển thị trong bất kỳ trình xem nào tuân thủ tiêu chuẩn và có thể được chỉnh sửa hoặc trả lời sau này.

Tại sao chọn GroupDocs.Annotation cho Java PDF arrow annotations?

GroupDocs.Annotation cung cấp một bộ phong phú các loại annotation, hỗ trợ cấp doanh nghiệp và một Java API đơn giản giúp giảm mã lặp lại. So với các giải pháp thay thế, nó xử lý hơn 50 định dạng đầu vào và đầu ra và có thể xử lý PDF 500 trang với dưới 200 MB bộ nhớ heap, nhờ kiến trúc streaming.

Yêu cầu trước - những gì bạn thực sự cần

Thư viện và phụ thuộc cần thiết

Đầu tiên, thêm phụ thuộc Maven của GroupDocs.Annotation. Đoạn mã dưới đây phản ánh các tọa độ chính xác bạn cần; thay thế placeholder phiên bản bằng bản phát hành ổn định mới nhất.

<repositories>
   <repository>
      <id>repository.groupdocs.com</id>
      <name>GroupDocs Repository</name>
      <url>https://releases.groupdocs.com/annotation/java/</url>
   </repository>
</repositories>
<dependencies>
   <dependency>
      <groupId>com.groupdocs</groupId>
      <artifactId>groupdocs-annotation</artifactId>
      <version>25.2</version>
   </dependency>
</dependencies>

Mẹo chuyên nghiệp: Kiểm tra trang phát hành của GroupDocs để biết số phiên bản mới nhất. Các bản phát hành mới thường bao gồm các bản vá hiệu năng và các kiểu annotation bổ sung.

Cài đặt môi trường không gây rắc rối

  • JDK 8 hoặc mới hơn – JDK 11 được khuyến nghị vì bộ thu gom rác cải tiến và hệ thống module.
  • Maven 3.6+ – các phiên bản Maven cũ hơn có thể gặp khó khăn với các phụ thuộc truyền tải.
  • IDE – IntelliJ IDEA hoặc Eclipse cung cấp trải nghiệm gỡ lỗi tốt nhất cho các thư viện Java.
  • Memory – Phân bổ ít nhất 2 GB heap khi làm việc với PDF lớn hơn 100 trang.

Kiến thức nền (hãy trung thực với bản thân)

Bạn nên thoải mái với:

  • Các collection cơ bản của Java và xử lý ngoại lệ.
  • Quản lý phụ thuộc Maven.
  • I/O tệp cơ bản (đọc và ghi luồng nhị phân).

Nếu bất kỳ lĩnh vực nào trên cảm thấy chưa vững, hãy xem xét một buổi ôn nhanh trước khi bắt đầu viết mã annotation.

Cài đặt GroupDocs.Annotation - cách đúng

Bước 1: Cấu hình Maven (kèm khắc phục lỗi)

Thêm repository và phụ thuộc đã hiển thị ở trên. Nếu Maven không thể giải quyết artifact, hãy chắc chắn rằng bạn đã định nghĩa repository công cộng của GroupDocs trong pom.xml của mình:

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

Bước 2: Cấu hình giấy phép (quan trọng cho môi trường sản xuất)

Đối với phát triển, bạn có thể sử dụng giấy phép dùng thử tạm thời:

// For evaluation purposes
License license = new License();
// license.setLicense("path/to/license.lic"); // Comment this out for trial

Kiểm tra thực tế: Bản dùng thử sẽ thêm watermark hiển thị vào mỗi PDF đã lưu. Giấy phép sản xuất sẽ loại bỏ watermark này và mở khóa toàn bộ tính năng annotation.

Bước 3: Mẫu khởi tạo cơ bản

Annotator là lớp chính để tải tài liệu PDF và áp dụng các annotation.
Luôn bao bọc Annotator trong khối try‑finally để các tài nguyên nền được giải phóng kịp thời:

Annotator annotator = null;
try {
    annotator = new Annotator("YOUR_DOCUMENT_DIRECTORY/input.pdf");
    // Your annotation code here
} finally {
    if (annotator != null) {
        annotator.dispose();
    }
}

Tại sao cần khối try‑finally? GroupDocs cấp phát bộ nhớ native cho việc phân tích PDF; nếu không giải phóng Annotator có thể gây rò rỉ bộ nhớ, đặc biệt khi xử lý nhiều tài liệu trong một công việc batch.

Hướng dẫn triển khai đầy đủ - từ đầu đến sản xuất

Hiểu về arrow annotation trong ngữ cảnh

Arrow annotation hoạt động như các chỉ dẫn trực quan trong quy trình đánh giá tài liệu. Các trường hợp sử dụng điển hình bao gồm:

  1. Phản hồi đánh giá – “Điều khoản này cần làm rõ.”
  2. Liên kết tham chiếu – “Xem sơ đồ ở trang 12.”
  3. Hướng dẫn quy trình – “Bắt đầu kiểm toán tại đây.”
  4. Nổi bật vấn đề – “Có thể có lỗi chính tả trong đoạn này.”

Thiết kế UI annotation dựa trên các kịch bản này giúp người dùng nhanh chóng tiếp nhận công cụ.

Bước 1: Xây dựng phản hồi annotation (cách thông minh)

Phản hồi biến một mũi tên tĩnh thành một điểm thảo luận tương tác. Lần đầu tiên bạn đề cập đến lớp Reply, hãy định nghĩa ngắn gọn:

Định nghĩa: Reply đại diện cho một bình luận văn bản đính kèm vào annotation, lưu thông tin tác giả và thời gian.

Reply reply1 = new Reply();
reply1.setComment("First comment");
reply1.setRepliedOn(Calendar.getInstance().getTime());

Reply reply2 = new Reply();
reply2.setComment("Second comment");
reply2.setRepliedOn(Calendar.getInstance().getTime());

List<Reply> replies = new ArrayList<>();
replies.add(reply1);
replies.add(reply2);

Mẹo: Lưu ID và vai trò của người dùng trong metadata của reply; điều này giúp dễ dàng lọc bình luận sau này.

Bước 2: Tạo arrow annotation (với các cân nhắc thực tế)

Định nghĩa: ArrowAnnotation là đối tượng của GroupDocs dùng để vẽ một mũi tên chỉ hướng trên một trang PDF.

ArrowAnnotation arrow = new ArrowAnnotation();
arrow.setBox(new Rectangle(100, 100, 100, 100)); // Position and size
arrow.setCreatedOn(Calendar.getInstance().getTime()); // Creation time
arrow.setMessage("This is an arrow annotation"); // Annotation message
arrow.setOpacity(0.7); // Opacity level
arrow.setPageNumber(0); // Page number
arrow.setPenColor(65535); // ARGB pen color
arrow.setPenStyle(PenStyle.DOT); // Pen style
arrow.setPenWidth((byte) 3); // Arrow line width
arrow.setReplies(replies); // Attach replies

Các tham số chính được giải thích:

  • Tọa độ hình chữ nhật – (x, y, width, height) trong đó (x, y) là góc trên‑trái của hộp bao.
  • PenColor – Sử dụng số nguyên ARGB; 65535 cho ra màu xanh sống động. Sử dụng công cụ chuyển đổi trực tuyến cho màu tùy chỉnh.
  • PenStyle – Các tùy chọn bao gồm DOT, DASH, SOLID, DASHDOT, DASHDOTDOT. Chọn SOLID cho hầu hết các trường hợp.
  • Opacity – Giá trị từ 0.0 (trong suốt) đến 1.0 (đục). Giá trị 0.7 cân bằng giữa khả năng nhìn thấy và độ đọc được của nội dung nền.

Bước 3: Thêm và lưu (kèm xử lý lỗi)

Định nghĩa: Annotator.save lưu lại tất cả các thay đổi annotation đang chờ vào tệp PDF đích.

try {
    annotator.add(arrow);
    annotator.save("YOUR_OUTPUT_DIRECTORY/output.pdf");
    System.out.println("Arrow annotation added successfully!");
} catch (Exception e) {
    System.err.println("Failed to add annotation: " + e.getMessage());
    // Log the full stack trace in production
    e.printStackTrace();
} finally {
    annotator.dispose();
}

Luôn bắt IOException và AnnotationException để xử lý các tệp hỏng, đường dẫn không hợp lệ hoặc vấn đề quyền truy cập. Ghi log stack trace giúp bạn chẩn đoán vấn đề trong môi trường sản xuất.

Những lỗi thường gặp và cách tránh chúng

Vấn đề 1: Tọa độ không khớp vị trí mong muốn

Vấn đề: Mũi tên xuất hiện lệch so với vị trí mong muốn.

Giải pháp: Gốc tọa độ PDF là góc dưới‑trái, trong khi GroupDocs mong đợi góc trên‑trái. Chuyển đổi tọa độ UI cho phù hợp, hoặc sử dụng hàm trợ giúp tích hợp convertToPdfCoordinates:

// If arrows appear in wrong positions, try adjusting the Y coordinate
int adjustedY = pageHeight - originalY - annotationHeight;
arrow.setBox(new Rectangle(x, adjustedY, width, height));

Vấn đề 2: Annotation biến mất sau khi lưu

Vấn đề: Mũi tên hiển thị trong quá trình xử lý nhưng không có trong PDF cuối cùng.

Giải pháp: Điều này hầu như luôn chỉ ra vấn đề giấy phép. Xác minh rằng tệp giấy phép đã được tải trước khi tạo bất kỳ thể hiện Annotator nào:

License license = new License();
try {
    license.setLicense("GroupDocs.Annotation.lic");
} catch (Exception e) {
    System.out.println("License not found, using trial mode");
}

Vấn đề 3: Rò rỉ bộ nhớ trong xử lý batch

Vấn đề: JVM hết bộ nhớ heap khi xử lý hàng chục PDF.

Giải pháp: Giải phóng mỗi Annotator sau khi hoàn thành tài liệu, và xử lý tệp theo các lô nhỏ để giữ việc sử dụng bộ nhớ dự đoán được:

for (String documentPath : documentPaths) {
    Annotator annotator = null;
    try {
        annotator = new Annotator(documentPath);
        // Process document
    } finally {
        if (annotator != null) {
            annotator.dispose();
        }
    }
    
    // Force garbage collection every 10 documents
    if (processedCount % 10 == 0) {
        System.gc();
    }
}

Kỹ thuật tùy chỉnh nâng cao

Định vị mũi tên động

Khi mũi tên cần theo các cú nhấp của người dùng trong UI web, tính toán hình chữ nhật phía client và gửi tọa độ tới backend. Backend sau đó có thể tạo một ArrowAnnotation với các giá trị đó.

public ArrowAnnotation createArrowAt(int x, int y, String message) {
    ArrowAnnotation arrow = new ArrowAnnotation();
    
    // Create arrow pointing to specific coordinates
    int arrowLength = 50;
    arrow.setBox(new Rectangle(x - arrowLength, y - arrowLength, arrowLength, arrowLength));
    arrow.setMessage(message);
    arrow.setOpacity(0.8);
    arrow.setPenColor(0xFF0000); // Red color
    arrow.setPenStyle(PenStyle.SOLID);
    arrow.setPenWidth((byte) 2);
    
    return arrow;
}

Định dạng mũi tên cho các trường hợp sử dụng khác nhau

Bạn có thể thay đổi PenColor và PenStyle để truyền tải ý nghĩa—ví dụ, mũi tên đỏ đứt nét cho các vấn đề quan trọng, mũi tên xanh lá đậm cho các phần đã được phê duyệt.

// Error highlighting (red, thick, solid)
public ArrowAnnotation createErrorArrow() {
    ArrowAnnotation arrow = new ArrowAnnotation();
    arrow.setPenColor(0xFF0000); // Red
    arrow.setPenWidth((byte) 4);
    arrow.setPenStyle(PenStyle.SOLID);
    arrow.setOpacity(0.9);
    return arrow;
}

// Suggestion arrows (blue, thin, dashed)
public ArrowAnnotation createSuggestionArrow() {
    ArrowAnnotation arrow = new ArrowAnnotation();
    arrow.setPenColor(0x0000FF); // Blue
    arrow.setPenWidth((byte) 2);
    arrow.setPenStyle(PenStyle.DASH);
    arrow.setOpacity(0.6);
    return arrow;
}

Các kịch bản triển khai thực tế

Kịch bản 1: Hệ thống đánh giá tài liệu

Trong một cổng đánh giá đa người dùng, mỗi người đánh giá tạo một ArrowAnnotation và đính kèm một Reply. Hệ thống lưu trữ các reply trong cơ sở dữ liệu quan hệ, cho phép thảo luận dạng chuỗi trên mỗi annotation.

public class DocumentReviewSystem {
    public void addReviewArrow(String documentPath, int x, int y, 
                              String reviewComment, String reviewerName) {
        Annotator annotator = new Annotator(documentPath);
        
        ArrowAnnotation arrow = new ArrowAnnotation();
        arrow.setBox(new Rectangle(x, y, 50, 50));
        arrow.setMessage("Review by " + reviewerName);
        
        // Add reviewer's comment as reply
        Reply review = new Reply();
        review.setComment(reviewComment);
        review.setUser(new User(reviewerName));
        review.setRepliedOn(new Date());
        
        arrow.setReplies(Arrays.asList(review));
        
        annotator.add(arrow);
        annotator.save(documentPath.replace(".pdf", "_reviewed.pdf"));
        annotator.dispose();
    }
}

Kịch bản 2: Phát hiện vấn đề tự động

Một engine phân tích quét PDF để tìm vi phạm tuân thủ và tự động chèn mũi tên đỏ chỉ vào các điều khoản có vấn đề.

public void highlightDetectedIssues(String documentPath, List<Issue> issues) {
    Annotator annotator = new Annotator(documentPath);
    
    for (Issue issue : issues) {
        ArrowAnnotation arrow = createArrowForIssue(issue);
        annotator.add(arrow);
    }
    
    annotator.save(documentPath.replace(".pdf", "_issues_highlighted.pdf"));
    annotator.dispose();
}

private ArrowAnnotation createArrowForIssue(Issue issue) {
    ArrowAnnotation arrow = new ArrowAnnotation();
    arrow.setBox(new Rectangle(issue.getX(), issue.getY(), 40, 40));
    arrow.setMessage("Issue detected: " + issue.getType());
    
    // Color‑code by severity
    switch (issue.getSeverity()) {
        case HIGH:
            arrow.setPenColor(0xFF0000); // Red
            break;
        case MEDIUM:
            arrow.setPenColor(0xFFA500); // Orange
            break;
        case LOW:
            arrow.setPenColor(0xFFFF00); // Yellow
            break;
    }
    
    return arrow;
}

Mẹo tối ưu hiệu năng

Thực hành tốt quản lý bộ nhớ

  1. Sử dụng try‑with‑resources (Java 7+) để tự động đóng các đối tượng Annotator:

try (Annotator annotator = new Annotator(“document.pdf”)) { // Your annotation code } // Automatically disposed


2. **Xử lý từng trang riêng lẻ** thay vì tải toàn bộ tài liệu vào bộ nhớ.  
3. **Giám sát việc sử dụng heap** bằng các công cụ như VisualVM hoặc JConsole trong các lần chạy batch quy mô lớn.

### Các cân nhắc về hiệu năng CPU

- Tái sử dụng một thể hiện `Color` duy nhất cho tất cả các mũi tên để tránh việc cấp phát đối tượng không cần thiết.  
- Tránh các vòng lặp lồng nhau tạo ra các đối tượng `PenStyle` giống nhau liên tục.  
- Nếu bạn có nhiều PDF độc lập, hãy xem xét sử dụng thread pool, nhưng giới hạn số lượng `Annotator` đồng thời để kiểm soát mức tiêu thụ bộ nhớ.

## Hướng dẫn khắc phục – giải pháp cho các vấn đề thực tế

### Vấn đề: Annotation không hiển thị trong Adobe Reader

**Triệu chứng**: Mũi tên xuất hiện trong trình xem tùy chỉnh của bạn nhưng không trong Adobe Acrobat.

**Giải pháp**:

1. Lưu PDF với chuẩn PDF/A‑1b để đảm bảo khả năng tương thích tối đa với các trình xem:

   ```java
// Try different save options if available
SaveOptions saveOptions = new SaveOptions();
saveOptions.setAnnotationType(AnnotationType.All);
annotator.save(outputPath, saveOptions);
  1. Kiểm tra phiên bản PDF ít nhất là 1.7; các phiên bản cũ hơn có thể loại bỏ các loại annotation mới.

Vấn đề: Hiệu năng kém với PDF lớn

Triệu chứng: Ứng dụng bị treo hoặc không phản hồi khi xử lý PDF trên 200 trang.

Giải pháp:

  1. Xử lý từng trang riêng lẻ thay vì tải toàn bộ tệp:

// Process specific pages LoadOptions loadOptions = new LoadOptions(); loadOptions.setLoadCharts(false); // Skip charts if not needed Annotator annotator = new Annotator(documentPath, loadOptions);


2. **Kích hoạt streaming** trong hàm khởi tạo `Annotator` nếu phiên bản của bạn hỗ trợ.  
3. Tăng bộ nhớ heap của JVM (`-Xmx4g`) cho các tài liệu rất lớn.

### Vấn đề: Vấn đề hiển thị màu

**Triệu chứng**: Mũi tên xuất hiện màu xám hoặc hoàn toàn trong suốt.

**Giải pháp**: Định nghĩa màu bằng định dạng ARGB và đảm bảo không gian màu của PDF được đặt thành **DeviceRGB**:

```java
// Use hex values for consistent colors
int red = 0xFFFF0000;    // ARGB format
int blue = 0xFF0000FF;
int green = 0xFF00FF00;

// Or convert from RGB
public int rgbToArgb(int r, int g, int b) {
    return (0xFF << 24) | (r << 16) | (g << 8) | b;
}

Kiểm thử triển khai của bạn

Kiểm thử đơn vị arrow annotation

Một bài kiểm thử đơn vị vững chắc tải một PDF mẫu, thêm một ArrowAnnotation, lưu tệp, và sau đó mở lại để xác minh số lượng và thuộc tính của annotation:

@Test
public void testArrowAnnotationCreation() {
    // Arrange
    String inputPath = "test-documents/sample.pdf";
    String outputPath = "test-output/annotated.pdf";
    
    // Act
    Annotator annotator = new Annotator(inputPath);
    ArrowAnnotation arrow = new ArrowAnnotation();
    arrow.setBox(new Rectangle(100, 100, 50, 50));
    arrow.setMessage("Test annotation");
    
    annotator.add(arrow);
    annotator.save(outputPath);
    annotator.dispose();
    
    // Assert
    assertTrue("Output file should exist", new File(outputPath).exists());
    
    // Verify annotation was added
    Annotator verifyAnnotator = new Annotator(outputPath);
    List<AnnotationInfo> annotations = verifyAnnotator.get();
    assertEquals("Should have one annotation", 1, annotations.size());
    verifyAnnotator.dispose();
}

Kiểm thử tích hợp

Chạy cùng bộ kiểm thử đối với các PDF có kích thước khác nhau (10 trang, 100 trang, 500 trang) và trên các trình xem khác nhau (Adobe Reader, Foxit, Chrome) để đảm bảo việc render nhất quán.

Kết luận

Bạn giờ đã có một bộ công cụ hoàn chỉnh để triển khai Java PDF arrow annotations sử dụng GroupDocs.Annotation. Hãy nhớ:

  • Giải phóng các đối tượng Annotator kịp thời.
  • Kiểm thử với các phiên bản và kích thước PDF đa dạng.
  • Áp dụng các mẹo hiệu năng khi mở rộng lên các công việc batch.
  • Định dạng mũi tên sao cho phù hợp với ý nghĩa ngữ nghĩa của mỗi bình luận.

Bước tiếp theo: khám phá các loại annotation khác như TextAnnotation, AreaAnnotation, và WatermarkAnnotation. Các mẫu khởi tạo và giải phóng tương tự áp dụng, cho phép bạn xây dựng một nền tảng cộng tác tài liệu đầy đủ tính năng.

Câu hỏi thường gặp

Q: Tôi có thể thêm arrow annotation vào PDF được bảo vệ bằng mật khẩu không?
A: Có, cung cấp mật khẩu khi tạo thể hiện Annotator:

LoadOptions loadOptions = new LoadOptions();
loadOptions.setPassword("your-password");
Annotator annotator = new Annotator("protected.pdf", loadOptions);

Q: Làm thế nào để xử lý hàng loạt nhiều tài liệu một cách hiệu quả?
A: Xử lý tài liệu theo các lô nhỏ, tái sử dụng một Annotator cho mỗi tệp, và gọi dispose() sau mỗi lần lưu:

for (String doc : documents) {
    try (Annotator annotator = new Annotator(doc)) {
        // Add annotations
        annotator.save(doc.replace(".pdf", "_annotated.pdf"));
    }
    if (processedCount % 10 == 0) {
        System.gc(); // Encourage garbage collection
    }
}

Q: Số lượng annotation tối đa cho mỗi tài liệu là bao nhiêu?
A: GroupDocs không đặt giới hạn cứng, nhưng hiệu năng thực tế giảm sau khoảng 1.000 annotation trên PDF 500 trang nếu bạn không áp dụng các kỹ thuật quản lý bộ nhớ đã mô tả ở trên.

Q: Tôi có thể tùy chỉnh hình dạng mũi tên vượt quá các tùy chọn tiêu chuẩn không?
A: Thư viện cung cấp các đầu mũi tên tiêu chuẩn. Để có hình dạng tùy chỉnh hoàn toàn, bạn có thể kết hợp nhiều đối tượng AreaAnnotation hoặc chuyển sang thư viện tập trung vào đồ họa hỗ trợ đường vector.

Q: Làm thế nào để xử lý các hệ tọa độ PDF khác nhau?
A: GroupDocs tự động chuyển đổi giữa tọa độ UI góc trên‑trái và tọa độ PDF góc dưới‑trái. Nếu bạn gặp sự không khớp, hãy kiểm tra lại rằng bạn không áp dụng một lớp chuyển đổi bổ sung ở phía client.

// Get page info for coordinate calculations
PageInfo pageInfo = annotator.getDocument().getPages().get(pageNumber);
int pageHeight = pageInfo.getHeight();

// Adjust Y coordinate if needed
int adjustedY = pageHeight - originalY;

Q: Chi phí giấy phép cho môi trường sản xuất là bao nhiêu?
A: GroupDocs cung cấp các giấy phép Developer, Site và OEM. Giá bắt đầu từ $699 cho mỗi ghế lập trình viên mỗi năm. Tham khảo trang giá của GroupDocs để biết số liệu mới nhất.

Q: Làm thế nào để tích hợp điều này với các ứng dụng Spring Boot?
A: Tạo một bean @Service bao gói logic annotation, tiêm nó vào các controller của bạn, và mở một endpoint REST nhận luồng PDF và trả về PDF đã được annotation.

@Service
public class AnnotationService {
    public void addArrowAnnotation(String inputPath, String outputPath, 
                                 int x, int y, String message) {
        try (Annotator annotator = new Annotator(inputPath)) {
            ArrowAnnotation arrow = new ArrowAnnotation();
            arrow.setBox(new Rectangle(x, y, 50, 50));
            arrow.setMessage(message);
            
            annotator.add(arrow);
            annotator.save(outputPath);
        }
    }
}

Q: Tôi có thể trích xuất các arrow annotation hiện có từ PDF không?
A: Có, gọi phương thức getAnnotations() trên một thể hiện Annotator và lọc kết quả theo AnnotationType.Arrow.

Annotator annotator = new Annotator("document.pdf");
List<AnnotationInfo> annotations = annotator.get();

for (AnnotationInfo annotation : annotations) {
    if (annotation instanceof ArrowAnnotation) {
        ArrowAnnotation arrow = (ArrowAnnotation) annotation;
        System.out.println("Arrow message: " + arrow.getMessage());
    }
}

Tài nguyên bổ sung


Cập nhật lần cuối: 2026-08-14
Kiểm tra với: GroupDocs.Annotation 25.2 for Java
Tác giả: GroupDocs

public void processBatch(List<String> documents, int batchSize) {
    for (int i = 0; i < documents.size(); i += batchSize) {
        List<String> batch = documents.subList(i, 
            Math.min(i + batchSize, documents.size()));
        
        processBatchInternal(batch);
        
        // Allow GC between batches
        System.gc();
        Thread.sleep(100);
    }
}
Runtime runtime = Runtime.getRuntime();
long memoryBefore = runtime.totalMemory() - runtime.freeMemory();

// Your annotation processing

long memoryAfter = runtime.totalMemory() - runtime.freeMemory();
System.out.println("Memory used: " + (memoryAfter - memoryBefore) + " bytes");
java -Xmx4g -jar your-application.jar

Hướng dẫn liên quan