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

通过SpringRESTJPA在自定义REST控制器中使用链接资源

乐华晖
2023-03-14

我正在通过数据库开发一组rest资源,并使用Spring Data Rest公开核心CRUD功能,以直接与存储库交互。

在我的简化示例中,我有以下用户:

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

    public String name;

    @OneToMany(mappedBy = "user")
    public Collection<Project> projects;
}

和用户自己的项目:

@Entity
public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long id;

    public String name;

    public String oneOfManyComplexDerivedProperties;

    @ManyToOne
    public User user;
}

直接与存储库交互是可以的,所以对于创建用户(其他简单实体),问题来自于创建项目。项目有大量基于用户表单输入的服务器派生字段,所以我编写了一个自定义控制器来生成它们并保存结果。为了持久化结果,我需要将项目与其拥有的用户相关联。我希望我的客户能够为此使用用户链接,就像通过直接访问存储库来创建新实体一样(直接访问存储库就可以了):

@RepositoryRestController
public class CustomProjectController {

    @Autowired
    ProjectRepo projectRepo;

    @RequestMapping(value = "/createProject", method = RequestMethod.POST)
    public HttpEntity<Project> createProject(@RequestParam User userResource,
                                         @RequestParam String formField1, // actually an uploaded file that gets processed, but i want simple for example purposes
                                         @RequestParam String formfield2)
{
    Project project = new Project();

    /*
    Actually a large amount of complex business logic to derive properties from users form fields, some of these results are binary.
     */
    String result = "result";
    project.oneOfManyComplexDerivedProperties = result;
    project.user = userResource;
    projectRepo.save(project);

    // aware that this is more complex than I've written.
    return ResponseEntity.ok(project);
}
}

当我呼叫时:
http://localhost:9999/api/createProject?userResource=http://localhost:9999/api/users/1

我得到:

{
    "timestamp": 1510588643801,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.web.method.annotation.MethodArgumentTypeMismatchException",
    "message": "Failed to convert value of type 'java.lang.String' to required type 'com.badger.User'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'http://localhost:9999/api/users/1'; nested exception is java.lang.NumberFormatException: For input string: \"http://localhost:9999/api/users/1\"",
    "path": "/api/createProject"
}

如果我将userResource更改为typeResource,则会出现另一个错误:
“未能将'java.lang.String'类型的值转换为所需类型'org.springframework.hateoas.Resource';嵌套异常为java.lang.IllegalStateException:无法将'java.lang.String'类型的值转换为所需类型'org.springframework.hateoas.Resource':未找到匹配的编辑器或转换策略”

我在文档中找不到任何关于在自定义控制器中使用存储库URI的引用,我找到的最接近的引用是在自定义控制器(Spring HATEOAS)中解析实体URI,但API自编写以来已经更改,我无法使其工作。


共有3个答案

丁钟展
2023-03-14

User userResources需要的是一个User对象你传入的是一个Stringhttp://localhost:9999/api/users/1

因此,我建议您将请求更改为POST请求,并将您的用户对象作为该请求的主体传递。

请求的正文将以JSON格式显示:

{
    id: 1,
    name: "myName",
    projects: []
}

因此,您可以删除userResource=http://localhost:9999/api/users/1从您的URL。最后将@RequestParam User userResource更改为@RequestBody User userResource

编辑因为您的请求中有用户Id,所以您可以在控制器中进行调用,以通过Id查找用户。因此,您可以将用户对象从@RequestParam user userResource更改为@RequestParam long userId,然后在方法中进行调用以查找类似于findUserById(userId)的用户

所以你的url看起来像http://localhost:9999/api/createProject?userId=1

漆雕和昶
2023-03-14

如果您想继续使用url参数,可以将@RequestParam User userResource更改为@RequestParam String userId

然后在你的createProject代码中有一些

User user = userRepo.findOne(userId);
project.user = user;
....
projectRepo.save(project);

如果是我,我会定义一个你传入的CreateProjectRequest对象,例如。

{
   "userId" : "1",
   "formField1" : "whatever",
   "formField2" : "whatever"
}

把你的创意改成

createProject(@RequestBody CreateProjectRequest createProjectRequest)
    ...
    project.setField1(createProjectRequest.getFormField1());
    ...

    User user = userRepo.findOne(createProjectRequest.getUserId());
    project.user = user;
    ....
    projectRepo.save(project);
汝宏伯
2023-03-14

我建议你真正应该做的是:

http://localhost:9999/api/users/1/projects?formField1=data1&formField2=Otherdata

通过启用Spring Data的Web支持,您可以将路径变量自动绑定到实体实例。

@RequestMapping(value = "users/{id}/projects", method = RequestMethod.POST)
        public HttpEntity<Project> createProject(
                            @PathVariable("id") User user,
                            @RequestParam String formField1,
                            @RequestParam String formfield2)
{

}

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#core.web

 类似资料:
  • 我正在使用Spring-boot-starter-data-rest的Spring Boot1.5.10。 如果导航到http://localhost:8080/api/v1/users,就会得到如下内容: 但我想使用自定义控制器,使用@RepositoryRestController向“http://localhost:8080/api/v1/users/search”添加一个新的endpoin

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

  • 我有一个Web应用程序,使用log4j。我在 /WEB-INF/classes/log4j.properties文件中配置了一个自定义记录器,如下所示: 日志消息按预期写入server.log,但我试图找到一种方法来控制自定义记录器日志级别通过glassfish服务器。 我尝试从命令中创建glassfish中的记录器: 但是,即使asadmin命令将记录器设置为警告,所有INFO消息仍然会被记录。

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

  • 问题内容: 我的过滤器很少 在我的项目中,要获得良好的结果,我必须在控制器中进行此过滤,而不是在视图中 我知道基本的语法,但我不知道如何在控制器中制作过滤器链,因此一切都将如模板中的示例一样工作。 我找到了一些解决方案,现在仅使用一个过滤器,但是应该可以用于许多;) 我在ng-repeat中使用此功能可以正常工作,但是我必须使用少量过滤器进行检查。 问题答案: 您只需重新过滤您从第一个过滤器返回的

  • 本文向大家介绍简述angular自定义过滤器在页面和控制器中的使用,包括了简述angular自定义过滤器在页面和控制器中的使用的使用技巧和注意事项,需要的朋友参考一下 AngularJS另一个特点就是提供了过滤器,可以通过操作UNIX下管道的方式,操作数据结果。   通过使用管道,可以便于双向的数据绑定中视图的展现。   过滤器在处理过程中,将数据变成新的格式,而且可以使用管道这种链式风格,还能接