搶先一步
VMware 提供培訓和認證,以加速您的進展。
了解更多超過 12 個專案修正了 300 多個問題,使得很難追蹤自上次發布以來發生的事情。因此,以下是我們在上次迭代期間一直在開發的一些新功能的更詳細摘錄。
自 Dijkstra 發布系列以來,我們已經能夠透過 JPA 後端儲存庫中的 @EntityGraph
註釋引用在實體上宣告的具名實體圖。在下面的範例中,這強制firstName 和 lastName 被急切載入,而所有其他屬性保持延遲載入。
@Entity
@NamedEntityGraphs(
@NamedEntityGraph(name = "with-tags",
attributeNodes = { @NamedAttributeNode("tags") }))
class Product {
@ManyToMany
Set<Tag> tags;
// other properties omitted
}
interface ProductRepository extends Repository<Customer, Long> {
@EntityGraph("with-tags")
Product findOneById(Long id);
}
Gosling 版本現在將我們的 JPA 2.1 故事向前推進一步,將其擴展到 ad-hoc 提取圖定義。透過在查詢方法上透過 @EntityGraph(attributePaths = …)
顯式指定屬性,您無需在實體上擁有 NamedEntityGraph
註釋。
@Entity
class Product {
@ManyToMany
Set<Tag> tags;
// other properties omitted
}
interface ProductRepository extends Repository<Customer, Long> {
@EntityGraph(attributePaths = {"tags"})
Product findOneById(Long id);
}
Spring Data Web 支援已經允許您在控制器處理常式方法中宣告 Pageable
類型的參數。新引入的 Querydsl 整合擴展了該功能,使您可以接收直接從 HTTP 請求的查詢字串衍生的現成可用的 Predicate
。當配置 @EnableSpringDataWebSupport
並且在類別路徑上找到 Querydsl 時,該功能會自動啟用。
如果 Predicate
在沒有進一步配置的情況下使用,我們將嘗試從該方法的回傳類型解析 Predicate
解析的根類型,儘管在大多數情況下,透過 @QuerydslPredicate(root = …)
顯式宣告所需的類型引用可能更好。有了這個設定,查詢字串屬性將綁定到該類型的匹配屬性,從而建立例如
QUser.user.firstname.eq("Dave").and(QUser.user.lastname.eq("Matthews"))
從使用預設屬性類型相依綁定的 ?firstname=Dave&lastname=Matthews
。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Controller
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
static class UserController {
private final UserRepository repository;
@RequestMapping(value = "/", method = RequestMethod.GET)
String index(Model model,
@QuerydslPredicate(root = User.class) Predicate predicate,
Pageable pageable) {
model.addAttribute("users", repository.findAll(predicate, pageable));
return "index";
}
}
}
現在,使用預設(等於)綁定並不總是有意義的,而是每個屬性的專用綁定或特定類型的綁定。為了實現這一點,只需透過提供一個可以透過 @QuerydslPredicate(bindings = …)
註冊或簡單地由儲存庫實現的 QuerydslBinderCustomizer
來覆寫預設值。
interface UserRepository extends CrudRepository<User, String>,
QueryDslPredicateExecutor<User>,
QuerydslBinderCustomizer<QUser> {
// Query methods go here
@Override
default public void customize(QuerydslBindings bindings, QUser user) {
bindings.bind(user.nationality).first(
(path, value) -> path.equalsIgnoreCase(value)); // 1
bindings.bind(String.class).first(
(StringPath path, String value) -> path.containsIgnoreCase(value)); // 2
bindings.excluding(user.password);
}
}
正如您所看到的,我們利用 Java 8 lambda 以及 Querydsl 的類型安全屬性引用來定義特定屬性的綁定 (1) 或給定類型的所有屬性的綁定 (2)。使用 QuerydslBindings.excluding
允許您從查詢中移除路徑。
在 Spring Data 範例儲存庫 中找到一個完整的工作範例,並查閱 參考文件 以了解詳細資訊。
Spring Data Commons 中引入的 Querydsl 支援(參見上方)已整合到 Spring Data REST 中。這表示您可以透過將簡單的屬性查詢參數附加到請求 URI 來過濾您的集合資源。
在公開 Starbucks 商店位置的 Spring Data REST 範例中,請注意 StoreRepository 現在如何同時實現 QueryDslPredicateExecutor
和 QuerydslBinderCustomizer<QStore>
,就像上面描述的那樣。
Spring Data REST 公開的商店集合資源將允許您發出如下請求
$ http :8080/api/stores?address.city=York
{
"_embedded": {
"stores": [
{
"_links": {
…
},
"address": {
"city": "New York",
"location": { "x": -73.938421, "y": 40.851 },
"street": "803 W 181st St",
"zip": "10033-4516"
},
"name": "Washington Hgts/181st St"
},
{
"_links": {
…
},
"address": {
"city": "New York",
"location": { "x": -73.939822, "y": 40.84135 },
"street": "4001 Broadway",
"zip": "10032-1508"
},
"name": "168th & Broadway"
},
…
]
},
"_links": {
…
},
"page": {
"number": 0,
"size": 20,
"totalElements": 209,
"totalPages": 11
}
}
請注意,它只會回傳城市以 "York" 結尾的商店,就像在 StoresRepository
中 QuerydslBinderCustomizer
的實作中所定義的那樣。
我們目前正在研究以更明顯的方式宣傳這種查詢機制的選項,例如使用範本變數,甚至提供進階的對應功能來自訂要使用的請求參數名稱。
Spring Data REST 的 Gosling 版本附帶了一個額外的模組,該模組包裝了 Mike Kelly 的 HAL 瀏覽器 並對其進行了一些調整,以利用我們公開的 API 元資料。要將瀏覽器與您的應用程式一起使用,只需將 spring-data-rest-hal-browser
模組添加到您的專案中,您的 API 根目錄將為接受 text/html
的請求提供瀏覽器。當然,預設情況下或如果您使用基於 JSON 的 Accept
標頭,仍然會提供標準 HAL 回應。
圖 1. - HAL 瀏覽器(點擊放大)
雖然 Spring Data REST 模組可以輕鬆地將瀏覽器添加到您的應用程式中,但它也對瀏覽器進行了輕微調整。當您點擊按鈕以觸發非 GET
請求時,瀏覽器通常會開啟一個模態對話框,該對話框需要一些原始 JSON 輸入。當然,如果您知道自己在做什麼,這很好,但它有點容易出錯,而且不是很方便,因為您必須了解伺服器期望的資料結構。
Spring Data REST 透過利用 profile
連結關係公開系統公開的類型的 JSON 結構描述文件,這使得結構描述可以被泛型發現,而無需將發現邏輯綁定到 Spring Data REST 本身。我們提供的瀏覽器實例將查閱該結構描述元資料,如果它可以找到一些元資料,則會將其傳遞給 JSON Editor,以使用完全從 JSON 結構描述派生的表單替換預設對話框。
圖 2. - 基於 JSON Editor 的 POST 表單(點擊放大)
請參閱表單如何允許新增行項目,因為結構描述將其公開為陣列。價格和訂單日期欄位被標記為唯讀,location 欄位允許從具有國際化值的列舉中選擇值。
範例專案可以在 GitHub 上找到。
正如您在上面的螢幕截圖中看到的,restbucks:orders
連結附帶了人類可讀的描述。描述是使用 _links.$rel.title
鍵從一個可選的資源捆綁包 rest-messages
中提取的,以定義一個可讀的值。該範例使用 rest-messages.properties
作為後備資源捆綁包,但也包含一個 rest-messages_de.properties
,用於為發送設定為 de
的 Accept-Language
標頭的客戶端回傳德語標籤。
相同的資源包可用於國際化列舉值,以便在客戶端以人類可讀的方式使用。為了不破壞現有的應用程式,必須透過 RepositoryRestConfiguration.setEnableEnumTranslation(…)
顯式啟用此功能。有關翻譯的詳細資訊可以在 EnumTranslationConfiguration
上配置。
對 Pivotal GemFire 8.1 和 Apache Geode 的支援是 Spring Data GemFire 1.7 中最顯著的補充。Pivotal GemFire 早些時候已提交給 Apache Incubator,Spring Data 團隊迅速回應,將 支援 納入 Spring Data GemFire 中。
此外,還添加了幾個其他功能,以簡化使用 Spring 開發 GemFire 和 Apache Geode 應用程式。例如,開發人員現在可以使用註釋來定義特定於應用程式網域物件的到期策略。
@TimeToLiveExpiration(
timeout = "@expirationSettings['spel.defined.timeout']" action="DESTROY")
@IdleTimeoutExpiration(
timeout = "1800" action="${property.placeholder.defined.action}")
class ApplicationDomainObject { … }
基於到期的註釋支援 SpEL 和 Spring Property Placeholder 值。若要啟用基於註釋的到期策略,您只需在 GemFire 區域上配置 Spring Data GemFire 的 CustomExpiry 實作,AnnotationBasedExpiration,用於 TTL 和 TTI 中的任一或兩者。
<gfe:partitioned-region id="Example" persistent="false" …>
<gfe:custom-entry-ttl>
<bean class="….gemfire.support.AnnotationBasedExpiration" factory-method="forTimeToLive"/>
</gfe:custom-entry-ttl>
<gfe:custom-entry-tti ref="ttiExpiration"/>
</gfe:partitioned-region>
<bean id="ttiExpiration" class="….gemfire.support.AnnotationBasedExpiration" factory-method="forIdleTimeout">
<constructor-arg ref="defaultExpirationAttributes"/>
</bean>
<bean id="defaultExpirationAttributes" class="….ExpirationAttributes">
<constructor-arg value="600"/>
<constructor-arg value="#{T(….ExpirationAction).DESTROY}"/>
</bean>
請參閱參考指南,以 了解更多資訊。接下來,添加了通過註釋支持儲存庫查詢方法 OQL 擴展。
interface CustomerRepository implements CrudRepository<Cutomer, Long> {
@Trace
@Limit(25)
@Import("org.exmple.Customer")
@Hint("CustomerLastNameIdx")
List<Customer> findByLastNameOrderByLastNameAsc(String lastName);
}
@Trace
啟用個別 OQL 語句除錯。@Limit
限制查詢結果集中的結果數量,而 @Import
允許應用程式區分相似命名的物件類型。例如,您的應用程式可能同時定義 org.example.app.core.Customer
和 org.example.app.vendor.xyz.Customer
類型。有關更多詳細資訊,請參閱 GemFire 的 doc。@Hint
啟用 OQL 提示的使用,以識別適用於查詢的索引。在此處瞭解有關 OQL 擴展的更多資訊。
最後,Spring Data GemFire 使用 Spring Data GemFire XML 資料命名空間提供對 GemFire 快取和區域快照 的支援。
<gfe:partitioned-region id="Example" persistent="false" … />
<gfe-data:snapshot-service id="exampleRegionSnapshotService" region-ref="Example">
<gfe-data:snapshot-import location="/path/to/import/example.snapshot"/>
<gfe-data:snapshot-export locator="/path/to/export/example.snapshot"/>
</gfe-data:snapshot-service>
您可以進一步了解 Spring Data GemFire 如何支援匯入上的 ZIP 檔案、使用 Spring ApplicationEvents
來觸發匯入和匯出快照,以及如何適當地篩選匯入和匯出的資料 在此。
自從我們被要求為 Spring Data 儲存庫提供一個非常簡單的基於 Map
的實作以來已經很長一段時間了,這主要是為了各種測試目的。這些要求最終以一種略有不同的方式重振了 KeyValue 模組,與它之前存在的狀態不同。
Spring Data KeyValue 現在包含一個基本的基於 Map
的儲存庫實作,預設情況下它將使用 Spring Expression Language (SpEL) 查詢值,並根據其集合模組提供排序、分頁和 Querydsl 整合。它還公開了專用的 API,允許鍵值儲存利用儲存中的儲存特定最佳化、檢索,最重要的是,如果需要,可以執行查詢。
Spring Data KeyValue 儲存庫使用的預設查詢機制基於 SpEL,並允許您定義和運行複雜的查詢。當在 COMPILED
模式 下運行時,此方法展示了它的真正威力,因為它有效地編譯了要在值上執行的過濾表達式。或者,您也可以使用 Querydsl 表達式進行類型安全的查詢。
@Configuration
@EnableMapRepositories("com.acme.repositories")
class AppConfig {}
@KeySpace("user")
class User {
String @Id id;
String firstname;
}
interface UserRepository extends CrudRepository<User, String> {
List<String> findByFirstnameStartingWith(String firstname);
}
我們目前有針對 Ehcache、Hazelcast 和 Aerospike 的 API 擴展正在開發中,並且期待評估選項以整合 Redis,並可能移植一些 Gemfire API 來使用它。
接下來是 SpringOne2GX 在華盛頓特區 - 我們很高興在那裡見到您 - 這是與團隊聯繫、了解新功能並度過美好時光的最佳地點。同時,我們已經在為 Fowler Release Train 準備下一個服務版本,並開始為 Hopper Release Train 開發新功能(噓...我們將在 SpringOne 的 “Spring Data 的 2015 年新功能?”演講 中搶先了解 Hopper)。