如何使用自定义Spring Data Rest Controller将现有链接扩展到资源

时间:2018-02-19 18:29:22

标签: spring-data-rest spring-hateoas

我在 spring-boot-starter-data-rest 中使用 Spring boot 1.5.10

我创建了域实体:

@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"
    }
  }
}

但我想在&#34; http://localhost:8080/api/v1/users/search&#34;添加新的端点。使用自定义控制器,使用 @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 端点添加到用户/搜索,最终获得以下内容:< / p>

{
  "_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"
    }
  }
}

是否可以这样做?

1 个答案:

答案 0 :(得分:2)

您需要实施ResourceProcessor<RepositorySearchesResource>并手动添加链接。

// 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,以便稍后在必要时提供关于添加其他休息参数(分页,排序......)的提示。