天天看點

HATEOAS

HATEOAS(Hypermedia as the engine of application state)是 REST 架構風格中最複雜的限制,也是建構成熟 REST 服務的核心。它的重要性在于打破了用戶端和伺服器之間嚴格的契約,使得用戶端可以更加智能和自适應,而 REST 服務本身的演化和更新也變得更加容易。在了解HATEOAS之前先來看看 REST 服務按照成熟度劃分成 4 個層次:

  • 第一個層次(Level 0)的 Web 服務隻是使用 HTTP 作為傳輸方式,實際上隻是遠端方法調用(RPC)的一種具體形式。SOAP 和 XML-RPC 都屬于此類。
  • 第二個層次(Level 1)的 Web 服務引入了資源的概念。每個資源有對應的辨別符和表達。
  • 第三個層次(Level 2)的 Web 服務使用不同的 HTTP 方法來進行不同的操作,并且使用 HTTP 狀态碼來表示不同的結果。如 HTTP GET 方法來擷取資源,HTTP DELETE 方法來删除資源。
  • 第四個層次(Level 3)的 Web 服務使用 HATEOAS。在資源的表達中包含了連結資訊。用戶端可以根據連結來發現可以執行的動作。

   HATEOAS 的核心是連結,由 rel 和 href 兩個屬性組成。連結的存在使得用戶端可以動态發現其所能執行的動作。其中屬性 rel 表明了該連結所代表的關系含義

self 指向目前資源本身的連結的 rel 屬性。每個資源的表達中都應該包含此關系的連結。
edit 指向一個可以編輯目前資源的連結。
item 如果目前資源表示的是一個集合,則用來指向該集合中的單個資源。
collection 如果目前資源包含在某個集合中,則用來指向包含該資源的集合。
related 指向一個與目前資源相關的資源。
rel 屬性值 描述
search 指向一個可以搜尋目前資源及其相關資源的連結。
first、last、previous、next 這幾個 rel 屬性值都有集合中的周遊相關,分别用來指向集合中的第一個、最後一個、上一個和下一個資源。

案例:

Maven依賴

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.22</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.3</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>

    <!-- HATEOAS 的依賴 -->
    <!-- https://mvnrepository.com/artifact/org.springframework.hateoas/spring-hateoas -->
    <dependency>
        <groupId>org.springframework.hateoas</groupId>
        <artifactId>spring-hateoas</artifactId>
        <version>1.4.5</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.22</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.3.22</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.7</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.9</version>
    </dependency>


</dependencies>
      

config層中的springMvc

@Configuration
@ComponentScan("edu.nf.demo")
@EnableWebMvc
public class SpringMvc {
}
      
WebInitializer
      
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvc.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
      

entity

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Integer uid;
    private String  username;
}      

vo

@Data
public class ResultVo<T> extends RepresentationModel {


    private Integer code;
    private T       data;
    private  String  message;

}      

controller

@RestController
@RequestMapping("/api/v1")
public class Controller {


    @GetMapping("/users/{uid}")
    public ResultVo<User> getUser( @PathVariable("uid") int id){
        User use = new User(id,"user1");

        ResultVo<User> userResultVo = new ResultVo<>();

        userResultVo.setCode(HttpStatus.OK.value());
        userResultVo.setData(use);

        //添加HATEOAS
        //建立self的連接配接
        userResultVo.add(Link.of("http://localhost:8080/api/v1/users/uid"));
        //建立controller的連接配接,通過這個連結來通路所有的使用者資訊
        userResultVo.add(Link.of("http://localhost:8080/api/v1/users","controller"));
        return userResultVo;
    }

    @GetMapping("/users")
    public ResultVo<List<User>> listUser(){
       User user = new User(1,"user1");
       User user1 = new User(2,"ser2");
        List<User> users = Arrays.asList(user, user1);
        ResultVo<List<User>> vo= new ResultVo<>();
        vo.setCode(HttpStatus.OK.value());
        vo.setData(users);

        //添加Hateoas連結
        vo.add(Link.of("http://localhost:8080/api/v1/users"));
        //根據id,擷取某個使用者資訊的連結
        vo.add(Link.of("http://localhost:8080/api/v1/users/uid","item"));
        //根據使用者名搜尋使用者資訊的連結
        vo.add(Link.of("http://localhost:8080/api/v1/users/name","search"));
        return vo;

    }


}       

結果:

這是第一個get中的連結的成功顯示,還有一個就不一一示範了

HATEOAS
HATEOAS

繼續閱讀