1. 什么是Spring Data REST
Spring Data JPA是基於Spring Data 的Repository之上,可以將Repository自動輸出為REST資源。目前Spring Data REST支持將Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j、Spring Data Gemfire以及Spring Data Cassandra的Repository自動轉換成REST服務。
2. Spring mvc中配置使用Spring Data REST
Spring Data REST的配置是定義在RepositoryRestMvcConfiguration配置類中已經配置好了,我們可以通過繼承此類或者直接在自己的配置類上@Import此配置類
3. Spring boot的支持
Spring Boot對Spring Data REST的自動配置放置在rest包中
通過SpringBootRestConfiguration類的源碼我們可以得出,Spring Boot已經為我們自動配置了RepositoryRestConfiguration,所以在Spring boot中使用Spring Data REST只需引入spring-boot-starter-data-rest的依賴,無須任何配置即可使用。
Spring boot通過在application.properties中配置以“spring.data.rest”為前綴的屬性來配置RepositoryRestConfiguration
1 import org.springframework.beans.factory.annotation.Autowired; 2 import org.springframework.core.annotation.Order; 3 import org.springframework.data.rest.core.config.RepositoryRestConfiguration; 4 import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter; 5 import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; 6 7 @Order(0) 8 class SpringBootRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter { 9 10 @Autowired(required = false) 11 private Jackson2ObjectMapperBuilder objectMapperBuilder; 12 13 @Autowired 14 private RepositoryRestProperties properties; 15 16 @Override 17 public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 18 this.properties.applyTo(config); 19 } 20 21 @Override 22 public void configureJacksonObjectMapper(ObjectMapper objectMapper) { 23 if (this.objectMapperBuilder != null) { 24 this.objectMapperBuilder.configure(objectMapper); 25 } 26 } 27 28 }
1 @ConfigurationProperties(prefix = "spring.data.rest") 2 public class RepositoryRestProperties { 3 4 /** 5 * Base path to be used by Spring Data REST to expose repository resources. 6 */ 7 private String basePath; 8 9 /** 10 * Default size of pages. 11 */ 12 private Integer defaultPageSize; 13 14 /** 15 * Maximum size of pages. 16 */ 17 private Integer maxPageSize; 18 19 /** 20 * Name of the URL query string parameter that indicates what page to return. 21 */ 22 private String pageParamName; 23 24 /** 25 * Name of the URL query string parameter that indicates how many results to return at 26 * once. 27 */ 28 private String limitParamName; 29 30 /** 31 * Name of the URL query string parameter that indicates what direction to sort 32 * results. 33 */ 34 private String sortParamName; 35 36 /** 37 * Strategy to use to determine which repositories get exposed. 38 */ 39 private RepositoryDetectionStrategies detectionStrategy = RepositoryDetectionStrategies.DEFAULT; 40 41 /** 42 * Content type to use as a default when none is specified. 43 */ 44 private MediaType defaultMediaType; 45 46 /** 47 * Return a response body after creating an entity. 48 */ 49 private Boolean returnBodyOnCreate; 50 51 /** 52 * Return a response body after updating an entity. 53 */ 54 private Boolean returnBodyOnUpdate; 55 56 /** 57 * Enable enum value translation via the Spring Data REST default resource bundle. 58 * Will use the fully qualified enum name as key. 59 */ 60 private Boolean enableEnumTranslation; 61 62 public String getBasePath() { 63 return this.basePath; 64 } 65 66 public void setBasePath(String basePath) { 67 this.basePath = basePath; 68 } 69 70 public Integer getDefaultPageSize() { 71 return this.defaultPageSize; 72 } 73 74 public void setDefaultPageSize(Integer defaultPageSize) { 75 this.defaultPageSize = defaultPageSize; 76 } 77 78 public Integer getMaxPageSize() { 79 return this.maxPageSize; 80 } 81 82 public void setMaxPageSize(Integer maxPageSize) { 83 this.maxPageSize = maxPageSize; 84 } 85 86 public String getPageParamName() { 87 return this.pageParamName; 88 } 89 90 public void setPageParamName(String pageParamName) { 91 this.pageParamName = pageParamName; 92 } 93 94 public String getLimitParamName() { 95 return this.limitParamName; 96 } 97 98 public void setLimitParamName(String limitParamName) { 99 this.limitParamName = limitParamName; 100 } 101 102 public String getSortParamName() { 103 return this.sortParamName; 104 } 105 106 public void setSortParamName(String sortParamName) { 107 this.sortParamName = sortParamName; 108 } 109 110 public RepositoryDetectionStrategies getDetectionStrategy() { 111 return this.detectionStrategy; 112 } 113 114 public void setDetectionStrategy(RepositoryDetectionStrategies detectionStrategy) { 115 this.detectionStrategy = detectionStrategy; 116 } 117 118 public MediaType getDefaultMediaType() { 119 return this.defaultMediaType; 120 } 121 122 public void setDefaultMediaType(MediaType defaultMediaType) { 123 this.defaultMediaType = defaultMediaType; 124 } 125 126 public Boolean getReturnBodyOnCreate() { 127 return this.returnBodyOnCreate; 128 } 129 130 public void setReturnBodyOnCreate(Boolean returnBodyOnCreate) { 131 this.returnBodyOnCreate = returnBodyOnCreate; 132 } 133 134 public Boolean getReturnBodyOnUpdate() { 135 return this.returnBodyOnUpdate; 136 } 137 138 public void setReturnBodyOnUpdate(Boolean returnBodyOnUpdate) { 139 this.returnBodyOnUpdate = returnBodyOnUpdate; 140 } 141 142 public Boolean getEnableEnumTranslation() { 143 return this.enableEnumTranslation; 144 } 145 146 public void setEnableEnumTranslation(Boolean enableEnumTranslation) { 147 this.enableEnumTranslation = enableEnumTranslation; 148 } 149 150 public void applyTo(RepositoryRestConfiguration configuration) { 151 if (this.basePath != null) { 152 configuration.setBasePath(this.basePath); 153 } 154 if (this.defaultPageSize != null) { 155 configuration.setDefaultPageSize(this.defaultPageSize); 156 } 157 if (this.maxPageSize != null) { 158 configuration.setMaxPageSize(this.maxPageSize); 159 } 160 if (this.pageParamName != null) { 161 configuration.setPageParamName(this.pageParamName); 162 } 163 if (this.limitParamName != null) { 164 configuration.setLimitParamName(this.limitParamName); 165 } 166 if (this.sortParamName != null) { 167 configuration.setSortParamName(this.sortParamName); 168 } 169 if (this.detectionStrategy != null) { 170 configuration.setRepositoryDetectionStrategy(this.detectionStrategy); 171 } 172 if (this.defaultMediaType != null) { 173 configuration.setDefaultMediaType(this.defaultMediaType); 174 } 175 if (this.returnBodyOnCreate != null) { 176 configuration.setReturnBodyOnCreate(this.returnBodyOnCreate); 177 } 178 if (this.returnBodyOnUpdate != null) { 179 configuration.setReturnBodyOnUpdate(this.returnBodyOnUpdate); 180 } 181 if (this.enableEnumTranslation != null) { 182 configuration.setEnableEnumTranslation(this.enableEnumTranslation); 183 } 184 } 185 186 }
實戰演練
1.定義實體類
2.定義Repository
3.測試
1 @Entity 2 public class Person { 3 @Id 4 @GeneratedValue 5 private Long id; 6 7 private String name; 8 9 private Integer age; 10 11 private String address; 12 13 14 15 public Person() { 16 super(); 17 } 18 public Person(Long id, String name, Integer age, String address) { 19 super(); 20 this.id = id; 21 this.name = name; 22 this.age = age; 23 this.address = address; 24 } 25 public Long getId() { 26 return id; 27 } 28 public void setId(Long id) { 29 this.id = id; 30 } 31 public String getName() { 32 return name; 33 } 34 public void setName(String name) { 35 this.name = name; 36 } 37 public Integer getAge() { 38 return age; 39 } 40 public void setAge(Integer age) { 41 this.age = age; 42 } 43 public String getAddress() { 44 return address; 45 } 46 public void setAddress(String address) { 47 this.address = address; 48 } 49 50 51 }
public interface PersonRepository extends JpaRepository<Person, Long> { Person findByNameStartsWith(@Param("name")String name); }
GET請求
http://localhost:8080/psersons 獲取列表
http://localhost:8080/1 獲取id為1的對象
在上面的自定義Repository中定義了findByNameStartsWith方法,若想此方法也暴露為REST資源,需做如下修改
public interface PersonRepository extends JpaRepository<Person, Long> { @RestResource(path = "nameStartsWith", rel = "nameStartsWith") Person findByNameStartsWith(@Param("name")String name); }
此時使用GET訪問http://localhost:8080/persons/search/nameStartsWith?name=kevin,可實現查詢操作
http://localhost:8080/persons/?page=1&size=2 分頁查詢,page-1即第2頁,size=2即每頁數量為2
http://localhost:8080/persons/?sort=age,desc 排序,即按照age屬性倒序
POST請求
http://localhost:8080/persons ,並將數據放到請求體中 保存
http://localhost:8080/persons/21,並將數據放到請求體中 更新
DELETE請求
http://localhost:8080/persons/21 刪除
4. 定制
(1)定制根路徑
在上面的實戰例子中,我們訪問的REST資源的路徑是在根目錄下的,即http://localhost:8080/persos,如果我們需要定制根路徑的話,只需要在Spring Boot的application.properties中添加定義 spring.data.rest.base-path= /api 此時REST資源的路徑變成了http://localhost:8080/api/persons
(2)定制節點路徑
上例實戰中,我們的節點路徑為http://localhost:8080/persons,這是Spring Data REST的默認規則,就是在實體類之后加“s”來形成路徑。如果要對映射的名稱進行修改的話,需要在實體類Repository上使用@RepositoryRestResource注解的path屬性進行修改
1 @RepositoryRestResource(path = "people") 2 public interface PersonRepository extends JpaRepository<Person, Long> { 3 4 @RestResource(path = "nameStartsWith", rel = "nameStartsWith") 5 Person findByNameStartsWith(@Param("name")String name); 6 7 }
此時訪問REST服務的地址變成http://localhost:8080/api/people