如何从 HATEOAS _link属性中循环和检索值(例如检索描述)?



tl;博士

我的代码从 Restful GET 获取一个 javascript/json 对象数组。如何编写代码以循环并从 HATEOAS "_link"属性中检索描述(或任何值)以进行显示?

上下文

我继承了一个基于 Spring 的小型项目 - 它跟踪服务器、软件安装等供我们团队内部使用。它使用 Angular 前端和 Spring/java/mysql 后端作为休息的后端。

我正在将手工编码的SQL转换为JPA和"弹簧启动器数据休息">

当前 API 确实如此

当前手工编码的 SQL 连接表以提供"显示友好的结果"。

Product
---------
Product ID
Product Name
Category ID
Category
---------
Category ID
Category Name

"检索产品"sql 联接产品和类别以提供"显示友好名称"。Rest API 检索附加了此"类别名称"的"产品对象"。

Spring 数据休息域对象

产品

@Entity
@Table(name="products")
public class Products
{
private static final long serialVersionUID = 5697367593400296932L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public long id;
public String product_name;
@ManyToOne(optional = false,cascade= CascadeType.MERGE)
@JoinColumn(name = "category_id")
private ProductCategory productCategory;
public Products(){}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Products(String product_name) {
this.product_name = product_name;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public ProductCategory getProductCategory()
{
return productCategory;
}
public void setProductCategory(ProductCategory pProductCategory)
{
productCategory = pProductCategory;
}
}

产品类别

@Entity
@Table(name="productcat")
public class ProductCategory implements Serializable{
private static final long serialVersionUID = 890485159724195243L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public long id;
public String category;
@OneToMany(mappedBy = "productCategory", cascade = CascadeType.ALL)
@JsonBackReference
Set<Products> products;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Set<Products> getProducts() {
return products;
}
}

问题

我已经删除了联接,并为产品和类别添加了 Spring 存储库。"获取产品"RESTFUL API 现在返回以下列表:

{
"product_name" : "ForceFive 1.0",
"_links" : {
"self" : {
"href" : "http://localhost:8080/api/rest/products/8"
},
"products" : {
"href" : "http://localhost:8080/api/rest/products/8"
},
"productCategory" : {
"href" : "http://localhost:8080/api/rest/products/8/productCategory"
}
}

问题

如何显示"产品类别"链接的类别名称?

"productCategory" : {
"href" : "http://localhost:8080/api/rest/products/8/productCategory"
}

我最初认为我可以检索类别,然后构建一个"类别 url"到"描述"的映射。但是,网址不同:

"产品类别"网址看起来很喜欢这个: http://localhost:8080/api/rest/productcat/1

而产品具有: "产品类别" : { "href" : "http://localhost:8080/api/rest/products/8/productCategory" }

问题澄清

因此,如果 JavaScript 控制器 HTTP 获取产品:

requests.get(productsUrl, $scope).success(function(data, status){
$scope.models = data._embedded.products;  
});

那又如何?这些是步骤吗?

javascript 控制器遍历每个 data._embedded.products。 对于每个产品,代码

  • HTTP 获取产品类别网址

    产品类别" : { "href" : "http://localhost:8080/api/rest/products/8/productCategory" }

  • http 获取类别

    "产品类别": {

    "href": "http://localhost:8080/api/rest/productcat/4"
    

    },

- 将描述存储在某个地方以便在页面上重用(即将其添加到 JavaScript 对象中)

如果这些是步骤:

  • 这是很多代码
  • 对于一长串(例如 50 个产品),这是另外 100 个 HTTP GET 请求。

即使我添加一个调用来获取/缓存所有产品类别,这仍然是额外的 50 http get

奖金:

  • 易于编码
  • 运行速度快

尝试 #01:添加投影

我添加了这个投影:

public interface ProductRepository extends PagingAndSortingRepository<Products, Long>
{
@Projection(name = "dummyNameForProjection", types = { Products.class })
interface VirtualProjection
{
String getProduct_name() ;
//Get Product Category
@Value("#{target.productCategory.category}")
String getCategoryName();
}
}

但是,此 url 不返回类别名称:

http://localhost:8080/api/rest/products/4?projection=dummyNameForProjection

返回的 json

{
"product_name": "Force Five",
"_links": {
"self": {
"href": "http://localhost:8080/api/rest/products/4"
},
"products": {
"href": "http://localhost:8080/api/rest/products/4"
},
"productCategory": {
"href": "http://localhost:8080/api/rest/products/4/productCategory"
}
}
}

此外,我为这些设置了调试

logging.level.org.springframework.data=DEBUG
logging.level.org.springframework.data.rest=DEBUG
logging.level.org.hibernate=DEBUG

日志/控制台未提及任何投影。

尝试 #02:修复了D 下的投影文件,表示 D'oh。我将投影卡在存储库上而不是实体上。查看一些示例代码显示了问题。投影就是门票!

弹簧投影

@Projection(name = "dummyNameForProjection", types = { Product.class })
public interface VirtualProjection {
// this will get the attribute name from the product entity
String getProductName();
//this will get the name of the category entity related to the product
@Value("#{target.category.name}") 
String getCategoryName();

}

只需在您的请求中包含投影名称,例如:/products?projection=dummyNameForProjection

最新更新