読者です 読者をやめる 読者になる 読者になる

Spring BootでSpring Data RESTを試す

Spring Data RESTを試してみたメモです。

JSUGでSpring Data RESTというものを知ったので少し触ってみました。
https://www.slideshare.net/makingx/spring-boot-tips

Spring Data REST

Spring Data RESTはSpring Data projectの一部で、
Spring Data RepositoryをRESTのリソースとしてアクセス出来るようにします。
Spring Data RESTはSpring MVC上に構築されます。
Spring Data REST

Maven dependency

Spring Dataのライブラリの互換性を確保するために、releasetrainを指定します。
現時点で最新のIngalls-RELEASEを指定しました。

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-releasetrain</artifactId>
        <version>Ingalls-RELEASE</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
    </dependencies>
  </dependencyManagement>

dependencyには、
・spring-boot-starter-web
・spring-boot-starter-data-rest
・spring-boot-starter-data-jpa
・h2
を追加しました。

DBはh2でインメモリで動かしてみます。

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
  </dependencies>

テスト用クラス

テスト用のドメインとして、下記のUserクラスを作成しました。
@Entityでエンティティを定義し、@Idで主キーを指定し、@GeneratedValueで主キーの生成方法を指定します。

User.java

@Setter
@Getter
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
    private int age;
    private String country;
}

Userのリポジトリを作成します。
PagingAndSortingRepositoryを継承したUserRepositoryインターフェースを作成します。
PagingAndSortingRepositoryはCrudRepositoryにページングとソートを拡張したインターフェースです。

UserRepository.java

public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}

これで、Spring Bootアプリケーションを起動すると、
Userリポジトリに対するCRUDのREST URIのエンドポイントが作成されます。
(Controllerを作成せずにエンドポイントが作成されます)

CRUD

各エンドポイントが追加されているか確認してみます。

トップレベ

トップレベルのエンドポイントを確認してみます。
http://localhost:8080/ にGETでアクセスしてみると、
usersというドメインの複数形の名前のエンドポイントが追加されていることが分かります。

$ curl http://localhost:8080/
{
  "_links" : {
    "users" : {
      "href" : "http://localhost:8080/users"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
POST

usersにデータを登録してみます。
POSTでjsonデータを送信します。

レスポンスで/users/1で登録されたことが分かります。

$ curl -X POST http://localhost:8080/users -H "Content-Type:application/json" -d "{\"name\" : \"Alice\", \"age\" : \"18\", \"country\" : \"America\"}"
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}
GET

GETで先程作成したデータを取得してみます。
GETで/users/1にアクセスします。

先程登録した内容が返ってきています。

$ curl -X GET http://localhost:8080/users/1
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

idを指定せずに/users にアクセスするとデータをリストで取得します。
12件ほどデータを追加して、/users にアクセスしてみます。

下記のように12件取得されます。

curl -X GET http://localhost:8080/users
{
  "_embedded" : {
    "users" : [ {
      "name" : "Alice",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "user" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    }, {
      "name" : "Bobby",
      "age" : 20,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/2"
        },
        "user" : {
          "href" : "http://localhost:8080/users/2"
        }
      }
    }, {
      "name" : "Cindy",
      "age" : 33,
      "country" : "Japan",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/3"
        },
        "user" : {
          "href" : "http://localhost:8080/users/3"
        }
      }
    },
        :
        :
        :
        :

     ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 12,
    "totalPages" : 1,
    "number" : 0
  }
}

・size
デフォルトでsize,page,sortのパラメータが用意されています。
sizeで取得するデータ数を指定できます。

curl -X GET http://localhost:8080/users?size=5
{
  "_embedded" : {
    "users" : [ {
      "name" : "Alice",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "user" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    }, {
      "name" : "Bobby",
      "age" : 20,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/2"
        },
        "user" : {
          "href" : "http://localhost:8080/users/2"
        }
      }
    }, {
      "name" : "Cindy",
      "age" : 33,
      "country" : "Japan",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/3"
        },
        "user" : {
          "href" : "http://localhost:8080/users/3"
        }
      }
    }, {
      "name" : "Danniel",
      "age" : 29,
      "country" : "Chaina",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/4"
        },
        "user" : {
          "href" : "http://localhost:8080/users/4"
        }
      }
    }, {
      "name" : "Elly",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/5"
        },
        "user" : {
          "href" : "http://localhost:8080/users/5"
        }
      }
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/users?page=0&size=5"
    },
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "next" : {
      "href" : "http://localhost:8080/users?page=1&size=5"
    },
    "last" : {
      "href" : "http://localhost:8080/users?page=2&size=5"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    }
  },
  "page" : {
    "size" : 5,
    "totalElements" : 12,
    "totalPages" : 3,
    "number" : 0
  }
}

・page
pageで次のsize件を指定できます。

$ curl -X GET "http://localhost:8080/users?size=5&page=1"
{
  "_embedded" : {
    "users" : [ {
      "name" : "Forrest",
      "age" : 21,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/6"
        },
        "user" : {
          "href" : "http://localhost:8080/users/6"
        }
      }
    }, {
      "name" : "Giants",
      "age" : 20,
      "country" : "Japan",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/7"
        },
        "user" : {
          "href" : "http://localhost:8080/users/7"
        }
      }
    }, {
      "name" : "Hellen",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/8"
        },
        "user" : {
          "href" : "http://localhost:8080/users/8"
        }
      }
    }, {
      "name" : "Ian",
      "age" : 20,
      "country" : "Japan",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/9"
        },
        "user" : {
          "href" : "http://localhost:8080/users/9"
        }
      }
    }, {
      "name" : "Jimmy",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/10"
        },
        "user" : {
          "href" : "http://localhost:8080/users/10"
        }
      }
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/users?page=0&size=5"
    },
    "prev" : {
      "href" : "http://localhost:8080/users?page=0&size=5"
    },
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "next" : {
      "href" : "http://localhost:8080/users?page=2&size=5"
    },
    "last" : {
      "href" : "http://localhost:8080/users?page=2&size=5"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    }
  },
  "page" : {
    "size" : 5,
    "totalElements" : 12,
    "totalPages" : 3,
    "number" : 1
  }
}

・sort
sortでソートするキーを指定できます。
asc,descを指定すると降順、昇順も指定できます。

$ curl -X GET "http://localhost:8080/users?sort=age,desc"
{
  "_embedded" : {
    "users" : [ {
      "name" : "Kris",
      "age" : 41,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/11"
        },
        "user" : {
          "href" : "http://localhost:8080/users/11"
        }
      }
    }, {
      "name" : "Lennon",
      "age" : 33,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/12"
        },
        "user" : {
          "href" : "http://localhost:8080/users/12"
        }
      }
    }, {
      "name" : "Cindy",
      "age" : 33,
      "country" : "Japan",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/3"
        },
        "user" : {
          "href" : "http://localhost:8080/users/3"
        }
      }
    },
        :
        :
        :
        :
     ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    },
    "search" : {
      "href" : "http://localhost:8080/users/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 12,
    "totalPages" : 1,
    "number" : 0
  }
}
PUT

PUTでレコード全体を置換します。
すべてのフィールドを指定する必要があります。
指定されていないフィールドはnullで更新されます。

curl -X PUT http://localhost:8080/users/1 -H "Content-Type:application/json" -d "{\"name\" : \"Bob\", \"age\" : \"22\", \"country\" : \"Canada\"}"
{
  "name" : "Bob",
  "age" : 22,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

更新されていることが分かります。

$ curl -X GET http://localhost:8080/users/1
{
  "name" : "Bob",
  "age" : 22,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}
PATCH

PATCHで指定したフィールドだけ更新できます。
PUTではすべてのフィールドを指定する必要がありましたが、PATCHは更新したいフィールドだけ指定すればよいです。

curl -X PATCH http://localhost:8080/users/1 -H "Content-Type:application/json" -d "{ \"age\" : \"89\"}"
{
  "name" : "Bob",
  "age" : 89,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

更新されていることが分かります。

$ curl -X GET http://localhost:8080/users/1
{
  "name" : "Bob",
  "age" : 89,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}
DELETE

DELETEで対象のリソースを削除します。

curl -X DELETE http://localhost:8080/users/1

リソースが取得出来ないことが分かります。

$ curl -X GET http://localhost:8080/users/1
カスタムクエリ

カスタムクエリを定義できます。

下記のように
nameを元にUserを返すfindByNameメソッドと
countryを元にUserのリストを返すfindByCountryメソッドを定義。

public interface UserRepository extends PagingAndSortingRepository<User, Long> {
    User findByName(@Param("name") String name);

    List<User> findByCountry(@Param("country") String country);
}

カスタムクエリのエンドポイントは下記のように/users/searchで取得出来ます。
/users/search/findByCountryはcountryをパラメータに取り、
/users/search/findByNameはnameをパラメータに取ることが分かります。

$ curl -X GET http://localhost:8080/users/search
{
  "_links" : {
    "findByCountry" : {
      "href" : "http://localhost:8080/users/search/findByCountry{?country}",
      "templated" : true
    },
    "findByName" : {
      "href" : "http://localhost:8080/users/search/findByName{?name}",
      "templated" : true
    },
    "self" : {
      "href" : "http://localhost:8080/users/search"
    }
  }
}

・findByName
name=Bobbyのパラメータを付けて、findByNameにアクセスすると、
対象のUserが取得出来ているのが分かります。

$ curl -X GET "http://localhost:8080/users/search/findByName?name=Bobby"
{
  "name" : "Bobby",
  "age" : 20,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/2"
    },
    "user" : {
      "href" : "http://localhost:8080/users/2"
    }
  }
}

・findByCountry
country=Canadaのパラメータを付けて、findByCountryにアクセスすると、
対象のUserがリストで取得できているのが分かります。

$ curl -X GET "http://localhost:8080/users/search/findByCountry?country=Canada"
{
  "_embedded" : {
    "users" : [ {
      "name" : "Bobby",
      "age" : 20,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/2"
        },
        "user" : {
          "href" : "http://localhost:8080/users/2"
        }
      }
    }, {
      "name" : "Forrest",
      "age" : 21,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/6"
        },
        "user" : {
          "href" : "http://localhost:8080/users/6"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/search/findByCountry?country=Canada"
    }
  }
}

Configration

色々な設定をapplication.propertiesで設定出来ます。

application.properties

spring.data.rest.xxxxx=zzzzz
basePath

basePathでRESTのroot URIを変更できます。
spring.data.rest.basePath=/api とした場合、RESTのエンドポイントは下記のようになります。

・POST

$ curl -X POST http://localhost:8080/api/users -H "Content-Type:application/json" -d "{\"name\" : \"Alice\", \"age\" : \"18\", \"country\" : \"America\"}"
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/api/users/1"
    }
  }
}

・GET

$ curl -X GET http://localhost:8080/api/users/1
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/api/users/1"
    }
  }
}
defaultPageSize

defaultPageSizeで1ページで取得するデータのデフォルト数を変更します。
spring.data.rest.defaultPageSize=3とすると、下記の通りデフォルトで3件取得します。

$ curl -X GET http://localhost:8080/users
{
  "_embedded" : {
    "users" : [ {
      "name" : "Alice",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "user" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    }, {
      "name" : "Bobby",
      "age" : 20,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/2"
        },
        "user" : {
          "href" : "http://localhost:8080/users/2"
        }
      }
    }, {
      "name" : "Cindy",
      "age" : 33,
      "country" : "Japan",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/3"
        },
        "user" : {
          "href" : "http://localhost:8080/users/3"
        }
      }
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/users?page=0&size=3"
    },
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "next" : {
      "href" : "http://localhost:8080/users?page=1&size=3"
    },
    "last" : {
      "href" : "http://localhost:8080/users?page=3&size=3"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    },
    "search" : {
      "href" : "http://localhost:8080/users/search"
    }
  },
  "page" : {
    "size" : 3,
    "totalElements" : 12,
    "totalPages" : 4,
    "number" : 0
  }
}
maxPageSize

maxPageSizeを指定すると、1ページでのデータの最大数を指定できます。
spring.data.rest.maxPageSize=2とすると、下記のようにsize=5のパラメータを指定しても
2件だけ取得されます。

$ curl -X GET "http://localhost:8080/users?size=5"
{
  "_embedded" : {
    "users" : [ {
      "name" : "Alice",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "user" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    }, {
      "name" : "Bobby",
      "age" : 20,
      "country" : "Canada",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/2"
        },
        "user" : {
          "href" : "http://localhost:8080/users/2"
        }
      }
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/users?page=0&size=2"
    },
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "next" : {
      "href" : "http://localhost:8080/users?page=1&size=2"
    },
    "last" : {
      "href" : "http://localhost:8080/users?page=5&size=2"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    },
    "search" : {
      "href" : "http://localhost:8080/users/search"
    }
  },
  "page" : {
    "size" : 2,
    "totalElements" : 12,
    "totalPages" : 6,
    "number" : 0
  }
}
pageParamName/limitParamName/sortParamName

pageParamName,limitParamName,sortParamNameでそれぞれ
page,size,sortのデフォルトのクエリパラメータ名を変更できます。

spring.data.rest.pageParamName=p
spring.data.rest.limitParamName=l
spring.data.rest.sortParamName=s
を設定した場合、下記のようにp,l,sのパラメータでデータを取得できます。

$ curl -X GET "http://localhost:8080/users?p=0&l=4&s=age"
{
  "_embedded" : {
    "users" : [ {
      "name" : "Jimmy",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/10"
        },
        "user" : {
          "href" : "http://localhost:8080/users/10"
        }
      }
    }, {
      "name" : "Elly",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/5"
        },
        "user" : {
          "href" : "http://localhost:8080/users/5"
        }
      }
    }, {
      "name" : "Alice",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "user" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    }, {
      "name" : "Hellen",
      "age" : 18,
      "country" : "America",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/8"
        },
        "user" : {
          "href" : "http://localhost:8080/users/8"
        }
      }
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/users?p=0&l=4&s=age,asc"
    },
    "self" : {
      "href" : "http://localhost:8080/users"
    },
    "next" : {
      "href" : "http://localhost:8080/users?p=1&l=4&s=age,asc"
    },
    "last" : {
      "href" : "http://localhost:8080/users?p=2&l=4&s=age,asc"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/users"
    },
    "search" : {
      "href" : "http://localhost:8080/users/search"
    }
  },
  "page" : {
    "size" : 4,
    "totalElements" : 12,
    "totalPages" : 3,
    "number" : 0
  }
}
returnBodyOnCreate

returnBodyOnCreateでデータ作成時のレスポンスボディでデータを返すか設定できます。
デフォルトはtrueでレスポンスボディに作成したデータが返ってきます。
falseに設定するとデータを返さないように設定できます。

・spring.data.rest.returnBodyOnCreate=true

$ curl -X POST http://localhost:8080/users -H "Content-Type:application/json" -d "{\"name\" : \"Alice\", \"age\" : \"18\", \"country\" : \"America\"}"
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

・spring.data.rest.returnBodyOnCreate=false

$ curl -X POST http://localhost:8080/users -H "Content-Type:application/json" -d "{\"name\" : \"Alice\", \"age\" : \"18\", \"country\" : \"America\"}"
returnBodyOnUpdate

同様にreturnBodyOnUpdateでデータ更新時のレスポンスボディでデータを返すか設定できます。
この設定はPUTとPATCHの両方に適用されるようです。
デフォルトはtrueでレスポンスボディに更新したデータが返ってきます。
falseに設定するとデータを返さないように設定できます。

・spring.data.rest.returnBodyOnUpdate=true
PUT

$ curl -X PUT http://localhost:8080/users/1 -H "Content-Type:application/json" -d "{\"name\" : \"Bob\", \"age\" : \"22\", \"country\" : \"Canada\"}"
{
  "name" : "Bob",
  "age" : 22,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

PATCH

$ curl -X PATCH http://localhost:8080/users/1 -H "Content-Type:application/json" -d "{ \"age\" : \"89\"}"
{
  "name" : "Bob",
  "age" : 89,
  "country" : "Canada",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

・spring.data.rest.returnBodyOnUpdate=false
PUT

$ curl -X PUT http://localhost:8080/users/1 -H "Content-Type:application/json" -d "{\"name\" : \"Bob\", \"age\" : \"22\", \"country\" : \"Canada\"}"

PATCH

$ curl -X PATCH http://localhost:8080/users/1 -H "Content-Type:application/json" -d "{ \"age\" : \"89\"}"

その他の設定

@JsonIgnore

jacksonの@JsonIgnoreで対象のフィールドを無視させることが出来ます。
下記のようなpasswordフィールドに@JsonIgnoreを付与すると、
RESTのフィールドに含まれなくなります。

User.java

@Setter
@Getter
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
    private int age;
    private String country;

    @JsonIgnore
    private String password;
}

POST

$ curl -X POST http://localhost:8080/users -H "Content-Type:application/json" -d "{\"name\" : \"Alice\", \"age\" : \"18\", \"country\" : \"America\"}"
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

GET

$ curl -X GET http://localhost:8080/users/1
{
  "name" : "Alice",
  "age" : 18,
  "country" : "America",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "user" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}
REST URLの変更

REST URLはデフォルトだとドメインの複数形のURIで公開されますが、
@RepositoryRestResource(path = "xxxx")を指定することで、URIを変更できます。

下記のようなChildクラスがあった場合、デフォルトだとURIは/childsで公開されます。

Child.java

@Setter
@Getter
@Entity
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
    private int age;
}

下記のように@RepositoryRestResource(path = "children")を指定することで、
/children のURIで公開されます。

ChildRepository.java

@RepositoryRestResource(path = "children")
public interface ChildRepository extends PagingAndSortingRepository<Child, Long> {
}

下記のように/children でアクセス出来ます。
・POST

$ curl -X POST http://localhost:8080/children -H "Content-Type:application/json" -d "{\"name\" : \"Alice\", \"age\" : \"18\"}"
{
  "name" : "Alice",
  "age" : 18,
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/children/1"
    },
    "child" : {
      "href" : "http://localhost:8080/children/1"
    }
  }
}

・GET

$ curl -X GET http://localhost:8080/children/1
{
  "name" : "Alice",
  "age" : 18,
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/children/1"
    },
    "child" : {
      "href" : "http://localhost:8080/children/1"
    }
  }
}
Hiding methods

特定のメソッドを公開しないようにすることが出来ます。

CRUDを非公開
特定のCRUDメソッドを非公開にする場合、レポジトリで非公開にするメソッドをオーバーライドし、
@RestResource(exported = false)を付与します。

DELETEメソッドを非公開にする場合、下記の様に記述します。

AnimalRepository.java

public interface AnimalRepository extends PagingAndSortingRepository<Animal, Long> {
    List<Animal> findByName(@Param("name") String name);

    @Override
    @RestResource(exported = false)
    void delete(Long id);
}

データを登録します。

$ curl -X POST http://localhost:8080/animals -H "Content-Type:application/json" -d "{\"name\" : \"Fox\"}"
{
  "name" : "Fox",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/animals/1"
    },
    "animal" : {
      "href" : "http://localhost:8080/animals/1"
    }
  }
}

DELETEで削除してみると、405が返ってきます。

$ curl -i -X DELETE http://localhost:8080/animals/1
HTTP/1.1 405
Allow: GET,HEAD,PUT,PATCH,OPTIONS
Content-Length: 0
Date: Fri, 03 Mar 2017 12:04:41 GMT

GETしてみると削除できていないことが分かります。

$ curl -X GET http://localhost:8080/animals/1
{
  "name" : "Fox",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/animals/1"
    },
    "animal" : {
      "href" : "http://localhost:8080/animals/1"
    }
  }
}

・カスタムクエリを非公開
カスタムクエリを非公開にする場合、リポジトリで非公開にするメソッドに
@RestResource(exported = false)を付与します。

AnimalRepository.java

public interface AnimalRepository extends PagingAndSortingRepository<Animal, Long> {
    @RestResource(exported = false)
    List<Animal> findByName(@Param("name") String name);
}

@RestResource(exported = false)付与前は、
/searchでエンドポイントを検索してみると、findByNameのエンドポイントが表示されますが、

$ curl -X GET http://localhost:8080/animals/search
{
  "_links" : {
    "findByName" : {
      "href" : "http://localhost:8080/animals/search/findByName{?name}",
      "templated" : true
    },
    "self" : {
      "href" : "http://localhost:8080/animals/search"
    }
  }
}

@RestResource(exported = false)を付与すると、下記のように表示されません。

$ curl -X GET http://localhost:8080/animals/search

リポジトリを非公開
リポジトリを非公開にする場合、レポジトリに
@RepositoryRestResource(exported = false)を付与します。

AnimalRepository.java

@RepositoryRestResource(exported = false)
public interface AnimalRepository extends PagingAndSortingRepository<Animal, Long> {
    List<Animal> findByName(@Param("name") String name);
}

@RepositoryRestResource(exported = false)付与前は
エンドポイントを検索してみると、/animalsのエンドポイントが表示されますが、

$ curl -X GET http://localhost:8080/
{
  "_links" : {
    "children" : {
      "href" : "http://localhost:8080/children{?page,size,sort}",
      "templated" : true
    },
    "animals" : {
      "href" : "http://localhost:8080/animals{?page,size,sort}",
      "templated" : true
    },
    "users" : {
      "href" : "http://localhost:8080/users{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}

@RepositoryRestResource(exported = false)を付与すると、下記のように表示されません。

$ curl -X GET http://localhost:8080/
{
  "_links" : {
    "children" : {
      "href" : "http://localhost:8080/children{?page,size,sort}",
      "templated" : true
    },
    "users" : {
      "href" : "http://localhost:8080/users{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}

終わり。

ソースは下記にあげました。
github.com