@RepositoryRestResource


既然在〈簡介 Spring Data JDBC〉用上了 Spring Data,那就再來介紹個有趣的功能吧!想要建立基於 MessageDAO 來建立一個 RESTful 應用程式可以有多簡單呢?

你可以在 build.gradle 加上個:

implementation('org.springframework.boot:spring-boot-starter-data-rest')

也就是說,將要使用的其實是 Spring Data Rest 的功能,接著在 MessageDAO 加上個 @RepositoryRestResource

package cc.openhome;

...略
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource
public interface MessageDAO extends CrudRepository<Message, Integer> {
    ...略
}

然後,就有 REST 的控制器可以使用了:

POST /messages
PUT /messages/{id}
GET /messages/{id}
DELETE /messages/{id}

MessageDAO 新定義的方法,會被列在 /messages/search,例如請求 http://localhost:8080/messages/search 的話,會看到開放的 API:

{
  "_links" : {
    "newestMessages" : {
      "href" : "http://localhost:8080/messages/search/newestMessages{?n}",
      "templated" : true
    },
    "deleteMessageBy" : {
      "href" : "http://localhost:8080/messages/search/deleteMessageBy{?username,millis}",
      "templated" : true
    },
    "messagesBy" : {
      "href" : "http://localhost:8080/messages/search/messagesBy{?username}",
      "templated" : true
    },
    "self" : {
      "href" : "http://localhost:8080/messages/search"
    }
  }
}

例如,你可以請求 http://localhost:8080/messages/search/messagesBy?username=caterpillar 來呼叫 MessageDAOmessagesBy 方法,瀏覽器會收到:

{
  "_embedded" : {
    "messages" : [ {
      "username" : "caterpillar",
      "millis" : 1518666695521,
      "blabla" : "我是一隻弱小的毛毛蟲&#xff0c;想像有天可以成為強壯的挖土機&#xff0c;擁有挖掘夢想的神奇手套&#xff01;",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/messages/1"
        },
        "message" : {
          "href" : "http://localhost:8080/messages/1"
        }
      }
    }, {
      "username" : "caterpillar",
      "millis" : 1518666716781,
      "blabla" : "碁峰把《Java SE 9 技術手冊》電子書放上去囉&#xff01;",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/messages/2"
        },
        "message" : {
          "href" : "http://localhost:8080/messages/2"
        }
      }
    }, 
    ...略
}

如果想進一步控制每個方法,可以標註 @RestResource,例如,不開放 delete

package cc.openhome;

...略

import org.springframework.data.rest.core.annotation.RestResource;

@RepositoryRestResource
public interface MessageDAO extends CrudRepository<Message, Integer> {
    @RestResource(exported = true)
    @Query("SELECT * FROM message m WHERE m.username = :username")
    List<Message> messagesBy(@Param("username") String username);

    @RestResource(exported = true)
    @Modifying
    @Query("DELETE FROM message WHERE username = :username AND millis = :millis")   
    void deleteMessageBy(@Param("username") String username, @Param("millis") String millis);

    @RestResource(exported = true)
    @Query("SELECT * FROM message ORDER BY millis DESC LIMIT :n")
    List<Message> newestMessages(@Param("n") int n);

    @Override
    @RestResource(exported = false)
    void delete(Message message);
}

你可以在 DataREST 找到以上的範例專案。