Phần 3
của loạt bài "Giới thiệu Spring Roo" đã thảo luận về kiến trúc add-on trên Spring
Roo và cách tạo các add-on đơn giản và hỗ trợ mã ký tự quốc tế bằng cách sử dụng
lệnh addon create. Bài này tập trung vào hai kiểu add-on
còn lại được Spring Roo hỗ trợ, đó là, add-on nâng cao và add-on trình bao đóng
(wrapper). Điều quan trọng là trước hết bạn nên đọc Phần 3 trước khi tiếp tục. (ND:
Một add-on của trình bao đóng nhận một tạo phẩm Maven đã cho và bao đóng nó với các
mục nhập MANIFEST.MF thích hợp của OSGi, phân phối nó như là một tệp JAR mới để được
trình vỏ Roo sử dụng).
Add-on nâng cao cho phép Spring Roo làm mọi thứ mà một add-on đơn giản có thể làm, như cập nhật một tệp POM của Maven với các phụ thuộc hoặc các plug-in, cập nhật hoặc thêm các tệp cấu hình cộng với tăng cường các kiểu Java hiện có và đưa vào các kiểu Java mới bằng cách sử dụng các ITD của AspectJ. Khả năng thêm mã nguồn làm cho các add-on nâng cao rất mạnh mẽ so với tất cả các add-on khác. Trước khi bạn tạo một add-on nâng cao Spring Roo, hãy xem xét một add-on nâng cao hiện có do Spring Roo cung cấp.
Một add-on nâng cao là JPA, thực hiện công việc liên quan đến sự tồn tại lâu bền, có nghĩa là, thêm sự hỗ trợ cho các cơ sở dữ liệu và tạo ra các thực thể mới. Để thấy JPA này đang hoạt động, hãy mở trình shell của Roo và thực hiện các lệnh trong Liệt kê 1. Trong bài này, tôi sử dụng phiên bản Spring Roo 1.2.0.M1.
Liệt kê 1. Ví dụ JPA
project --topLevelPackage com.dw.demo --projectName entity-demo jpa setup --database FIREBIRD --provider HIBERNATE entity --class ~.domain.Book |
Cả hai lệnh jpa setup (thiết lập jpa) và lệnh entity (thực thể) đều tương ứng với một add-on nâng cao
được gọi là org.springframework.roo.addon.jpa. Kết quả
của lệnh jpa setup và lệnh entity trên trình shell của Roo cho phép phân biệt rõ giữa các add-on
đơn giản và nâng cao. Liệt kê 2 cho
thấy kết quả của lệnh set JPA.
Liệt kê 2. Kết quả của lệnh set JPA
Created SRC_MAIN_RESOURCES/META-INF/spring/database.properties Updated ROOT/pom.xml [added dependencies ...] Updated SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml Created SRC_MAIN_RESOURCES/META-INF/persistence.xml |
Kết quả của lệnh jpa setup cho thấy nó đang thực hiện các
chức năng cấu hình, chẳng hạn như thêm các phụ thuộc vào pom.xml, cập nhật Spring
applicationContext.xml và tạo ra tệp persistence.xml đặc trưng-tồn tại lâu bền. Ở
đây đã giả sử rằng lệnh JPA setup tương ứng với một add-on đơn giản vì nó không tạo
ra hoặc cập nhật mã nguồn Java. Hãy sử dụng add-on đơn giản cho các kịch bản tương
tự như kịch bản thiết lập được hiển thị ở trên.
Liệt kê 3 cho thấy kết quả của lệnh
entity.
Liệt kê 3. Kết quả của lệnh
Created SRC_MAIN_JAVA/com/dw/demo/domain Created SRC_MAIN_JAVA/com/dw/demo/domain/Book.java Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Configurable.aj Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Jpa_Entity.aj Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_Entity.aj Created SRC_MAIN_JAVA/com/dw/demo/domain/Book_Roo_ToString.aj |
Kết quả trên cho thấy việc tạo ra một tệp Java gọi là Book.java và 4 tệp *.aj. Quy tắc vàng để xác định một add-on nâng cao là việc tạo ra các tệp Java hoặc các tệp *.aj hoặc cả hai, như trong trường hợp của lệnh entity. Các tệp *Roo_*.aj này được gọi là các ITD (Inter-type Declarations – Các khai báo giữa các kiểu). Các ITD cho phép một kiểu (một khía cạnh) khai báo cho một kiểu khác, có nghĩa là, bạn có thể sửa đổi cấu trúc tĩnh của bất kỳ kiểu nào bằng cách thêm các phương thức, các trường hoặc thay đổi hệ thống phân cấp kiểu của chúng. Roo sử dụng một ITD làm một tạo phẩm tạo mã và quản lý chúng trong suốt vòng đời của chúng. Các ITD cho phép Roo tạo mã trong một đơn vị biên dịch riêng biệt, nhưng chúng được kết hợp vào trong cùng một lớp đã biên dịch.
Sau khi xem kết quả của lệnh entity, hãy xem các tạo phẩm này (các tệp .java và .aj) được Spring Roo tạo ra như thế nào. Xem Liệt kê 4 để biết một ví dụ mẫu của một tệp Book.java.
Liệt kê 4. Một tệp Book.java
package com.dw.demo.domain;
import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
@RooJavaBean
@RooToString
@RooEntity
public class Book {
}
|
Tệp Java này trông bình thường, ngoại trừ các chú thích trên lớp. Khi xem xét các tên
của các chú thích và các tệp .aj, rõ ràng là một số các chú thích tương ứng với chức
năng được các tệp .aj thêm vào. Ví dụ, RooToString tương
ứng với tệp Book_Roo_ToString.aj và nó thêm phương thức toString(). RooEntity tương ứng với
Book_Roo_Entity aj, Book_Roo_Jpa_Entity và các phương
thức liên quan đến tồn tại lâu bền. Tạm thời bây giờ bạn có thể để yên phần còn lại.
Để hiểu chú thích dẫn đến việc tạo các ITD ra sao, hãy khám phá cách Spring Roo cung
cấp các chức năng của add-on nâng cao.
- Trong lúc khởi động trình shell của Roo, nó sẽ quét tất cả các lớp và đăng ký
tất cả các lớp nào thực hiện giao diện
CommandMarker. Giao diệnCommandMarkercho Roo biết rằng các lớp này sẽ định nghĩa các lệnh mà add-on này có thể thực hiện. - Tất cả các add-on nâng cao đăng ký các dịch vụ của chúng với thời gian chạy OSGi
được cung cấp bởi Spring Roo. Các dịch vụ này chỉ rõ các điều kiện mà theo đó nó
sẽ kích hoạt việc tạo mã. Đối với tất cả các add-on nâng cao, điểm kích hoạt là
sự có mặt của một chú thích. Ví dụ, một add-on nâng cao để tạo phương thức
toString()chỉ được kích hoạt nếu một kiểu Java có chú thích RooToString. Điều này cũng đúng cho các chú thích khác. - Khi sử dụng
entity --class ~.domain.Book, add-on sẽ tạo ra một tệp Java được gọi là Book.java với các chú thích. add-on khác kích hoạt khi một kiểu Java có các chú thích này và các tệp .aj được viết cho chúng.
Thông tin chi tiết sẽ rõ hơn khi bạn tạo add-on nâng cao riêng của mình.
Add-on org.springframework.roo.addon.jpa chỉ là một ví dụ
về các add-on nâng cao được Spring Roo cung cấp. Các add-on nâng cao khác bao gồm
GWT, các driver, JSON và nhiều hơn nữa. Bản phát hành Spring Roo 1.2.0 có thêm hai
add-on nâng cao—đó là addon-equals và addon-JSF. add-on addon-equals
cung cấp cách thực hiện các phương thức so sánh bằng nhau (equals) và mã băm
(hashcode) cho một thực thể, còn add-on addon-JSF cung cấp sự hỗ trợ JSF trong các
ứng dụng Spring Roo. Để xem ảnh chụp màn hình Spring Roo mới nhất, hãy hoặc là xây
dựng mã Spring Roo hoặc là tải về ảnh chụp màn hình hiện có từ kho lưu trữ Spring Roo.
Đưa phương thức compareTo () vào lớp My Entity
Thông thường cần phải có các đối tượng hoặc thực thể để thực hiện giao diện java.lang.Comparable và cung cấp cách thực hiện phương thức compareTo(). Giao diện Comparable (có thể so sánh được) bắt
buộc các đối tượng của mỗi lớp thực hiện nó phải làm theo toàn bộ thứ tự. Khi bạn
thực hiện Comparable, bạn có thể:
- Gọi
java.util.Collections.sortvàjava.util.Collections.binarySearch - Gọi
java.util.Arrays.sortvàjava.util.Arrays.binarySearch - Sử dụng các đối tượng làm các khóa trong một
java.util.TreeMap - Sử dụng các đối tượng làm các phần tử trong một
java.util.TreeSet
Trong bài này, bạn sẽ xây dựng một add-on nâng cao sẽ cung cấp một cách thực hiện
compareTo() cho các thực thể được tạo ra trong ứng
dụng của bạn. Vì bạn muốn thêm mã Java vào ứng dụng của mình, nên bạn phải tạo ra
một add-on nâng cao.
Tài liệu hướng dẫn Spring Roo giải thích rõ cách thiết lập một dự án và kho lưu trữ Maven trên mã Google (Google code), do đó, không cần thiết phải lặp lại nó ở đây. Lưu ý rằng tôi sẽ sử dụng "spring-dw-roo-compareto-addon" làm tên dự án.
Nếu bạn chưa sử dụng phiên bản mới nhất của Spring Roo, 1.2.0.RC1, hãy tải nó từ trang web của dự án. Giải nén và cài đặt nó như đã giải thích trong Phần 1.
Spring Roo đã không ủng hộ hoặc đã loại bỏ một số các lớp được sử dụng trong các phiên bản trước đó.
Sau khi bạn thiết lập projectp, bạn sẽ thấy một thư mục tên là spring-dw-roo-compareto-addon chỉ có một thư mục .svn. Từ dòng lệnh, chuyển vào thư mục spring-dw-roo-compareto-addon và khởi động trình vỏ Roo. Rồi gõ lệnh sau:
addon create advanced --topLevelPackage
org.xebia.roo.addon.compareto --projectName spring-dw-roo-compareto-addon
Thế là xong! Bạn vừa mới tạo ra một add-on nâng cao.
Tiếp theo, trên trình shell của Roo, bắt đầu thực hiện lệnh perform package (thực hiện gói) để tạo ra một tệp jar của add-on. Liệt kê 5 cho thấy các tệp được lệnh
addon create advanced tạo ra.
Liệt kê 5. Các tệp được lệnh addon create advanced tạo ra
Created ROOT/pom.xml Created SRC_MAIN_JAVA Created SRC_MAIN_RESOURCES Created SRC_TEST_JAVA Created SRC_TEST_RESOURCES Created SPRING_CONFIG_ROOT Created ROOT/readme.txt Created ROOT/legal Created ROOT/legal/LICENSE.TXT Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoCommands.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoOperations.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoOperationsImpl.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoMetadata.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/ComparetoMetadataProvider.java Created SRC_MAIN_JAVA/org/xebia/roo/addon/compareto/RooCompareto.java Created ROOT/src/main/assembly Created ROOT/src/main/assembly/assembly.xml Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/compareto Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/compareto/configuration.xml |
Một số các tệp được tạo ra như pom.xml, readme.txt và license.txt, không cần bất kỳ lời giới thiệu nào vì chúng đã được thảo luận trong Phần 3 và là tự giải thích rồi. Các tạo phẩm thú vị hơn là:
- ComparetoCommands.java
- ComparetoOperations.java
- ComparetoOperationsImpl.java
- ComparetoMetadata.java
- ComparetoMetadataProvider.java
- RooCompareto.java
Bây giờ hãy xem xét từng tạo phẩm được tạo ra.
ComparetoCommands.java: Lớp này thực hiện giao diệnCommandMarkervà trưng ra hai loại phương thức—một loại có chú thíchCliAvailablityIndicatorvà loại khác có chú thíchCliCommand. Chú thíchCliAvailablityIndicatorcho Spring Roo biết khi nào lệnh này sẽ nhìn thấy được. Ví dụ lệnh 'entity' sẽ không được tạo sẵn trước khi người dùng định nghĩa các giá trị cài đặt tồn tại lâu bền trong trình shell của Roo hoặc trực tiếp trong dự án. Các phương thức được chú thích với@CliCommandsẽ đăng ký lệnh này với trình shell của Roo. Chú thích@CliCommandcó hai thuộc tính: value (giá trị), định nghĩa tên lệnh và help (trợ giúp), định nghĩa thông báo trợ giúp được hiển thị khi gõ lệnh help. Để biết thêm về một giải thích chi tiết của lớp*Commands, hãy tham khảo Phần 3.ComparetoOperationsImpl.java: LớpComparetoCommandsủy quyền tất cả công việc cho lớpComparetoOperationsImpl. Bốn phương thức được tạo ra trong lớp này là:isCommandAvailable(): Phương thức này được gọi bởi phương thức được chú thích với chú thíchCliAvailabilityIndicator ComparetoCommandstrong lớpComparetoCommandsđể kiểm tra xem lệnh này có nhìn thấy được hay không. Điều này là để bảo đảm các lệnh nhận biết về bối cảnh. Phương thức này thực hiện các việc xác nhận hợp lệ khác nhau. Ví dụ, nếu dự án đã được tạo ra, thì chỉ khi đó lệnh này sẽ nhìn thấy được hoặc nếu đã thiết lập tính tồn tại lâu bền, thì chỉ khi đó lệnh này sẽ nhìn thấy được. Không bắt buộc phải có một điều kiện để nhìn thấy được lệnh này. Để chắc chắn rằng lệnh luôn nhìn thấy được, chỉ cần trả về true (đúng).setup(): Phương thức này được gọi bởi phương thứcsetup()trong lớpComparetoCommandsđược chú thích với@CliCommand. Mã, làm cho lớp này trở nên rõ ràng, chịu trách nhiệm về thực hiện các nhiệm vụ liên quan đến thiết lập chẳng hạn như thêm các phụ thuộc Maven, thêm các kho lưu trữ Maven hoặc tạo hoặc cập nhật các tệp bối cảnh Spring (như đã thực hiện với add-on Roo Jamon trong Phần 3).annotateType(): Phương thức này vàannotateAll()là các phương thức mới chưa có trong các add-on đơn giản. Chức năng của phương thức này là thêm một chú thích (RooCompareto) vào kiểu Java đã chỉ rõ. Phương thức này sử dụng một số dịch vụ do Spring Roo-cung cấp để tìm nạp các chi tiết Class (Lớp) cho kiểu Java đã cho và nối thêm chú thíchRooJComparetovào nó.annotateAll(): Phương thức này tìm tất cả các kiểu được chú thích với chú thíchRooJavaBeangọi phương thứcannotateType()trên tất cả các kiểu đó. Hãy sử dụng phương thức này khi tất cả các thực thể cần có chú thíchRooCompareto.
RooCompareto.java: Sự có mặt của chú thích này làm cho add-on tạo mã.ComparetoMetadataProvider.java: Lớp này là một dịch vụ Spring Roo và được gọi bởi Roo để lấy ra siêu dữ liệu cho add-on. Lớp này đăng ký các thủ tục trigger để thêm và loại bỏ siêu dữ liệu. Không cần phải có thay đổi nào trong lớp này, nhưng hãy nhớ rằng lớp này có một phương thức gọi là getMetaData (), sẽ được gọi bởi Spring Roo bất cứ khi nào có bất kỳ kiểu Java nào có chú thíchRooCompareto.ComparetoMetadata.java: Lớp này chịu trách nhiệm để tạo ra ITD tương ứng với add-on. Trong đoạn mã được tạo ra, nó sử dụng một lớp được gọi làItdTypeDetailsBuilderđể tạo ra một ITD có một trường và một phương thức. Phần dưới đây trong bài này, bạn sẽ thay đổi mã mặc định được tạo ra để đáp ứng các yêu cầu thêm một phương thứccompareTovà thực hiện giao diện Comparable.
Sửa đổi add-on để đáp ứng các yêu cầu
Bạn muốn tạo ra một add-on, mà nó sẽ cần thêm phương thức compareTo vào các lớp thực thể. Bạn sẽ:
- Thêm phụ thuộc Maven của
commons-langphiên bản 3.1 vào dự án đích. Điều này là cần thiết bởi vìcommons-langcung cấp một lớp của trình xây dựng tên làCompareToBuildermà trình này sẽ được sử dụng để xây dựng phương thứccompareTo. - Tạo lớp thực thể thực hiện giao diện
Comparable. - Tạo một ITD cho phương thức
compareTo.
Để đáp ứng các yêu cầu này, cần có các thay đổi trong các lớp ComparetoOperationsImpl và ComparetoMetadata.
Hãy thực hiện từng thay đổi này.
- Đầu tiên, hãy thêm phụ thuộc
commons-langcủa Maven vào dự án đích. Cập nhật tệp Configuration.xml để có phụ thuộccommons-langthay cho gói phụ thuộc Spring được cung cấp theo mặc định, như trong Liệt kê 6.
Liệt kê 6. Cập nhật tệp Configuration.xml<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.1</version> </dependency> </dependencies> </configuration>
- Tiếp theo, sửa đổi mã thực hiện phương thức
setup()trong lớpComparetoOperationsImplđể đọc phụ thuộccommons-langcủa Maven thay cho phụ thuộc bó Spring của Maven, như trong Liệt kê 7. Phương thứcannotateTypevàannotateAll()không được hiển thị ở đây vì chúng không có bất kỳ thay đổi nào.
Liệt kê 7. Sửa đổi việc thực hiện phương thức setup ()@Component @Service public class ComparetoOperationsImpl implements ComparetoOperations { @Reference private ProjectOperations projectOperations; @Reference private TypeLocationService typeLocationService; @Reference private TypeManagementService typeManagementService; /** {@inheritDoc} */ public void setup() { // Install the add-on Google code repository needed to get the annotation projectOperations.addRepository("", new Repository("Compareto Roo add-on repository", "Compareto Roo add-on repository", "https://spring-dw-roo-compareto-addon.googlecode.com/svn/repo")); List<Dependency> dependencies = new ArrayList<Dependency>(); // Install the dependency on the add-on jar ( dependencies.add(new Dependency("org.xebia.roo.addon.compareto", "org.xebia.roo.addon.compareto", "0.1.0.BUILD-SNAPSHOT", DependencyType.JAR, DependencyScope.PROVIDED)); Element configuration = XmlUtils.getConfiguration(getClass()); for (Element dependencyElement : XmlUtils.findElements( "/configuration/dependencies/dependency", configuration)) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies("", dependencies); } }
Những thay đổi được thực hiện cho đến nay là tương tự như những thay đổi được sử dụng để tạo ra add-on đơn giản Jamon trong Phần 3.
Tạo lớp thực thể triển khai giao diện Comparable
Sau khi thực hiện các thay đổi về mã để thêm phụ thuộc Maven, bạn cần phải chắc chắn
rằng lớp thực thể của bạn thực hiện giao diện java.lang.Comparable. Để làm điều đó,
hãy sửa đổi ITD do lớp ComparetoMetadata tạo ra. Các lớp
siêu dữ liệu tạo ra ITD bằng cách sử dụng lớp ItdTypeDetailsBuilder, nó cung cấp các phương thức add khác nhau để thêm
các phương thức, các trường, các chú thích, giao diện và nhiều hơn nữa vào một ITD.
Để tạo ra một kiểu Java thực hiện một giao diện, hãy sử dụng phương thức addImplementsType trong lớp ItdTypeDetailsBuilder, như trong Liệt kê 8. Tôi chỉ hiển thị các hàm dựng ComparetoMetadata vì việc xây dựng ITD diễn ra trong hàm dựng.
Liệt kê 8. Thực hiện giao diện java.lang.Comparable
public ComparetoMetadata(String identifier, JavaType aspect Name,
PhysicalTypeMetadata governorPhysicalTypeMetadata) {
super(identifier, aspect Name, governorPhysicalTypeMetadata);
Assert.isTrue(isValid(identifier), "Metadata identification string '" +
identifier + "' does not appear to be a valid");
JavaType comparableInterface = new JavaType("java.lang.Comparable");
builder.addImplementsType(comparableInterface);
itdTypeDetails = builder.build();
}
|
Tạo một ITD cho phương thức compareTo
Sau khi tạo ra một kiểu Java thực hiện giao diện Comparable, bạn phải cung cấp mã
lệnh thực hiện phương thức compareTo. Lớp CompareToBuilder cung cấp một giao diện
uyển chuyển để tạo ra phương thức compareTo. add-on equals của Spring Roo sử dụng
EqualsBuilder và HashCodeBuilder để cung cấp mã thực hiện cho phương thức equals và
hashcode. Hãy lấy một ví dụ để chắc chắn là CompareToBuilder giúp đỡ trong việc tạo ra phương thức compareTo như thế nào. Giả sử bạn có một thực thể được gọi
là Book và bạn muốn cung cấp việc thực hiện compareTo cho nó bằng cách sử dụng CompareToBuilder. Liệt kê 9 cho thấy lớp Book và phương thức compareTo.
Liệt kê 9. Lớp Book và phương thức compareTo
import org.apache.commons.lang3.builder.CompareToBuilder;
public class Book implements Comparable {
private String title;
private String author;
private double price;
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
// getters and setters
public int compareTo(Book o) {
if(!(o instanceof Book)){
return -1;
}
Book book = (Book)o
return new CompareToBuilder().append(this.title, book.title).append(this.author,
book.author).append(this.price, book.price).toComparison();
}
@Override
public String toString() {
return "Book [title=" + title + ", author=" + author + ", price=" + price + "]";
}
}
|
Phương thức compareTo trong Liệt kê 9 thực hiện như sau:
- Nếu o không phải là
instanceOfBookthì trả về -1 - Nếu o là
instanceOfBookthì áp kiểu o là Book - Tạo một đối tượng của lớp
CompareToBuildervà sau đó gọi phương thức append (nối thêm) trên các trường
Xây dựng phương thức compareTo dần dần theo các bước sau:
- Nếu o không phải là instanceof Book thì trả về -1
Trước khi bạn thêm việc kiểm tra
instanceOf, hãy tạo ra phương thứccompareTo. Xem Liệt kê 10.
Liệt kê 10. Tạo phương thức compareTopublic ComparetoMetadata(String identifier, JavaType aspect Name, PhysicalTypeMetadata governorPhysicalTypeMetadata) { super(identifier, aspect Name, governorPhysicalTypeMetadata); Assert.isTrue(isValid(identifier), "Metadata identification string '" + identifier + "' does not appear to be a valid"); JavaType comparableInterface = new JavaType("java.lang.Comparable"); builder.addImplementsType(comparableInterface); builder.addMethod(getCompareToMethod()); itdTypeDetails = builder.build(); } private MethodMetadata getCompareToMethod() { final JavaType parameterType = JavaType.OBJECT; final List<JavaSymbolName> parameterNames = Arrays.asList(new JavaSymbolName("obj")); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine("return -1;"); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName("compareTo"), JavaType.INT_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterType), parameterNames, bodyBuilder); return methodBuilder.build(); }
getCompareToMethod()tạo ra siêu dữ liệu của phương thứccompareTobằng cách sử dụng lớpMethodMetadataBuilder. LớpMethodMetadataBuilderlà một lớpBuilderdo Spring Roo cung cấp để xây dựng siêu dữ liệu phương thức. Để xây dựng siêu dữ liệu phương thức, đầu tiên hãy xây dựng một đối tượngMethodMetadataBuilder, chuyển cho nó các đối số làm trình sửa đổi, tên phương thức, kiểu trả về, danh sách tham số hoặc một trình xây dựng thân phương thức để xây dựng siêu dữ liệu cho phương thứccompareTonhư trong Liệt kê 11.
Liệt kê 11. Kiểm tra instanceofprivate MethodMetadata getCompareToMethod() { final JavaType parameterType = JavaType.OBJECT; String parameterName = "obj"; final List<JavaSymbolName> parameterNames = Arrays.asList(new JavaSymbolName(parameterName)); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); final String typeName = destination.getSimpleTypeName(); bodyBuilder.appendFormalLine("if (!(" + parameterName + " instanceof " + typeName + ")) {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("return -1;"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); bodyBuilder.appendFormalLine("return -1;"); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName("compareTo"), JavaType.INT_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterType), parameterNames, bodyBuilder); return methodBuilder.build(); }
- Nếu o là
instanceOfBookthì ép kiểu o là BookBước tiếp theo là một phép ép kiểu sao cho bạn có thể xây dựng phương thức
compareTo. Để làm điều này, sau khi kiểm tra instanceof hãy thêm dòng sau:bodyBuilder.appendFormalLine(typeName + " rhs = (" + typeName + ") " + OBJECT_NAME + ";");
- Tạo đối tượng lớp CompareToBuilder rồi gọi phương thức append trên các trường
Để xây dựng phương thức
compareTo, bạn cần truy cập vào tất cả các trường của một lớp. LớpComparetoMetadatakhông chứa bất kỳ thông tin nào về kiểu, do đó nó không thể nhận được các trường của lớp. Thông tin này có thể đượcComparetoMetadataProvidercung cấp như Liệt kê 12.
Liệt kê 12. ComparetoMetadataProviderprotected ItdTypeDetailsProvidingMetadataItem getMetadata(String metadataId, JavaType aspect Name, PhysicalTypeMetadata governorPhysicalTypeMetadata, String itdFilename) { final String[] excludeFields = {}; final MemberDetails memberDetails = getMemberDetails(governorPhysicalTypeMetadata); if (memberDetails == null) { return null; } final JavaType javaType = governorPhysicalTypeMetadata.getMemberHoldingTypeDetails().getName(); final List<FieldMetadata> compareToFields = locateFields(javaType, excludeFields, memberDetails, metadataId); return new ComparetoMetadata(metadataId, aspect Name, governorPhysicalTypeMetadata, compareToFields); } private List<FieldMetadata> locateFields(final JavaType javaType, final String[] excludeFields, final MemberDetails memberDetails, final String metadataIdentificationString) { final SortedSet<FieldMetadata> locatedFields = new TreeSet<FieldMetadata>(new Comparator<FieldMetadata>() { public int compare(final FieldMetadata l, final FieldMetadata r) { return l.getFieldName().compareTo(r.getFieldName()); } }); final List<?> excludeFieldsList = CollectionUtils.arrayToList(excludeFields); final FieldMetadata versionField = persistenceMemberLocator.getVersionField(javaType); for (final FieldMetadata field : memberDetails.getFields()) { if (excludeFieldsList.contains(field.getFieldName().getSymbolName())) { continue; } if (Modifier.isStatic(field.getModifier()) || Modifier.isTransient(field.getModifier()) || field.getFieldType().isCommonCollectionType() || field.getFieldType().isArray()) { continue; } if (versionField != null && field.getFieldName().equals(versionField.getFieldName())) { continue; } locatedFields.add(field); metadataDependencyRegistry.registerDependency( field.getDeclaredByMetadataId(), metadataIdentificationString ); } return new ArrayList<FieldMetadata>(locatedFields); }
Sau khi bạn có các trường, hãy chuyển chúng tới
ComparetoMetadatasao cho nó có thể xây dựng phương thứccompareTo, như trong Liệt kê 13.
Liệt kê 13. Chuyển siêu dữ liệu để xây dựng phương thức compareToprivate List<FieldMetadata> compareToFields; public ComparetoMetadata(String identifier, JavaType aspectName, PhysicalTypeMetadata governorPhysicalTypeMetadata, List<FieldMetadata> compareToFields) { super(identifier, aspectName, governorPhysicalTypeMetadata); Assert.isTrue(isValid(identifier), "Metadata identification string '" + identifier + "' does not appear to be a valid"); this.compareToFields = compareToFields; if (!CollectionUtils.isEmpty(compareToFields)) { JavaType comparableInterface = new JavaType("java.lang.Comparable"); builder.addImplementsType(comparableInterface); builder.addMethod(getCompareToMethod()); } itdTypeDetails = builder.build(); } private MethodMetadata getCompareToMethod() { final JavaType parameterType = JavaType.OBJECT; String parameterName = "obj"; final List<JavaSymbolName> parameterNames = Arrays.asList(new JavaSymbolName(parameterName)); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); final ImportRegistrationResolver imports = builder.getImportRegistrationResolver(); imports.addImport( newJavaType("org.apache.commons.lang3.builder.CompareToBuilder") ); final String typeName = destination.getSimpleTypeName(); bodyBuilder.appendFormalLine("if (!(" + parameterName + " instanceof " + typeName + ")) {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("return -1;"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); bodyBuilder.appendFormalLine(typeName + " rhs = (" + typeName + ") " + parameterName + ";"); final StringBuilder builder = new StringBuilder(); builder.append("return new CompareToBuilder()"); for (final FieldMetadata field : compareToFields) { builder.append(".append(" + field.getFieldName() + ", rhs." + field.getFieldName() + ")"); } builder.append(".toComparison();"); bodyBuilder.appendFormalLine(builder.toString()); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName("compareTo"), JavaType.INT_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterType), parameterNames, bodyBuilder); return methodBuilder.build(); }
Điều này sẽ hoàn thành việc tạo add-on compareTo. Bạn có
thể tải về mã nguồn đầy đủ của add-on này từ kho lưu trữ mã
Google. Bây giờ, bạn có thể thử nghiệm compareTo
mà bạn vừa tạo ra.
- Thoát khỏi trình shell Roo và chạy lệnh
mvn clean install. Trong quá trình build, nó sẽ hỏi bạn về cụm từ mật khẩu GPG. - Sau khi add-on Roo được xây dựng, hãy mở một dòng lệnh mới và tạo ra một thư mục có tên là bookshop.
- Chuyển vào thư mục bookshop và gõ lệnh
roođể mở một trình shell Roo. - Thực hiện các lệnh từ Liệt kê 14 trong trình shell Roo.
Liệt kê 14. Tạo add-onproject --topLevelPackage com.xebia.roo.bookshop --projectName bookshop jpa setup --database HYPERSONIC_IN_MEMORY --provider HIBERNATE entity jpa --class ~.domain.Book field string --fieldName title --notNull field string --fieldName author --notNull field number --fieldName price --type double --notNull
- Để cài đặt và khởi động add-on này, hãy gõ lệnh sau vào trình shell Roo:
osgi start --url file://<location to compareTo addon jar>
Lệnh này sẽ cài đặt và kích hoạt add-on compareTo của bạn. Bạn có thể xem trạng thái của add-on bằng cách sử dụng lệnh ps của OSGi.
- Gõ
comparetovà nhấn phím tab để xem ba lệnh của add-on compareTo trong Liệt kê Liệt kê 15.
Liệt kê 15. Xem các lệnh của add-on compareToroo> compareto compareto add compareto all compareto setup
- Các bước trong Liệt kê 15 sẽ
xác nhận rằng add-on compareTo được cài đặt đúng. Bước tiếp theo là chạy lệnh
setup (cài đặt), sẽ cấu hình các phụ thuộc cần thiết. Xem Liệt kê 16.
Liệt kê 16. Chạy lệnh setuproo> compareto setup Updated ROOT/pom.xml [added repository https://spring-dw-roo-compareto-addon.googlecode.com/svn/repo; added dependencies org.xebia.roo.addon.compareto:org.xebia.roo.addon.compareto: 0.1.0.BUILD, org.apache.commons:commons-lang3:3.1; removed dependency org.apache.commons:commons-lang3:3.0.1]
- Một khi bạn chạy lệnh
compareto setup, bước logic tiếp theo là thêm phương thứccompareTovào các lớp thực thể. Có thể thực hiện việc này bằng hoặc lệnh compareTo add hoặc lệnh compareTo all tùy thuộc vào việc liệu bạn có muốn tạo phương thức compareTo chỉ cho một lớp thực thể hay cho tất cả các lớp thực thể. Hãy thêm phương thứccompareTovào tất cả các lớp thực thể trong ứng dụng bookshop ví dụ mẫu (Xem phần Tải về). Xem Liệt kê 17.
Liệt kê 17. Thêm phương thức compareTo vào tất cả các lớp thực thểroo> compareto all Updated SRC_MAIN_JAVA/com/xebia/roo/bookshop/domain/Book.java Created SRC_MAIN_JAVA/com/xebia/roo/bookshop/domain/Book_Roo_Compareto.aj
Như bạn có thể thấy ở trên trong kết quả của lệnh compareTo all, một ITD có tên là Book_Roo_Compareto.aj được tạo ra. Tệp này sẽ chứa phương thức compareTo. Liệt kê 18 cho thấy tệp Book_Roo_Compareto.aj.
Liệt kê 18. Tệp Book_Roo_Compareto.ajimport org.apache.commons.lang.builder.CompareToBuilder; privileged aspect Book_Roo_Compareto { declare parents: Book implements java.lang.Comparable; public int Book.compareTo(java.lang.Object obj) { if (!(obj instanceof Book)) { return -1; } Book rhs = (Book) obj; return new CompareToBuilder().append(author, rhs.author).append(id, rhs.id).append(price, rhs.price).append(title, rhs.title).toComparison(); } } - Chạy lệnh
perform packagetrên trình shell Roo để kiểm tra xem mọi thứ được biên dịch đúng chưa sau khi thêm add-on. Trước sự ngạc nhiên của bạn, việc xây dựng này sẽ thất bại vì Maven không thể phân giải các gói phụ thuộc Spring Roo. Các gói phụ thuộc này đến từ add-oncompareTo. Bạn cần phụ thuộc này theo add-on bởi vì các thực thể của bạn phải được chú thích với chú thích compareTo. Đây là điều duy nhất mà bạn cần từ add-on. Cách tốt nhất mà tôi đã tìm ra là tạo ra một mô đun Maven khác và đưa tất cả phụ thuộc của add-on vào đó. Điều này theo đúng các cách tương tự như những gì Spring Roo làm. Spring Roo không tìm phần phụ thuộc cho từng mỗi add-on và cho mọi add-on đã sử dụng. Nó có một tệp jar của các chú thích Spring Roo chung, có chứa tất cả các phụ thuộc. Tôi đã tạo ra một dự án xebia-spring-roo-addon-annotation và đặt chú thích Compareto vào trong mô đun này. Tiếp theo, tôi đã cập nhật tệp configuration.xml để thêm tệp jar này vào dự án của máy khách thay vì tệp jar của add-on. Liệt kê 19 cho thấy tệp configuration.xml.
Liệt kê 19. Tệp configuration.xml<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>org.xebia.roo.addon</groupId> <artifactId>xebia-spring-roo-addon-annotations</artifactId> <version>0.0.1</version> </dependency> </dependencies> <repositories> <repository> <id>spring-roo-addon-annoations</id> <name>Spring Roo Addon Annotation</name> <url>https://xebia-spring-roo-addon-annotations.googlecode.com/svn/repo</url> </repository> </repositories> </configuration>
Cập nhật phương thức
setup()của lớpComparetoOperationsImplđể đọc các phụ thuộc và kho lưu trữ mới đã được chỉ rõ trong tệp Configuration.xml đã cập nhật. Xem Liệt kê 20.
Liệt kê 20. Cập nhật phương thức setup () của lớp ComparetoOperationsImplpublic void setup() { bu List<Dependency> dependencies = new ArrayList<Dependency>(); Element configuration = XmlUtils.getConfiguration(getClass()); for (Element dependencyElement : XmlUtils.findElements("/configuration/dependencies/dependency", configuration)) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies("", dependencies); List<Element> repositories = XmlUtils.findElements( "/configuration/repositories/repository", configuration); for (Element repositoryElement : repositories) { Repository repository = new Repository(repositoryElement); projectOperations.addRepository(projectOperations.getFocusedModuleName(), repository); } }
Sau đó làm theo các bước sau:
- Xây dựng lại add-on này bằng cách chạy lệnh
mvn clean install. - Tạo lại trình máy khách như bạn đã tạo nó trong bước 4.
- Để loại bỏ add-on cũ, hãy gõ lệnh sau vào trình shell Roo:
addon remove --bundleSymbolicName org.xebia.roo.addon.compareto
- Cài đặt lại add-on bằng cách chạy lệnh
osgi install. - Ngay khi đã cài đặt add-on, hãy chạy các lệnh
compareto setupvàcompareto all.Bạn sẽ thấy các ITD của compareTo. Hãy chạy lệnh perform package và tất cả mọi thứ sẽ làm việc tốt.
Một khi bạn đã thử nghiệm xem add-on của bạn có đang làm việc trong môi trường phát triển của bạn không, bạn có thể đẩy nó vào dự án mã trên Google mà bạn đã tạo. Để xuất bản add-on ra thế giới bên ngoài, hãy làm theo thủ tục tương tự được dùng để xuất bản add-on i18n trong Phần 3. Tương tự như vậy, để đăng ký add-on với RooBot, hãy làm theo tài liệu hướng dẫn Spring Roo.
Tạo các driver JDBC không phải-OSGi nhưng tuân thủ OSGi với add-on của trình bao đóng
Một trường hợp sử dụng phổ biến của add-on của trình bao đóng là chuyển đổi các driver JDBC không phải-OSGi thành các bó tuân thủ OSGi. Một nơi mà bạn cần bao đóng một driver JDBC là khi bạn phải dùng kỹ thuật dịch ngược một cơ sở dữ liệu Oracle bằng cách sử dụng Spring Roo. Spring Roo không cung cấp các driver JDBC Oracle của OSGi vì các vấn đề bản quyền. Trước khi sử dụng kỹ thuật dịch ngược một cơ sở dữ liệu Oracle, trước hết hãy làm cho driver tuân thủ OSGi. Để tạo ra một add-on của trình bao đóng một driver JDBC Oracle:
- Cài đặt tệp jar JDBC Oracle trong kho lưu trữ Maven của máy tính cục bộ của bạn
bằng cách gõ lệnh sau.
mvn install:install-file -Dfile=ojdbc5.jar -DgroupId=com.oracle -DartifactId=ojdbc5 -Dversion=11.2.0.2 -Dpackaging=jar
- Tạo một thư mục mới có tên là oracle-wrapper-addon và từ dòng lệnh chuyển vào thư mục đó.
- Mở trình vỏ Roo và thực hiện lệnh add-on của trình bao đóng:
addon create wrapper --topLevelPackage com.oracle.wrapper.jdbc --groupId com.oracle --artifactId ojdbc5 --version 11.2.0.2 --vendorName Oracle --licenseUrl oracle.comLệnh này sẽ chỉ tạo các tệp pom.xml, sẽ được sử dụng để chuyển đổi một driver JDBC Oracle không phải-OSGi thành một driver OSGi.
- Từ bên trong trình shell Roo, chạy lệnh này để tạo bó OSGi:
perform command --mavenCommand bundle:bundle
Thế là xong. Bây giờ bạn đã tạo thành công một bó OSGi của một tệp jar không phải-OSGi.
Trong bài này, bạn đã học về add-on nâng cao và add-on của trình bao đóng trong Spring Roo. Bạn cũng đã học cách tạo ra add-on nâng cao và add-on của trình bao đóng. Bài này kết thúc quá trình tìm hiểu của bạn về một tính năng rất quan trọng của Spring Roo: đó là viết các add-on. Bất cứ lúc nào bạn muốn mở rộng chức năng của Spring Roo, hãy nhớ nghĩ đến việc tạo các add-on.
Trong phần tiếp theo của loạt bài "Giới thiệu Spring Roo", tôi sẽ nói về cách bạn viết các ứng dụng GWT khi sử dụng Spring Roo.
| Mô tả | Tên | Kích thước | Phương thức tải |
|---|---|---|---|
| Sample code | bookshop.zip | 14KB | HTTP |
| Sample code | spring-dw-roo-compareto-addon.zip | 18KB | HTTP |
Học tập
- Khám phá tài liệu hướng dẫn Spring Roo và tìm mọi thứ bạn cần để sử dụng Roo hiệu quả.
- Hãy chắc chắn đọc phần còn lại của loạt Spring Roo
này:
- Phần 1: Xây dựng từ mã nguồn
- Phần 2: Phát triển một ứng dụng bằng Spring Roo
- Phần 3: Phát triển các add-on Spring Roo
- Phần 4: Phát triển ứng dụng nhanh chóng trong đám mây với Spring Roo và Cloud Foundry
- Duyệt mã với Spring Roo
trong khung nhìn web của Mã nguồn của Spring Roo này.
- Tìm hiểu về giao diện java.lang.Comparable.
- Đọc tài liệu hướng dẫn Spring Roo về cách thiết lập một dự án và kho lưu trữ
Maven theo mã Google.
- Làm theo tài liệu hướng dẫn Spring Roo để đăng ký add-on với RooBot.
- Trong Vùng nguồn mở trên
developerWorks, tìm thông tin hướng dẫn, các công cụ và các bản cập nhật dự
án rộng lớn để giúp bạn phát triển với các công nghệ nguồn mở và sử dụng chúng với
các sản phẩm của IBM.
- Trên vùng công nghệ Java của
developerWorks, hãy tìm các bài viết, các hướng dẫn, các diễn đàn và nhiều
hơn nữa về mọi khía cạnh lập trình Java.
- Theo sát với các sự
kiện kỹ thuật và các webcast của developerWorks tập trung vào một loạt các
sản phẩm của IBM và các xu hướng của ngành công nghệ thông tin.
- Tham dự một hướng
dẫn Trực tiếp miễn phí trên developerWorks! để tăng tốc độ nhanh chóng trên
các sản phẩm và các công cụ của IBM, cũng như các xu hướng của ngành công nghệ thông
tin.
- Nghe developerWorks podcasts để biết các cuộc phỏng vấn thú vị và các cuộc thảo
luận cho các nhà phát triển phần mềm.
- Theo dõi developerWorks trên
Twitter.
- Xem các trình
diễn theo yêu cầu trên developerWorks trải rộng từ các trình diễn cài đặt và
thiết lập sản phẩm dành cho người mới bắt đầu đến các chức năng nâng cao cho các nhà
phát triển có kinh nghiệm.
Lấy sản phẩm và công nghệ
- Truy cập kho lưu trữ Spring Roo để tải về ảnh chụp màn hình mã hiện có.
- Tải về phiên bản mới nhất
của Spring Roo, 1.2.0.RC1 từ trang web của dự án.
- Tải về mã nguồn đầy đủ của
add-on
compareTo từ kho lưu trữ mã của Google.
- Truy cập phần mềm dùng thử của
IBM (có sẵn để tải về hoặc trên đĩa DVD) và đổi mới dự án phát triển nguồn
mở tiếp theo của bạn bằng cách sử dụng phần mềm chủ yếu dành cho các nhà phát
triển.
Thảo luận
- Kết nối với những người dùng
developerWorks khác trong khi khám phá các blog, các diễn đàn, các nhóm và
wiki theo hướng nhà phát triển. Giúp xây dựng nhóm Nguồn mở thế giới thực cho cộng đồng developerWorks.

Shekhar Gulati là một nhà tư vấn Java làm việc với Xebia India. Ông có sáu năm kinh nghiệm làm việc trong lĩnh vực Java. Ông có nhiều kinh nghiệm trong các dự án danh mục Spring, ví dụ như Spring, Spring-WS, Spring Roo, v.v. Các mối quan tâm của ông là Spring, cơ sở dữ liệu NoSQL, Hadoop, khung công tác RAD như Spring Roo, điện toán đám mây (chủ yếu là các dịch vụ PaaS như Google App Engine, CloudFoundry, OpenShift), Hadoop. Ông là một tác giả năng động viết bài cho các trang Javalobby, Developer.com, IBM developerWorks và blog riêng của ông tại http://whyjava.wordpress.com/. Bạn có thể theo dõi ông trên twitter @ http://twitter.com/#!/shekhargulati.