当前位置: 首页 > 知识库问答 >
问题:

如何用自定义Spring数据Rest控制器扩展到资源的现有链接

宗政和韵
2023-03-14

我正在使用Spring-boot-starter-data-rest的Spring Boot1.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);

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

但我想使用自定义控制器,使用@RepositoryRestController向“http://localhost:8080/api/v1/users/search”添加一个新的endpoint,例如:

@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);
    }

}

但我的控制器没有向现有endpoint添加任何内容。我已经读过如何在Spring Data REST中添加到根资源的链接?这个决定对根endpoint很有效,但我想将getUserByStreetAddressendpoint添加到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"
    }
  }
}

共有1个答案

白宏义
2023-03-14

您需要实现ResourceProcessor 并手动添加链接。

// 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,以便给出关于添加其他rest参数(分页、排序……)的提示如有必要,稍后再谈。

 类似资料:
  • 我正在通过数据库开发一组rest资源,并使用Spring Data Rest公开核心CRUD功能,以直接与存储库交互。 在我的简化示例中,我有以下用户: 和用户自己的项目: 直接与存储库交互是可以的,所以对于创建用户(其他简单实体),问题来自于创建项目。项目有大量基于用户表单输入的服务器派生字段,所以我编写了一个自定义控制器来生成它们并保存结果。为了持久化结果,我需要将项目与其拥有的用户相关联。我

  • 以前,在自定义控制器中可以通过注入并使用方法来实现这一点,但最近的Spring Data Rest更新打破了这一点。 我希望在实体上强制执行一个特定的视图,而SDR预测似乎是这样做的理想方法,特别是在HAL API的上下文中,而不是为自定义控制器编写硬DTO类并在它们之间进行映射等。节选预测不是我想要的,因为这些仅适用于查看相关资源时。

  • 注意:TPR已经停止维护,kubernetes 1.7及以上版本请使用CRD。 自定义资源是对Kubernetes API的扩展,kubernetes中的每个资源都是一个API对象的集合,例如我们在YAML文件里定义的那些spec都是对kubernetes中的资源对象的定义,所有的自定义资源可以跟kubernetes中内建的资源一样使用kubectl操作。 自定义资源 Kubernetes1.6版

  • 我有一个POJO类患者,具有以下特征: 现在从我的Rest控制器中,我只需要在json中发送患者的姓名、电话号码、电子邮件和地址。我希望json输出为 此处仅将检查成功/失败添加为标志。

  • 我试图向RepositoryRestResource中自动生成的endpoint添加一些额外的业务逻辑。请参见下面的代码: 资源: 控制器: 我看过下面两篇stackoverflow的文章: 我可以让自定义控制器镜像Spring-Data-Rest / Spring-Hateoas生成的类的格式吗? 在自定义控制器方法的 Spring Boot 中启用 HAL 序列化 我觉得我很接近了,但我面临的

  • 一、环境 1、hadoop 0.20.2 2、操作系统Linux 二、背景 1、最近写MR的代码,总在想统计一些错误的数据出现的次数,发现如果都写在reduce的输出里太难看了,所以想找办法专门输出一些统计数字。 2、翻看《hadoop权威指南》第8章第1节的时候发现能够自定义计数器,但都是基于0.19版本写的,好多函数都不对,改动相对较大。 3、基于上面2个理由,写个文档,记录一下。 三、实现