为Spring Boot 启用超媒体支持

  超媒体是一种创建自描述API的方式,即API所返回的资源中会包含相关资源的链接,客户端只需要了解最少的API URL 信息就能导航整个应用API。

  Spring HATEOAS项目为Spring提供了超链接的支持,它提供了一些类和资源装配器(assembler),在SpringMVC控制器返回资源之前能够为其添加链接。

⒈,添加hateoas starter依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>

⒉,创建实体,实体资源类【即可以携带链接信息的实体】,转换工具类

  1.实体类

public class User {
    private int id;
    private String username;
    private String password;
    private int age;

    public User() {
    }

    public User(int id, String username, String password, int age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

  2,实体资源类【即可以携带链接信息的实体】,通过继承 RepresentationModel,从而继承了一个Link对象的列表和管理链接列表的方法。

import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.server.core.Relation;

/**
 * User的资源类,即在User类的基础上携带资源链接
 * 用于替换 EntityModel
 * 通过继承 RepresentationModel,从而继承了一个Link对象的列表和管理链接列表的方法
 */
@Relation(value = "user", collectionRelation = "users") //规定json中Key的名称,默认为资源名称
public class UserEntityModel extends RepresentationModel<UserEntityModel> {

    // 和User实体具有相同的属性
    private int id;
    private String username;
    private String password;
    private int age;

    //接收User对象并复制相关属性
    public UserEntityModel(User user){
        this.id = user.getId();
        this.username = user.getUsername();
        this.password = user.getPassword();
        this.age = user.getAge();
    }

    public int getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public int getAge() {
        return age;
    }
}

  3,转换工具类【资源适配器】

import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;

/**
 * 资源装配器
 * 一个将User对象转换为可以携带资源链接的User封装类的工具类
 */
public class UserRepresentationModelAssembler extends RepresentationModelAssemblerSupport<User, UserEntityModel> {

    /**
     * 默认构造器,将告诉父类在创建User封装类中的链接时
     * 将会使用 UserController 来确定所有URL的基础路径
     */
    public UserRepresentationModelAssembler(){
        super(UserController.class,UserEntityModel.class);
    }

    /**
     * 基于 User实例创建User封装类实例。
     * 如果 User封装类有默认构造器,则该方法是可选的
     * @param entity
     * @return
     */
    @Override
    protected UserEntityModel instantiateModel(User entity) {
        return new UserEntityModel(entity);
    }

    /**
     * 基于 User实例创建User封装类实例并填充其self链接属性
     * 以下代码是指链接的URL是根据User对象的id属性确定的。
     * toModel()方法在创建实例时将会调用instantiateModel()方法
     * @param entity
     * @return
     */
    @Override
    public UserEntityModel toModel(User entity) {
        return createModelWithId(entity.getId(),entity);
    }
}

⒊,更改控制器代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


/**
 * 对API响应内容启用超媒体支持
 * 即API返回的资源信息中会包含相关资源的链接
 * Spring HATEOAS项目为Spring提供了超链接支持,在SpringMVC控制器返回资源之前能够为其添加链接
 * EntityModel代表资源,CollectionModel代表某种资源的集合
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/get")
    public ResponseEntity<List<User>> getUsers(){
        ResponseEntity<List<User>> datas = ResponseEntity.ok(userRepository.getUsers());
        return datas;
    }

    @GetMapping("/get2")
    public CollectionModel<EntityModel<User>> getUsersWithR(){
        List<User> userList = userRepository.getUsers();
        CollectionModel<EntityModel<User>> recentCollectionModel = CollectionModel.wrap(userList);
        //recentCollectionModel.add(Link.of("http://localhost:10035/user/get2","recents"));   //垃圾的硬编码形式
        //recentCollectionModel.add(WebMvcLinkBuilder.linkTo(UserController.class).slash("get2").withRel("recents")); //方式1,还是有硬编码的因素
        recentCollectionModel.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class).getUsersWithR()).withRel("recents"));   //方式2,推荐

        return recentCollectionModel;
    }

    @GetMapping("/get3")
    public CollectionModel<UserEntityModel> getUserWithA(){
        List<User> userList = userRepository.getUsers();
        UserRepresentationModelAssembler assembler = new UserRepresentationModelAssembler();
        CollectionModel<UserEntityModel> modelList = assembler.toCollectionModel(userList); //为用户列表添加资源链接
        modelList.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class).getUserWithA()).withRel("recents"));    //为根节点添加资源链接
        return modelList;
    }
}

 

posted @ 2020-12-02 10:03  SpringCore  阅读(335)  评论(0编辑  收藏  举报