GP Coder

Trang chia sẻ kiến thức lập trình Java

  • Java Core
    • Basic Java
    • OOP
    • Exception Handling
    • Multi-Thread
    • Java I/O
    • Networking
    • Reflection
    • Collection
    • Java 8
  • Design pattern
    • Creational Pattern
    • Structuaral Pattern
    • Behavior Pattern
  • Web Service
    • SOAP
    • REST
  • JPA
  • Java library
    • Report
    • Json
    • Unit Test
  • Message Queue
    • ActiveMQ
    • RabbitMQ
  • All
Trang chủ Java library Giới thiệu thư viện Apache Commons Chain

Giới thiệu thư viện Apache Commons Chain

Đăng vào 01/05/2019 . Được đăng bởi GP Coder . 5533 Lượt xem . Toàn màn hình

Nội dung

  • 1 Apache Commons Chain là gì?
  • 2 Cài đặt thư viện Apache Commons Chain
  • 3 Sử dụng thư viện Apache Commons Chain

Apache Commons Chain là gì?

Apache Commons Chain là một framework, một thư viện mã nguồn mở của Apache. Nó cung cấp API cho phép chúng ta dễ dàng cài đặt các xử lý tuân theo Chain of Responsibility (COR) pattern.

Chain of Responsiblity cho phép một đối tượng gửi một yêu cầu nhưng không biết đối tượng nào sẽ nhận và xử lý nó. Điều này được thực hiện bằng cách kết nối các đối tượng nhận yêu cầu thành một chuỗi (chain) và gửi yêu cầu theo chuỗi đó cho đến khi có một đối tượng xử lý nó.

Chain of Responsibility Pattern hoạt động như một danh sách liên kết (Linked list) với việc đệ quy duyệt qua các phần tử (recursive traversal).

Cài đặt thư viện Apache Commons Chain

Thêm thư viện vào project vào project maven:


<!-- https://mvnrepository.com/artifact/commons-chain/commons-chain -->
<dependency>
	<groupId>commons-chain</groupId>
	<artifactId>commons-chain</artifactId>
	<version>1.2</version>
</dependency>

Sử dụng thư viện Apache Commons Chain

Trong Chain framework, các đơn vị công việc trong một chuỗi các bước tuần tự được biểu diễn bằng các Command. Một chuỗi các lệnh (Command) tạo thành một chain. Chuỗi chính nó cũng là một Command có thể được thực thi. Chain được giữ trong danh mục (Catalog), từ đó chúng có thể được lấy tại thời điểm thực thi. Chain framework cung cấp các interface Chain, Catalog, Command, Fillter như sơ đồ lớp bên dưới.

  • Context : thể hiện trạng thái của ứng dụng, chứa dữ liệu được chia sẻ giữa các Command.
  • Command : thể hiện các đơn vị công việc. Command chỉ bao gồm một phương thức execute() với tham số là một Context và kiểu trả về là giá trị boolean. Kiểu trả về boolean: để xác định có nên tiếp tục xử lý hay không. Trả về true nếu đã hoàn thành, không cần Command kế tiếp xử lý, ngược lại trả về false.
  • Chain : nó extends từ Command. Chain có thể chứa một chuỗi tuần tự các Command/ Chain khác.
  • Filter : là một Command đặc biệt, có thêm phương thức postProcess(). Phương thức này được gọi sau khi phương thức execute() được gọi.
  • Catalog : các ứng dụng sử dụng Facade hoặc Factory hoặc DI để giảm sự phụ thuộc giữa các lớp. Các lớp có thể giao tiếp với nhau mà không cần thông qua tên lớp. Catalog cũng dựa trên ý tưởng đó, nó cho phép client có thể thực thi một Command thông qua định danh mà không cần biết tên lớp.

Ví dụ sử dụng thư viện Apache Commons Chain

Tạo custom context để chia sẻ dữ liệu giữa các Command.


package com.gpcoder.context;

import org.apache.commons.chain.impl.ContextBase;

import lombok.Data;

@Data
public class MyContext extends ContextBase {

	private String property;
}

Tạo file constant đặt tên cho các command, chain. Chúng ta sẽ sử dụng tên này để lấy các Command từ Catalog và thực thi.


package com.gpcoder.constant;

public enum MyCommandNamed {
	CHAIN_1, CHAIN_2, CMD_1, CMD_2, CMD_3, CMD_4, EXCEPTION_HANDLER
}

Tạo Command1, Command2: đây là command minh họa cho đơn vị công việc sẽ được thực hiện trong Chain.


package com.gpcoder.command;

import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;

import com.gpcoder.context.MyContext;

public class Command1 implements Command {
	
	public boolean execute(Context ctx) throws Exception {
		System.out.println("This is command 1: ");

		String property = ((MyContext) ctx).getProperty();
		System.out.println("+ property: " + property);

		String customValue = ctx.get("custom-key").toString();
		System.out.println("+ customValue: " + customValue);

		return false;
	}
}


package com.gpcoder.command;

import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;

import com.gpcoder.context.MyContext;

public class Command2 implements Command {
	
	public boolean execute(Context ctx) throws Exception {
		String value = ((MyContext) ctx).getProperty();
		System.out.println("This is command 2: " + value);
		return false;
	}
}

Ví dụ 1 – Thực thi 1 Chain

Tạo chain có 2 command: Command1 và Command2.


package com.gpcoder.example1_chain;

import org.apache.commons.chain.impl.ChainBase;

import com.gpcoder.command.Command1;
import com.gpcoder.command.Command2;

public class MyChain extends ChainBase {

	public MyChain() {
		super();
		addCommand(new Command1());
		addCommand(new Command2());
	}
}

Thực thi chain:


package com.gpcoder.example1_chain;

import org.apache.commons.chain.Command;

import com.gpcoder.context.MyContext;

/**
 * Execute a chain example
 */
public class ChainStart1 {

	public static void main(String[] args) throws Exception {
		// Create context
		MyContext context = new MyContext();
		context.setProperty("property-value");
		context.put("custom-key", "custom-value");

		// Get the command
		Command command = new MyChain();
		command.execute(context);
	}
}

Output chương trình:


This is command 1: 
+ property: property-value
+ customValue: custom-value
This is command 2: property-value

Ví dụ 2 – Thực thi một Command được lấy từ Catalog

Tạo Catalog chứa các command và Chain cần sử dụng:


package com.gpcoder.example2_catalog;

import org.apache.commons.chain.impl.CatalogBase;

import com.gpcoder.command.Command1;
import com.gpcoder.command.Command2;
import com.gpcoder.constant.MyCommandNamed;
import com.gpcoder.example1_chain.MyChain;

/**
 * CatalogBase is a collection of Chains and Commands with their logical names.
 */
public class MyCatalog extends CatalogBase {

	public MyCatalog() {
		super();
		addCommand(MyCommandNamed.CMD_1.name(), new Command1());
		addCommand(MyCommandNamed.CMD_2.name(), new Command2());
		addCommand(MyCommandNamed.CHAIN_1.name(), new MyChain());
	}
}

Lấy Command từ Catalog và thực thi:


package com.gpcoder.example2_catalog;

import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.Command;

import com.gpcoder.constant.MyCommandNamed;
import com.gpcoder.context.MyContext;

/**
 * Execute the specific command example
 */
public class ChainStart2 {

	public static void main(String[] args) throws Exception {

		// Create context
		MyContext ctx = new MyContext();
		ctx.setProperty("property-value");
		ctx.put("custom-key", "custom-value");

		// Get the catalog
		Catalog catalog = new MyCatalog();

		// Get the command
		System.out.println("Execute the specific command: CMD_1");
		Command command1 = catalog.getCommand(MyCommandNamed.CMD_1.name());
		command1.execute(ctx);

		System.out.println("\nExecute the specific chain: CHAIN_1");
		Command chain1 = catalog.getCommand(MyCommandNamed.CHAIN_1.name());
		chain1.execute(ctx);
	}
}

Output chương trình:


Execute the specific command: CMD_1
This is command 1: 
+ property: property-value
+ customValue: custom-value

Execute the specific chain: CHAIN_1
This is command 1: 
+ property: property-value
+ customValue: custom-value
This is command 2: property-value

Ví dụ 3 – Sử dụng Filter để xử lý exception

Tạo Command3 có throw một Exception:


package com.gpcoder.command;

import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;

public class Command3 implements Command {

	public boolean execute(Context ctx) throws Exception {
		throw new UnsupportedOperationException("Cannot execute Command4");
	}
}

Tạo Fitler để handle Exception:


package com.gpcoder.filter;

import org.apache.commons.chain.Context;
import org.apache.commons.chain.Filter;

public class CommandExceptionHandler implements Filter {

	public boolean execute(Context context) throws Exception {
		System.out.println("CommandExceptionHandler.execute() called.");
		return false;
	}

	public boolean postprocess(Context context, Exception exception) {
		if (exception == null) {
			return false;
		}
		System.out.println("Exception " + exception.getMessage() + " occurred.");
		return true;
	}
}

Tạo Chain với 2 Command: Command1 và Command3.


package com.gpcoder.example3_exception;

import org.apache.commons.chain.impl.ChainBase;

import com.gpcoder.command.Command1;
import com.gpcoder.command.Command3;
import com.gpcoder.filter.CommandExceptionHandler;

public class MyChain3 extends ChainBase {

	public MyChain3() {
		super();
		addCommand(new CommandExceptionHandler());
		addCommand(new Command1());
		addCommand(new Command3());
	}
}

Thực thi chain:


package com.gpcoder.example3_exception;

import org.apache.commons.chain.Command;

import com.gpcoder.context.MyContext;

/**
 * Filter for exception handling in Chains example
 */
public class ChainStart3 {

	public static void main(String[] args) throws Exception {
		Command chain = new MyChain3();
		chain.execute(new MyContext());
	}
}

Output của chương trình:


CommandExceptionHandler.execute() called.
This is command 1: 
+ property: null
Exception null occurred.

Lưu ý: Filter Command phải thêm vào đầu chain để có thể handle exception cho các Command được thực thi phía sau.

Ví dụ 4 – Tạo Catalog từ file xml

Trong ví dụ 2, chúng ta tạo một Catalog bằng cách extend từ một CatalogBase. Chúng ta có một cách khác để tạo Catalog là xử dụng cấu hình catalog từ xml file.

Để sử dụng tính năng này, cần thêm các thư viện sau:


<!-- Use for the command config -->
<!-- https://mvnrepository.com/artifact/commons-digester/commons-digester -->
<dependency>
	<groupId>commons-digester</groupId>
	<artifactId>commons-digester</artifactId>
	<version>1.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
	<groupId>commons-collections</groupId>
	<artifactId>commons-collections</artifactId>
	<version>3.2.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
	<version>1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
	<groupId>commons-beanutils</groupId>
	<artifactId>commons-beanutils</artifactId>
	<version>1.9.3</version>
</dependency>

Để dễ minh họa các trường hợp sử dụng cấu hình xml file, chúng ta sẽ tạo thêm một Command:


package com.gpcoder.command;

import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;

import com.gpcoder.context.MyContext;

public class Command4 implements Command {
	
	public boolean execute(Context ctx) throws Exception {
		String value = ((MyContext) ctx).getProperty();
		System.out.println("This is command 4: " + value);
		return false;
	}
}

Tạo file chain-config.xml trong thư mục /src/main/resources


<catalog>
	<!-- Single command "chains" from CatalogBaseTestCase -->
	<command name="CMD_1" className="com.gpcoder.command.Command1" />
	<command name="CMD_2" className="com.gpcoder.command.Command2" />

	<!-- Chains with nested commands -->
	<chain name="CHAIN_1">
		<command className="com.gpcoder.filter.CommandExceptionHandler" />
		<command className="com.gpcoder.command.Command1" />
		<command className="com.gpcoder.command.Command2" />
		<command className="com.gpcoder.command.Command3" />
		<!-- Lookup Command -->
		<command name="CHAIN_2" optional="true" className="org.apache.commons.chain.generic.LookupCommand" />
	</chain>

	<chain name="CHAIN_2">
		<command className="com.gpcoder.command.Command4" />
	</chain>
</catalog>

Tạo Catalog từ XML file:


package com.gpcoder.example4_xml_config;

import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.config.ConfigParser;
import org.apache.commons.chain.impl.CatalogFactoryBase;

/**
 * Get catalog from the XML configuration file
 */
public class MyXMLCatalog {

	private static final String CONFIG_FILE = "/chain-config.xml";
	private ConfigParser parser;
	private Catalog catalog;

	public MyXMLCatalog() {
		parser = new ConfigParser();
	}

	public Catalog getCatalog() throws Exception {
		if (catalog == null) {
			parser.parse(this.getClass().getResource(CONFIG_FILE));
		}
		catalog = CatalogFactoryBase.getInstance().getCatalog();
		return catalog;
	}
}

Thực thi Command lấy từ Catalog trên:


package com.gpcoder.example4_xml_config;

import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.Command;

import com.gpcoder.constant.MyCommandNamed;
import com.gpcoder.context.MyContext;

/**
 * Get the catalog from XML file and Execute the specific command example
 */
public class ChainStart4 {

	public static void main(String[] args) throws Exception {
		// Create context
		MyContext ctx = new MyContext();
		ctx.setProperty("property-value");
		ctx.put("custom-key", "custom-value");

		// Get the catalog
		Catalog catalog = new MyXMLCatalog().getCatalog();

		// Get the command
		System.out.println("Execute the specific command: CMD_1");
		Command command1 = catalog.getCommand(MyCommandNamed.CMD_1.name());
		command1.execute(ctx);

		System.out.println("\nExecute the specific chain: CHAIN_1");
		Command chain1 = catalog.getCommand(MyCommandNamed.CHAIN_1.name());
		chain1.execute(ctx);
	}
}

Output chương trình:


Execute the specific command: CMD_1
This is command 1: 
+ property: property-value
+ customValue: custom-value

Execute the specific chain: CHAIN_1
CommandExceptionHandler.execute() called.
This is command 1: 
+ property: property-value
+ customValue: custom-value
This is command 2: property-value
Exception Cannot execute Command4 occurred.

Tài liệu tham khảo:

  • http://commons.apache.org/proper/commons-chain/
  • https://www.baeldung.com/apache-commons-chain
4.9
10
Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé! Và Donate tác giả

Shares

Chuyên mục: Design pattern, Java library Được gắn thẻ: Design pattern

Làm thế nào tạo instance của một class mà không gọi từ khóa new?
Giới thiệu Java Service Provider Interface (SPI) – Tạo các ứng dụng Java dễ mở rộng

Có thể bạn muốn xem:

  • Hướng dẫn Java Design Pattern – Facade (16/11/2018)
  • Hướng dẫn Java Design Pattern – Flyweight (22/11/2018)
  • Tạo số và chuỗi ngẫu nhiên trong Java (15/09/2019)
  • Giới thiệu Google Guice – Dependency injection (DI) framework (04/02/2019)
  • Clean code (13/01/2024)

Bình luận

bình luận

Tìm kiếm

Bài viết mới

  • Clean code 13/01/2024
  • Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud 02/10/2020
  • Kết nối RabbitMQ sử dụng Web STOMP Plugin 19/06/2020
  • Sử dụng publisher confirm trong RabbitMQ 16/06/2020
  • Sử dụng Dead Letter Exchange trong RabbitMQ 13/06/2020

Xem nhiều

  • Hướng dẫn Java Design Pattern – Factory Method (98059 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (97699 lượt xem)
  • Giới thiệu Design Patterns (87764 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (86433 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (83839 lượt xem)

Nội dung bài viết

  • 1 Apache Commons Chain là gì?
  • 2 Cài đặt thư viện Apache Commons Chain
  • 3 Sử dụng thư viện Apache Commons Chain

Lưu trữ

Thẻ đánh dấu

Annotation Authentication Basic Java Behavior Pattern Collection Creational Design Pattern Cấu trúc điều khiển Database Dependency Injection Design pattern Eclipse Exception Executor Service Google Guice Gson Hibernate How to Interceptor IO Jackson Java 8 Java Core JDBC JDK Jersey JMS JPA json JUnit JWT Message Queue Mockito Multithreading OOP PowerMockito RabbitMQ Reflection Report REST SOAP Structuaral Pattern Swagger Thread Pool Unit Test Webservice

Liên kết

  • Clean Code
  • JavaTpoint
  • Refactoring Guru
  • Source Making
  • TutorialsPoint
  • W3Schools Online Web Tutorials

Giới thiệu

GP Coder là trang web cá nhân, được thành lập với mục đích lưu trữ, chia sẽ kiến thức đã học và làm việc của tôi. Các bài viết trên trang này chủ yếu về ngôn ngữ Java và các công nghệ có liên quan đến Java như: Spring, JSF, Web Services, Unit Test, Hibernate, SQL, ...
Hi vọng góp được chút ít công sức cho sự phát triển cộng đồng Coder Việt.

Donate tác giả

Tìm kiếm các bài viết của GP Coder với Google Search

Liên hệ

Các bạn có thể liên hệ với tôi thông qua:
  • Trang liên hệ
  • Linkedin: gpcoder
  • Email: contact@gpcoder.com
  • Skype: ptgiang56it

Follow me

Copyright 2025 © GP Coder · All Rights Reserved · Giới thiệu · Chính sách · Điều khoản · Liên hệ ·

Share

Blogger
Delicious
Digg
Email
Facebook
Facebook messenger
Flipboard
Google
Hacker News
Line
LinkedIn
Mastodon
Mix
Odnoklassniki
PDF
Pinterest
Pocket
Print
Reddit
Renren
Short link
SMS
Skype
Telegram
Tumblr
Twitter
VKontakte
wechat
Weibo
WhatsApp
X
Xing
Yahoo! Mail

Copy short link

Copy link