領先一步
VMware 提供訓練和認證,以加速您的進展。
瞭解更多Java 企業應用程式可以呈現多種形式。根據其需求,開發人員需要決定其應用程式需要哪些特定的架構層。到目前為止,Spring Roo 採取了務實的方法,以減少服務外觀、儲存庫或 DAO 層所引入的通常不必要的複雜性。新發布的 Spring Roo 1.2.0.M1 (請參閱公告) 包含針對可根據應用程式需求量身定制的架構層的經常 要求 的支援。本文概述了 Roo 的新服務和儲存庫層功能。
雖然現在有許多新的分層和持久性選擇可用,但預設情況下,Roo 將繼續預設支援 JPA Active Record Entity。但是,您可以透過新增更多服務或儲存庫層(詳情如下)來輕鬆變更現有的應用程式。如果您新增新的層,Roo 將自動變更消費者層或服務層中的 ITD。例如,Roo 將自動變更您的應用程式,以在現有的 MVC 控制器、GWT 定位器、整合測試或給定網域類型的隨需資料中注入並呼叫新的服務層。
在 Roo 1.2.0.M1 版本中,Roo 核心現在有三個選項可支援資料持久性:JPA 實體(Active Record 風格)、JPA 儲存庫和 MongoDB 儲存庫。Spring Data Neo4J 的支援目前正在開發中,應很快以 Roo 外掛程式 的形式提供。
自 Spring Roo 的第一個版本以來,Active record 風格的 JPA 實體一直是預設設定,並且將繼續如此。為了為 JPA 持久性設定您的專案,您可以執行 jpa setup 命令
roo> jpa setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT
這會設定您的專案以使用 Hibernate 物件關聯式對應器以及記憶體資料庫 (HSQLDB)。Roo 支援的 Active record 風格 JPA 實體使用 @RooEntity
註解,它負責提供持久性識別符號欄位及其存取器和變更器。此外,此註解還會建立典型的 CRUD 方法來支援資料存取。
roo> entity --class ~.domain.Pizza
此命令將建立 Pizza 網域類型以及 Active record 風格的方法,以持久化、更新、讀取和刪除您的實體。以下範例還包含許多欄位,這些欄位可以直接新增到 Java 來源中,或透過 Roo shell 的 field 命令新增。
@RooJavaBean
@RooToString
@RooEntity
public class Pizza {
@NotNull
@Size(min = 2)
private String name;
private BigDecimal price;
@ManyToMany(cascade = CascadeType.ALL)
private Set<Topping> toppings = new HashSet<Topping>();
@ManyToOne
private Base base;
}
需要儲存庫/DAO 層而不是預設 Roo JPA「Active Record」型持久性方法的開發人員,可以透過為給定的 JPA 網域類型建立 Spring Data JPA 支援的儲存庫來實現。透過 jpa setup
命令為 JPA 持久性設定您的專案後,此功能會透過使用 Roo 的 @RooJpaEntity
註解網域類型來自動提供。
roo> entity --class ~.domain.Pizza --activeRecord false
透過定義 --activeRecord false
,您可以選擇退出預設的「Active Record」風格。以下範例還包含許多欄位,這些欄位可以透過 Roo shell 的 field 命令新增。
@RooJavaBean
@RooToString
@RooJpaEntity
public class Pizza {
@NotNull
@Size(min = 2)
private String name;
private BigDecimal price;
@ManyToMany(cascade = CascadeType.ALL)
private Set<Topping> toppings = new HashSet<Topping>();
@ManyToOne
private Base base;
}
建立網域類型後,您現在可以使用 repository jpa
命令為此類型建立新的儲存庫
roo> repository jpa --interface ~.repository.PizzaRepository --entity ~.domain.Pizza
這將建立一個簡單的介面定義,該定義利用 Spring Data JPA
@RooRepositoryJpa(domainType = Pizza.class)
public interface PizzaRepository {
}
當然,您可以手動在任何介面上新增 @RooRepositoryJpa
註解,而不是在 Roo shell 中發出 repository jpa 命令。
新增 @RooRepositoryJpa
註解將觸發建立一個相當簡單的 AspectJ ITD,該 ITD 將 extends 陳述式新增到 PizzaRepository 介面,從而產生等效於此介面定義的結果
public interface PizzaRepository extends JpaRepository<Pizza, Long> {}
JpaRepository 介面是 Spring Data JPA API 的一部分,並提供開箱即用的所有 CRUD 功能。
作為 JPA 持久性的替代方案,Spring Roo 1.2 現在透過利用 Spring Data MongoDB 專案,提供 MongoDB 支援。Cloud Foundry 支援 MongoDB,它是自由開發和託管 Spring Roo 應用程式的絕佳場所。除了 MongoDB 之外,您還可以在 Cloud Foundry 中使用 MySQL 和 PostgreSQL。若要為 MongoDB 持久性設定專案,您可以使用 mongo setup 命令
roo> mongo setup
這會設定您的 Spring 應用程式內容以使用在 localhost 和預設埠上執行的 MongoDB 安裝。選用的命令屬性可讓您定義主機、埠、資料庫名稱、使用者名稱和密碼。如果您在 Cloud Foundry 上使用 MongoDB,只需在 'mongo setup' 後面加上 --cloudFoundry
,以便 Roo 可以為您自動設定一切
一旦應用程式設定為支援 MongoDB,entity mongo
和 repository mongo
命令即可使用
roo> entity mongo --class ~.domain.Pizza
此命令將建立使用 @RooMongoEntity
註解的 Pizza 網域類型。此註解負責觸發建立 ITD,該 ITD 提供 Spring Data @Id
註解欄位及其存取器和變更器。以下範例還包含許多欄位,這些欄位可以透過 Roo shell 的 field 命令新增。
@RooJavaBean
@RooToString
@RooMongoEntity
public class Pizza {
@NotNull
@Size(min = 2)
private String name;
private BigDecimal price;
@ManyToMany(cascade = CascadeType.ALL)
private Set<Topping> toppings = new HashSet<Topping>();
@ManyToOne
private Base base;
}
建立網域類型後,您現在可以使用 repository mongo 命令(或透過將 @RooRepositoryMongo
註解應用於任意介面)為此類型建立新的儲存庫
roo> repository mongo --interface ~.repository.PizzaRepository --entity ~.domain.Pizza
這將建立一個簡單的介面定義,該定義利用 Spring Data MongoDB
@RooRepositoryMongo(domainType = Pizza.class)
public interface PizzaRepository {
List<Pizza> findAll();
}
與上面看到的 Spring Data JPA 驅動儲存庫類似,此介面透過 ITD 進行擴充,該 ITD 引入了 Spring Data API 提供的 PagingAndSortingRepository,並負責提供所有必要的 CRUD 功能。此外,此介面還定義了一個「自訂」尋找器,PagingAndSortingRepository 實作未提供該尋找器:List findAll();
。Spring Roo 的 UI scaffolding 需要此方法,並且由 Spring Data MongoDB 提供的 查詢建構器機制 自動實作。
與使用 JPA 持久性的應用程式類似(有關將 JPA 與 Postgres 搭配使用的詳細資訊,請參閱此部落格文章),MongoDB 應用程式可以輕鬆部署到 VMware Cloud Foundry。以下腳本提供 Pizza Shop 範例應用程式(請參閱 /sample/pizzashop.roo)的範例,該範例已針對與 MongoDB 支援的儲存庫層一起使用進行調整
// Create a new project.
project com.springsource.pizzashop
// Create configuration for MongoDB peristence
mongo setup --cloudFoundry true
// Define domain model.
entity mongo --class ~.domain.Base --testAutomatically
field string --fieldName name --sizeMin 2 --notNull --class ~.domain.Base
entity mongo --class ~.domain.Topping --testAutomatically
field string --fieldName name --sizeMin 2 --notNull --class ~.domain.Topping
entity mongo --class ~.domain.Pizza --testAutomatically
field string --fieldName name --notNull --sizeMin 2 --class ~.domain.Pizza
field number --fieldName price --type java.lang.Float
field set --fieldName toppings --type ~.domain.Topping
field reference --fieldName base --type ~.domain.Base
entity mongo --class ~.domain.PizzaOrder --testAutomatically
field string --fieldName name --notNull --sizeMin 2 --class ~.domain.PizzaOrder
field string --fieldName address --sizeMax 30
field number --fieldName total --type java.lang.Float
field date --fieldName deliveryDate --type java.util.Date
field set --fieldName pizzas --type ~.domain.Pizza
// Add layer support.
repository mongo --interface ~.repository.ToppingRepository --entity ~.domain.Topping
repository mongo --interface ~.repository.BaseRepository --entity ~.domain.Base
repository mongo --interface ~.repository.PizzaRepository --entity ~.domain.Pizza
repository mongo --interface ~.repository.PizzaOrderRepository --entity ~.domain.PizzaOrder
service --interface ~.service.ToppingService --entity ~.domain.Topping
service --interface ~.service.BaseService --entity ~.domain.Base
service --interface ~.service.PizzaService --entity ~.domain.Pizza
service --interface ~.service.PizzaOrderService --entity ~.domain.PizzaOrder
// Create a Web UI.
web mvc setup
web mvc all --package ~.web
// Package the application into a war file.
perform package
// Deploy and start the application in Cloud Foundry
cloud foundry login
cloud foundry deploy --appName roo-pizzashop --path /target/pizzashop-0.1.0.BUILD-SNAPSHOT.war --memory 512
cloud foundry create service --serviceName pizzashop-mongo --serviceType mongodb
cloud foundry bind service --serviceName pizzashop-mongo --appName roo-pizzashop
cloud foundry start app --appName roo-pizzashop
「即時」範例應用程式目前部署在 Cloud Foundry 上:http://roo-pizzashop.cloudfoundry.com/
根據 Roo 的慣例,所有功能都將透過 AspectJ ITD 引入,因此為開發人員提供了一個乾淨的畫布,用於實作不自然地適合網域實體的自訂業務邏輯。服務層的其他常見用例是安全性或整合遠端處理(例如 Web 服務)。如需更詳細的討論,請參閱 Spring Roo 參考指南中的架構章節。
將服務層整合到 Roo 專案中類似於儲存庫層,方法是直接使用 @RooService 註解或 Roo shell 中的 service 命令
roo> service --interface ~.service.PizzaService --entity ~.domain.Pizza
此命令將在定義的套件中建立 PizzaService
介面,並在同一套件中額外建立 PizzaServiceImpl
(可以透過選用的 --class
屬性自訂 PizzaServiceImpl
的名稱和套件)。
@RooService(domainTypes = { Pizza.class })
public interface PizzaService {
}
遵循 Roo 慣例,預設 CRUD 方法定義可以在 AspectJ ITD 中找到
void savePizza(Pizza pizza);
Pizza findPizza(Long id);
List<Pizza> findAllPizzas();
List<Pizza> findPizzaEntries(int firstResult, int maxResults);
long countAllPizzas();
Pizza updatePizza(pizza pizza);
void deletePizza(Pizza pizza);
同樣,PizzaServiceImpl 也相當簡單
public class PizzaServiceImpl implements PizzaService {}
透過 AspectJ ITD,PizzaServiceImpl
類型預設使用 @Service
和 @Transactional
註解進行註解。此外,ITD 將在目標類型中引入以下方法和欄位
@Autowired PizzaRepository pizzaRepository;
public void savePizza(Pizza pizza) {
pizzaRepository.save(pizza);
}
public Pizza findPizza(Long id) {
return pizzaRepository.findOne(id);
}
public List<Pizza> findAllPizzas() {
return pizzaRepository.findAll();
}
public List<Pizza> findPizzaEntries(int firstResult, int maxResults) {
return pizzaRepository.findAll(new PageRequest(firstResult / maxResults, maxResults)).getContent();
}
public long countAllPizzas() {
return pizzaRepository.count();
}
public Pizza updatePizza(Pizza pizza) {
return pizzaRepository.save(pizza);
}
public void deletePizza(Pizza pizza) {
pizzaRepository.delete(pizza);
}
如您所見,Roo 將偵測給定的網域類型是否存在持久性提供者層,並自動注入此元件,以便將所有服務層呼叫委派給此層。如果不存在持久性(或其他「較低層級」)層,則服務層 ITD 將僅提供方法存根。
使用 Spring Roo 1.2,將架構層或持久性選項新增到新的或現有的 Spring Roo 管理的應用程式中變得幾乎微不足道。無需考慮為新的持久性提供者設定您的應用程式,或將對新層的參考注入到您的 Spring MVC 控制器、GWT UI 或整合測試中 - Roo 將為您完成這一切!
憑藉 Spring Roo 1.2 中可用的分層支援,我們期望在未來看到更多的持久性提供者。Spring Data Neo4J 的儲存庫分層整合目前正在開發中,應很快以 Roo 外掛程式 的形式提供。
如果您想輕鬆試用這些新功能,何不建置您自己的 MongoDB 支援的 Pizza Shop 應用程式 版本,並將其部署到 Cloud Foundry?借助這些新的 Roo 1.2.0.M1 功能,這只需幾分鐘即可完成。
鑑於 Spring Roo 1.2.0.M1 是一個里程碑版本,您應該繼續為生產專案使用 Roo 1.1.5。但是,我們確實認為 Roo 1.2 M1 適合探索新功能或快速專案。
Roo 團隊始終歡迎社群的回饋。