如何使用自定义 Spring Data Rest Controller 扩展现有资源链接
How to extend existing links to resources with custom Spring Data Rest Controller
我正在使用 Spring boot 1.5.10 和 spring-boot-starter-data-rest.
我创建了域实体:
@Entity
public class User {
@Column
private long id;
@Column
private String firstName;
@Column
private String secondName;
@Column
private int age;
@Fetch(FetchMode.SELECT)
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private Address address;
...
}
@Entity
public class Address {
@Column
private long id;
@Column
private String city;
@Column
private String street;
@Column
private String build;
...
}
并且我已经为这个域实体创建了存储库:
interface UserRepository extends JpaRepository<User, String> {
User getUserByFirstNameAndSecondName(String firstName, String secondName);
@RestResource(exported = false)
User getUserByAddress(Address address);
}
interface AddressRepository extends JpaRepository<Address, String> {
Address getAddressByStreet(String street);
}
之后我给出下一个 HATEOAS 根端点:
{
"_links" : {
"users" : {
"href" : "http://localhost:8080/api/v1/users{?page,size,sort}",
"templated" : true
},
"address" : {
"href" : "http://localhost:8080/api/v1/address{?page,size,sort}",
"templated" : true
}
}
如果我导航到 http://localhost:8080/api/v1/users,我会得到类似的东西:
{
"_links" : {
"getUserByFirstNameAndSecondName" : {
"href" : "http://localhost:8080/api/v1/users/search/getUserByFirstNameAndSecondName{?firstName, secondName ,projection}",
"templated" : true
},
"self" : {
"href" : "http://localhost:8081/api/v1/users/search"
}
}
}
但我想向“http://localhost:8080/api/v1/users/search”添加一个新端点,使用自定义控制器,使用 @RepositoryRestController,例如:
@RepositoryRestController
public class UserRestController {
private UserRepository userRepository;
@Autowired
public UserRestController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@RequestMapping("/users/search/getUserByStreetAddress")
public User getUserByStreetAddress(String street) {
Address address = new Address();
address.setStreet(street);
return userRepository.getUserByAddress(address);
}
}
但是我的控制器没有向现有端点添加任何内容。
我已阅读 How to add links to root resource in Spring Data REST? 并且此决定适用于根端点但我想将 getUserByStreetAddress 端点添加到 users/search 和最终得到以下内容:
{
"_links" : {
"getUserByFirstNameAndSecondName" : {
"href" : "http://localhost:8080/api/v1/users/search/getUserByFirstNameAndSecondName{?firstName, secondName ,projection}",
"templated" : true
},
//Method from my custom controller added to http://localhost:8080/api/v1/users/search" endpoint
"getUserByStreetAddress" : {
"href" : "http://localhost:8080/api/v1/users/search/getUserByStreetAddress{?street ,projection}",
"templated" : true
},
"self" : {
"href" : "http://localhost:8080/api/v1/users/search"
}
}
}
可以这样做吗?
您需要实施 ResourceProcessor<RepositorySearchesResource>
并手动添加 link。
// other imports here
import static org.springframework.hateoas.TemplateVariable.VariableType.REQUEST_PARAM;
@Component
public class RepositorySearchesResourceProcessor implements ResourceProcessor<RepositorySearchesResource> {
@Autowired
private RepositoryRestConfiguration restConfiguration;
@Override
public RepositorySearchesResource process(RepositorySearchesResource resource) {
// early exit if we're not dealing with a User resource
if (!User.class.equals(resource.getDomainType())) {
return resource;
}
// add a custom link to /users/search
String search = resource.getId().getHref();
List<TemplateVariable> list = new ArrayList<>;
list.add(new TemplateVariable("street", REQUEST_PARAM);
boolean addProjection = restConfiguration.getProjectionConfiguration().hasProjectionFor(Parameter.class);
if (addProjection) {
// should be "projection" unless you configured it differently
list.add(restConfiguration.getProjectionConfiguration().getParameterName());
}
TemplateVariables tvs = new TemplateVariables(list);
Link link = new Link(new UriTemplate(search + "/getUserByStreetAddress", tvs"), "getUserByStreetAddress");
resource.add(link);
return resource;
}
我放入了 RepositoryRestConfiguration 和 UriTemplate,以便在以后需要时提供有关添加其他剩余参数(分页、排序...)的提示。
我正在使用 Spring boot 1.5.10 和 spring-boot-starter-data-rest.
我创建了域实体:
@Entity
public class User {
@Column
private long id;
@Column
private String firstName;
@Column
private String secondName;
@Column
private int age;
@Fetch(FetchMode.SELECT)
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private Address address;
...
}
@Entity
public class Address {
@Column
private long id;
@Column
private String city;
@Column
private String street;
@Column
private String build;
...
}
并且我已经为这个域实体创建了存储库:
interface UserRepository extends JpaRepository<User, String> {
User getUserByFirstNameAndSecondName(String firstName, String secondName);
@RestResource(exported = false)
User getUserByAddress(Address address);
}
interface AddressRepository extends JpaRepository<Address, String> {
Address getAddressByStreet(String street);
}
之后我给出下一个 HATEOAS 根端点:
{
"_links" : {
"users" : {
"href" : "http://localhost:8080/api/v1/users{?page,size,sort}",
"templated" : true
},
"address" : {
"href" : "http://localhost:8080/api/v1/address{?page,size,sort}",
"templated" : true
}
}
如果我导航到 http://localhost:8080/api/v1/users,我会得到类似的东西:
{
"_links" : {
"getUserByFirstNameAndSecondName" : {
"href" : "http://localhost:8080/api/v1/users/search/getUserByFirstNameAndSecondName{?firstName, secondName ,projection}",
"templated" : true
},
"self" : {
"href" : "http://localhost:8081/api/v1/users/search"
}
}
}
但我想向“http://localhost:8080/api/v1/users/search”添加一个新端点,使用自定义控制器,使用 @RepositoryRestController,例如:
@RepositoryRestController
public class UserRestController {
private UserRepository userRepository;
@Autowired
public UserRestController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@RequestMapping("/users/search/getUserByStreetAddress")
public User getUserByStreetAddress(String street) {
Address address = new Address();
address.setStreet(street);
return userRepository.getUserByAddress(address);
}
}
但是我的控制器没有向现有端点添加任何内容。 我已阅读 How to add links to root resource in Spring Data REST? 并且此决定适用于根端点但我想将 getUserByStreetAddress 端点添加到 users/search 和最终得到以下内容:
{
"_links" : {
"getUserByFirstNameAndSecondName" : {
"href" : "http://localhost:8080/api/v1/users/search/getUserByFirstNameAndSecondName{?firstName, secondName ,projection}",
"templated" : true
},
//Method from my custom controller added to http://localhost:8080/api/v1/users/search" endpoint
"getUserByStreetAddress" : {
"href" : "http://localhost:8080/api/v1/users/search/getUserByStreetAddress{?street ,projection}",
"templated" : true
},
"self" : {
"href" : "http://localhost:8080/api/v1/users/search"
}
}
}
可以这样做吗?
您需要实施 ResourceProcessor<RepositorySearchesResource>
并手动添加 link。
// other imports here
import static org.springframework.hateoas.TemplateVariable.VariableType.REQUEST_PARAM;
@Component
public class RepositorySearchesResourceProcessor implements ResourceProcessor<RepositorySearchesResource> {
@Autowired
private RepositoryRestConfiguration restConfiguration;
@Override
public RepositorySearchesResource process(RepositorySearchesResource resource) {
// early exit if we're not dealing with a User resource
if (!User.class.equals(resource.getDomainType())) {
return resource;
}
// add a custom link to /users/search
String search = resource.getId().getHref();
List<TemplateVariable> list = new ArrayList<>;
list.add(new TemplateVariable("street", REQUEST_PARAM);
boolean addProjection = restConfiguration.getProjectionConfiguration().hasProjectionFor(Parameter.class);
if (addProjection) {
// should be "projection" unless you configured it differently
list.add(restConfiguration.getProjectionConfiguration().getParameterName());
}
TemplateVariables tvs = new TemplateVariables(list);
Link link = new Link(new UriTemplate(search + "/getUserByStreetAddress", tvs"), "getUserByStreetAddress");
resource.add(link);
return resource;
}
我放入了 RepositoryRestConfiguration 和 UriTemplate,以便在以后需要时提供有关添加其他剩余参数(分页、排序...)的提示。