Giới thiệu dự án

Sự chuyển dịch mạnh mẽ từ báo in truyền thống sang các nền tảng báo điện tử trực tuyến là xu thế tất yếu trong kỷ nguyên số. Thống kê từ Hiệp hội Báo chí Thế giới và dữ liệu ngành truyền thông cho thấy, hơn 65% độc giả toàn cầu tiếp cận tin tức qua nền tảng số, kéo theo sự sụt giảm hơn 50% doanh thu phát hành của báo in truyền thống. Tại Việt Nam, với hơn 77 tờ báo điện tử và hàng trăm trang thông tin tổng hợp, nhu cầu về một hệ thống quản trị và phân phối tin tức tốc độ cao, khả năng chịu tải lớn và tự động hóa cập nhật dữ liệu là vô cùng cấp thiết.

Hầu hết các hệ thống tòa soạn và trang tin điện tử truyền thống xây dựng trên kiến trúc nguyên khối (Monolithic) gặp phải các điểm nghẽn nghiêm trọng (bottlenecks):

  • Khó mở rộng độc lập từng phân hệ khi lưu lượng đọc bài tăng đột biến (traffic spikes).
  • Quy trình tổng hợp tin tức tự động từ các nguồn bên ngoài (RSS feeds) gây nghẽn tài nguyên của luồng xử lý giao diện người dùng.
  • Quản trị phân quyền người dùng và kiểm duyệt nội dung thiếu tính linh hoạt và an toàn dữ liệu.

Đồ án "Tìm hiểu Spring, Microservices và xây dựng hệ thống website tin tức trực tuyến" (thực hiện bởi sinh viên Nguyễn Hoàng Long & Bùi Xuân Trí, hướng dẫn bởi ThS. Nguyễn Minh Đạo - Trường Đại học Sư phạm Kỹ thuật TP.HCM) giải quyết trực tiếp các bài toán trên thông qua việc ứng dụng kiến trúc Microservices kết hợp với nền tảng Spring Boot và Single Page Application (SPA) Angular 5.

+-------------------------------------------------------------------------+
|                           MỤC TIÊU DỰ ÁN                                |
+-------------------------------------------------------------------------+
| 1. Xây dựng kiến trúc Microservices phân tán với API Gateway.          |
| 2. Tách biệt Frontend SPA (Angular 5) và Backend RESTful APIs.          |
| 3. Hiện thực cơ chế thu thập dữ liệu tự động (Dynamic RSS Crawling).     |
| 4. Xây dựng hệ thống bảo mật Role-Based Access Control (Spring Security)|
| 5. Thiết kế CSDL quan hệ chuẩn hóa cao trên PostgreSQL/Hibernate ORM.   |
+-------------------------------------------------------------------------+

Hệ thống hướng tới các chỉ số hiệu năng cụ thể: thời gian phản hồi API trung bình dưới 150ms, khả năng xử lý đồng thời 500+ requests/giây, và khả năng tự động cào tin từ nhiều nguồn RSS với độ chính xác cấu trúc dữ liệu đạt 99.5%. Phạm vi dự án tập trung vào nghiệp vụ quản trị tòa soạn, phân quyền đa cấp bậc (Admin, Staff, Member, Guest), công cụ kiểm duyệt tin tức và crawler dữ liệu động.


Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Khảo sát các giải pháp xuất bản và tổng hợp tin tức hiện nay cho thấy sự phân hóa rõ rệt giữa các mô hình kiến trúc:

Tiêu chí Monolithic CMS (WordPress / Drupal) Custom Monolith (Java EE / EJB) Microservices (Spring Boot + Angular 5)
Khả năng mở rộng (Scalability) Kém, phải nhân bản toàn bộ hệ thống Trung bình, phụ thuộc Application Server Rất cao, mở rộng linh hoạt từng service
Hiệu năng & Tối ưu tải Chậm khi dữ liệu lớn (>500ms) Nặng nề do mã nghi thức (ceremonial code) Tối ưu, tải không đồng bộ qua API Gateway (<150ms)
Tự động hóa RSS Crawling Phụ thuộc plugin, dễ xung đột Khó tích hợp tác vụ ngầm độc lập Service xử lý ngầm riêng biệt, không block UI
Tách biệt UI/UX Giao diện gắn chặt với Backend Tích hợp chặt với JSP/JSF Hoàn toàn độc lập qua RESTful API và Angular SPA
Bảo trì & Nâng cấp Rủi ro lỗi dây chuyền cao Quy trình build/deploy phức tạp, lâu Triển khai độc lập, kiểm thử tự động dễ dàng

Yêu cầu người dùng được lượng hóa theo mô hình MoSCoW:

  • Must have: Xác thực phân quyền (RBAC), xem tin theo danh mục, đọc chi tiết, thêm/sửa/xóa/duyệt tin tức, thu thập tin tức tự động qua cấu hình RSS URL động.
  • Should have: Tương tác like/unlike bài viết, thống kê bài viết theo chuyên mục, quản lý liên hệ người dùng, phân loại tin tức đa tầng.
  • Could have: Upload ảnh đại diện, tìm kiếm full-text nâng cao, quản lý trạng thái kích hoạt tài khoản.
  • Won't have (phiên bản hiện tại): Đề xuất tin tức tự động bằng AI Deep Learning, hỗ trợ thanh toán trả phí đọc tin (Paywall).

Thiết kế hệ thống

Kiến trúc hệ thống triển khai theo mô hình Microservices phân tầng kết hợp cổng kết nối API Gateway, đảm bảo tính đóng gói (encapsulation) và bảo mật tối đa cho các dịch vụ nội bộ:

[ Angular 5 Client (SPA - TypeScript / RxJS) ]
                       │ (HTTP/HTTPS REST Calls)
                       ▼
┌─────────────────────────────────────────────────────────┐
│              API Gateway (Zuul / Custom Router)         │
│  - Authentication Filter (Spring Security / JWT)        │
│  - Request Routing & Load Balancing                     │
│  - Rate Limiting & Protocol Translation                 │
└──────────────────────────┬──────────────────────────────┘
                           │
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
┌─────────────────┐┌─────────────────┐┌─────────────────┐
│  Auth & User    ││  News & Article ││  RSS Crawler    │
│  Microservice   ││  Microservice   ││  Microservice   │
│ (Spring Boot)   ││ (Spring Boot)   ││ (Spring Boot)   │
└────────┬────────┘└────────┬────────┘└────────┬────────┘
         │                  │                  │
         │ (Hibernate ORM)  │ (Hibernate ORM)  │ (Hibernate ORM)
         ▼                  ▼                  ▼
┌─────────────────────────────────────────────────────────┐
│         PostgreSQL Database (Isolated Schemas)          │
│   [users] [roles]   [news] [categories]   [rss_configs] │
└─────────────────────────────────────────────────────────┘

Technology Stack & Versions

  • Backend Framework: Spring Boot 2.1.x, Spring Security 5.x, Spring Data JPA / Hibernate 5.x.
  • Frontend Framework: Angular 5.2.x, TypeScript 2.5, RxJS 5.5, Bootstrap 4 / SCSS.
  • Database Management System: PostgreSQL 11.x.
  • Build & Dependency Tools: Maven 3.6, Angular CLI 1.7.x, JDK 8/11.
  • Testing & Benchmarking: JUnit 5, Mockito, Postman, Apache JMeter.

Database Schema & Relational Integrity

Cơ sở dữ liệu được chuẩn hóa đạt dạng chuẩn 3NF với các bảng cốt lõi:

  • users: user_id (PK, UUID/Serial), username (VARCHAR, Unique), password (VARCHAR, BCrypt), full_name, email, status (BOOLEAN).
  • roles: role_id (PK), role_name (VARCHAR, Unique), description.
  • user_roles: user_id (FK), role_id (FK) -> Quan hệ N-N giữa người dùng và quyền hạn.
  • categories: cat_id (PK), cat_name (VARCHAR), slug (VARCHAR), created_at, status.
  • news_items: item_id (PK), title (VARCHAR(500)), summary (TEXT), content (TEXT), image_url (VARCHAR), views_count (INT), likes_count (INT), status (TINYINT - 0: Draft, 1: Approved, 2: Rejected), cat_id (FK), created_by (FK).
  • rss_websites: web_id (PK), web_name (VARCHAR), base_url (VARCHAR), status.
  • rss_links: link_id (PK), web_id (FK), rss_url (VARCHAR), target_cat_id (FK), last_crawled_at.
-- Ràng buộc khóa ngoại và tính toàn vẹn dữ liệu
ALTER TABLE news_items 
ADD CONSTRAINT fk_news_category FOREIGN KEY (cat_id) REFERENCES categories(cat_id) ON DELETE RESTRICT;

ALTER TABLE user_roles 
ADD CONSTRAINT fk_ur_user FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
ADD CONSTRAINT fk_ur_role FOREIGN KEY (role_id) REFERENCES roles(role_id) ON DELETE CASCADE;

CREATE INDEX idx_news_status_cat ON news_items(status, cat_id);

Methodology

Dự án áp dụng phương pháp phát triển phần mềm lặp Agile/Scrum trong chu kỳ 15 tuần (từ 18/03/2019 đến 30/06/2019) với 5 mốc chính (milestones):

  1. Tuần 1 - 3 (Khảo sát & Thiết kế): Đặc tả Use Case, thiết kế kiến trúc Microservices, xây dựng Database ERD và mô hình Sequence Diagrams.
  2. Tuần 4 - 6 (Core API & UI Shell): Xây dựng Module Authentication, API Gateway, khung cấu trúc Angular NgModule và Routing.
  3. Tuần 7 - 9 (News & Category Management): Viết các API CRUD tin tức, danh mục, phân trang, lọc tin tức và tích hợp giao diện quản trị.
  4. Tuần 10 - 13 (Bảo mật & Dynamic RSS Engine): Tích hợp Spring Security (RBAC), xây dựng engine Crawling dữ liệu RSS và UI cấu hình URL nguồn.
  5. Tuần 14 - 15 (Kiểm thử, Tối ưu & Đóng gói): Kiểm thử hộp trắng (White-box testing), kiểm thử tích hợp (Integration testing), tối ưu hóa truy vấn SQL và viết báo cáo kỹ thuật.
+----------------------------------------------------------------------------+
|                       MA TRẬN QUẢN TRỊ RỦI RO                              |
+----------------------+------------+----------+-----------------------------+
| Rủi ro kỹ thuật      | Khả năng   | Mức độ   | Giải pháp giảm thiểu        |
+----------------------+------------+----------+-----------------------------+
| Xung đột schema RSS  | Cao        | Trung    | Chuẩn hóa qua Adapter       |
| từ các báo khác nhau |            | bình     | Pattern & Jsoup Parser      |
|                      |            |          |                             |
| Nghẽn kết nối DB khi | Trung bình | Cao      | Sử dụng HikariCP Connection |
| crawl dữ liệu ngầm   |            |          | Pool, chia nhỏ batch insert |
|                      |            |          |                             |
| Lỗ hổng Cross-Site   | Thấp       | Nghiêm   | Spring Security CSRF        |
| Scripting (XSS)      |            | trọng    | Token & Angular Sanitizer   |
+----------------------+------------+----------+-----------------------------+

Implementation và kết quả

Development process

Quá trình phát triển hệ thống tuân thủ chặt chẽ nguyên lý Clean Architecture và Design Patterns (Repository Pattern, DTO Pattern, Service Layer Pattern).

1. Xây dựng RESTful API với Spring Boot

Tầng điều khiển (Controller) tiếp nhận các request, thực hiện xác thực và điều phối dữ liệu qua tầng DTO và Service:

@RestController
@RequestMapping("/api/v1/news")
@CrossOrigin(origins = "*", maxAge = 3600)
public class NewsController {

    @Autowired
    private NewsService newsService;

    @GetMapping("/category/{catId}")
    public ResponseEntity<Page<NewsItemDTO>> getNewsByCategory(
            @PathVariable("catId") Long catId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
        Page<NewsItemDTO> results = newsService.findApprovedNewsByCategory(catId, pageable);
        return ResponseEntity.ok(results);
    }

    @PostMapping("/admin/create")
    @PreAuthorize("hasRole('STAFF') or hasRole('ADMIN')")
    public ResponseEntity<NewsItemDTO> createNews(@Valid @RequestBody NewsCreationRequest request) {
        NewsItemDTO createdItem = newsService.saveAndPublish(request);
        return new ResponseEntity<>(createdItem, HttpStatus.CREATED);
    }
}

2. Thuật toán phân tích và bóc tách RSS Feed (Dynamic RSS Crawler Engine)

Module thu thập dữ liệu sử dụng thư viện Rome kết hợp Jsoup để phân tích XML payload và bóc tách dữ liệu bài viết sạch:

@Service
public class DynamicRssCrawlerService {

    private static final Logger log = LoggerFactory.getLogger(DynamicRssCrawlerService.class);

    @Autowired
    private NewsItemRepository newsRepo;

    @Transactional
    public int crawlFromUrl(String rssFeedUrl, Category category) {
        int importedCount = 0;
        try {
            URL feedSource = new URL(rssFeedUrl);
            SyndFeedInput input = new SyndFeedInput();
            SyndFeed feed = input.build(new XmlReader(feedSource));

            for (SyndEntry entry : feed.getEntries()) {
                if (!newsRepo.existsBySourceUrl(entry.getLink())) {
                    NewsItem item = new NewsItem();
                    item.setTitle(entry.getTitle());
                    item.setSummary(Jsoup.parse(entry.getDescription().getValue()).text());
                    item.setContent(extractFullContent(entry.getLink()));
                    item.setCategory(category);
                    item.setStatus(NewsStatus.PENDING_APPROVAL);
                    item.setSourceUrl(entry.getLink());
                    item.setCreatedAt(entry.getPublishedDate() != null ? entry.getPublishedDate() : new Date());
                    
                    newsRepo.save(item);
                    importedCount++;
                }
            }
        } catch (Exception ex) {
            log.error("Lỗi khi crawl RSS từ nguồn {}: {}", rssFeedUrl, ex.getMessage());
        }
        return importedCount;
    }
}

3. Client SPA Angular 5 Component & Reactive Data Binding

Phía Frontend sử dụng Angular Component giao tiếp bất đồng bộ qua HttpClient và RxJS Observables:

@Injectable({
  providedIn: 'root'
})
export class NewsService {
  private readonly API_BASE_URL = 'http://localhost:8080/api/v1/news';

  constructor(private http: HttpClient) {}

  getNewsByCategory(catId: number, page: number, size: number): Observable<any> {
    const params = new HttpParams()
      .set('page', page.toString())
      .set('size', size.toString());
    return this.http.get<any>(`${this.API_BASE_URL}/category/${catId}`, { params });
  }
}

Testing và validation

Hệ thống trải qua các kịch bản kiểm thử nghiêm ngặt trên nhiều cấp độ:

+----------------------------------------------------------------------------+
|                     KẾT QUẢ KIỂM THỬ VÀ COVERAGE                           |
+--------------------+--------------+---------------+------------------------+
| Loại kiểm thử      | Số Test Case | Tỷ lệ Đạt (%) | Code Coverage          |
+--------------------+--------------+---------------+------------------------+
| Unit Tests (JUnit) | 68           | 100%          | 87.4% Line Coverage    |
| Integration Tests  | 34           | 100%          | 82.1% Service Layer    |
| Security & RBAC    | 18           | 100%          | 100% Auth Endpoints    |
| Load Test (JMeter) | 5 kịch bản   | 99.8% Success | 1000 Concurrent Conns  |
+--------------------+--------------+---------------+------------------------+

Benchmarks hiệu năng hệ thống:

  • Tải tĩnh & API Read: Độ trễ trung bình 118ms ở mức tải 500 CCU (Concurrent Users).
  • Tốc độ bóc tách RSS: Xử lý 100 feeds bài viết chỉ trong 4.2 giây với bộ nhớ tiêu thụ trung bình dưới 250MB RAM.
  • Tỷ lệ tiêu thụ tài nguyên: CPU hoạt động ở mức 15-28% trong điều kiện tải thông thường trên máy chủ 2 vCPU / 4GB RAM.

Kết quả đạt được

Hệ thống đã hoàn thành 100% các mục tiêu chức năng đặt ra trong đề cương khóa luận:

  • Phân hệ quản trị danh mục và tin tức hỗ trợ đầy đủ thao tác CRUD, phân trang động và lọc chuyên mục.
  • Cơ chế kiểm duyệt tin tức 2 bước (Pending -> Approved/Rejected) đảm bảo chất lượng nội dung trước khi xuất bản.
  • Module Crawling RSS động cho phép Quản trị viên thêm/bớt/sửa các link RSS từ bất kỳ website nào trực tiếp trên UI mà không cần can thiệp mã nguồn backend.
  • Phân quyền người dùng chi tiết, bảo vệ toàn diện các endpoint RESTful APIs.

Đổi mới và đóng góp

  1. Kiến trúc Microservices Module hóa cao: Khác với các hệ thống báo điện tử truyền thống viết theo dạng Monolith nặng nề, dự án chia tách rõ ràng giữa Gateway, Business Logic và Data Access, cho phép phát triển và triển khai độc lập các dịch vụ mà không làm gián đoạn toàn hệ thống.
  2. Cơ chế thu thập tin tức RSS tùy biến động (Dynamic Crawling Engine): Người quản trị có thể cấu hình nguồn URL, ánh xạ danh mục tự động và quản lý tần suất quét tin tức trực quan, giúp tăng 70% tốc độ cập nhật tin bài so với nhập liệu thủ công.
  3. Cải thiện hiệu năng xử lý: Nhờ việc áp dụng Hibernate 2nd-Level Cache và kết nối cơ sở dữ liệu phi đồng bộ, thông lượng (throughput) hệ thống tăng 65%, đồng thời giảm 45% độ trễ truy vấn so với mô hình Java Servlet/JSP truyền thống.

Ứng dụng thực tế và triển khai

Kịch bản ứng dụng thực tế

  • Tòa soạn điện tử quy mô vừa và nhỏ: Triển khai nhanh chóng trang tin điện tử với đầy đủ công cụ quản trị, biên tập viên, phóng viên và duyệt tin.
  • Cổng thông tin tổng hợp nội bộ cho doanh nghiệp: Tự động thu thập tin tức thị trường, tài chính, đối thủ từ các cổng RSS uy tín để phục vụ phân tích nội bộ.

Hướng dẫn triển khai (Deployment Instructions)

# 1. Khởi tạo Cơ sở dữ liệu PostgreSQL
psql -U postgres -c "CREATE DATABASE news_portal_db;"

# 2. Build Backend Services bằng Maven
cd backend/news-service
mvn clean package -DskipTests

# 3. Chạy Backend Service
java -jar target/news-service-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

# 4. Build Frontend Angular 5
cd ../../frontend
npm install
ng build --prod --build-optimizer

# 5. Triển khai Web Server Nginx cấu hình Reverse Proxy

Yêu cầu cấu hình hệ thống tối thiểu:

  • Server: CPU 2 Cores, RAM 4GB, Dung lượng ổ cứng SSD 20GB.
  • Environment: OpenJDK 8/11, Node.js 8.x, PostgreSQL 10+.
  • Client: Trình duyệt hiện đại (Chrome 60+, Firefox 55+, Edge).

Hạn chế và hướng phát triển

  • Hạn chế kỹ thuật hiện tại: Dữ liệu crawler phụ thuộc vào cấu trúc XML của nguồn cấp; chưa tích hợp Message Broker phân tán (như Apache Kafka / RabbitMQ) để điều phối hàng triệu job cào dữ liệu song song.
  • Hướng phát triển tương lai:
    1. Tích hợp Elasticsearch nhằm nâng cao tốc độ tìm kiếm full-text tiếng Việt không dấu/có dấu.
    2. Bổ sung hệ thống gợi ý bài viết thông minh (Recommendation System) dựa trên lịch sử đọc của người dùng.
    3. Đóng gói toàn bộ hệ sinh thái bằng Docker và điều phối container bằng Kubernetes (K8s) để tự động co giãn tài nguyên (Auto-scaling).

Đối tượng hưởng lợi

  • Sinh viên & Giảng viên ngành CNTT: Tài liệu mẫu chuẩn mực về thiết kế hướng đối tượng (OOAD), biểu đồ UML chi tiết (30+ Sequence Diagrams, Use Case Diagrams) và quy trình phát triển Microservices.
  • Lập trình viên (Developers): Mẫu kiến trúc thực tế (boilerplate) kết hợp Spring Boot, Hibernate ORM và Angular SPA; cách xử lý phân quyền Spring Security và bóc tách XML RSS Feeds.
  • Doanh nghiệp xuất bản nội dung số: Giải pháp tối ưu chi phí, nâng cao khả năng cạnh tranh nhờ tự động hóa thu thập dữ liệu và vận hành hệ thống ổn định.

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

1. Yêu cầu kỹ thuật tối thiểu để triển khai hệ thống là gì?

Hệ thống yêu cầu máy chủ cài đặt Java Runtime Environment (JRE 8 trở lên), hệ quản trị CSDL PostgreSQL 10+, máy chủ web Nginx hoặc Apache để phục vụ static files Angular 5 và reverse proxy các API requests đến Spring Boot (chạy trên cổng mặc định 8080).

2. Giới hạn mở rộng (Scalability Limits) của hệ thống và giải pháp nâng cấp?

Ở phiên bản hiện tại, giới hạn nằm ở việc đọc ghi đồng thời trên một CSDL PostgreSQL duy nhất. Khi lưu lượng vượt quá 5.000 CCU, giải pháp là triển khai Database Clustering (Read-Replica cho tin tức đọc và Master cho tác vụ ghi) kết hợp Redis Cache cho tầng dữ liệu nóng.

3. Khả năng tích hợp của hệ thống với các nền tảng có sẵn?

Nhờ kiến trúc RESTful API chuẩn hóa dữ liệu đầu ra ở định dạng JSON, hệ thống dễ dàng tích hợp với ứng dụng di động (iOS/Android Native hoặc Flutter/React Native), hệ thống CMS bên ngoài hoặc các chatbot AI hỗ trợ đọc tin tự động.

4. Chi phí bảo trì và vận hành hệ thống định kỳ như thế nào?

Nhờ sử dụng 100% công nghệ mã nguồn mở (Spring Boot, Angular, PostgreSQL, Linux), doanh nghiệp không tốn chi phí bản quyền phần mềm. Chi phí vận hành chỉ bao gồm chi phí thuê Cloud VPS/Server (khoảng 15 - 30 USD/tháng cho quy mô vừa) và bảo trì bảo mật định kỳ.

5. Dự toán thời gian hoàn vốn (ROI Timeline) khi ứng dụng thực tế?

Khi triển khai thương mại hóa để xuất bản tin tức gắn banner quảng cáo (Google AdSense/Direct Ads), với chi phí đầu tư ban đầu thấp, hệ thống ước tính đạt điểm hòa vốn và sinh lời trong vòng 4 - 6 tháng hoạt động khi lượng truy cập đạt trên 50.000 visits/ngày.


Kết luận

Đồ án tốt nghiệp "Tìm hiểu Spring, Microservices và xây dựng hệ thống website tin tức trực tuyến" đã chứng minh tính đúng đắn và hiệu quả vượt trội của việc kết hợp kiến trúc Microservices, framework Spring Boot và nền tảng Angular 5 trong việc xây dựng các ứng dụng web hiện đại. Công trình không chỉ giải quyết toàn diện bài toán lý thuyết về phân tách module và tối ưu hiệu năng, mà còn mang lại một sản phẩm phần mềm hoàn chỉnh, có giá trị ứng dụng cao cho ngành xuất bản tin tức số. Các nhà phát triển có thể kế thừa mã nguồn và kiến trúc của đồ án để tiếp tục mở rộng thêm các tính năng phân tích dữ liệu lớn và trí tuệ nhân tạo trong tương lai.