java - 覆盖 Spring Data Rest POST 方法

标签 java spring-data spring-data-jpa spring-data-rest

我需要为 POST 方法添加额外的业务逻辑。现在,我将重用 RepositoryEntityController 中的逻辑来获取和保存所需的对象。

@RepositoryRestController
@RequestMapping("/customPost")
public class UserController implements ApplicationEventPublisherAware {

private final UserRepository userRepository;
private final RepositoryRestConfiguration config;
private final HttpHeadersPreparer headersPreparer;
private ApplicationEventPublisher publisher;

@Autowired
public UserController(UserRepository userRepository, RepositoryRestConfiguration config, HttpHeadersPreparer headersPreparer) {
    this.userRepository = userRepository;
    this.config = config;
    this.headersPreparer = headersPreparer;
}

public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
    this.publisher = publisher;
}

@ResponseBody
@RequestMapping(
        value = {"/{repository}"},
        method = {RequestMethod.POST}
)
public ResponseEntity<ResourceSupport> postCollectionResource(PersistentEntityResource payload, PersistentEntityResourceAssembler assembler, @RequestHeader(value = "Accept", required = false) String acceptHeader) throws HttpRequestMethodNotSupportedException {
    return this.createAndReturn(payload.getContent(), assembler, this.config.returnBodyOnCreate(acceptHeader));
}

private ResponseEntity<ResourceSupport> createAndReturn(Object domainObject, PersistentEntityResourceAssembler assembler, boolean returnBody) {
    publisher.publishEvent(new BeforeCreateEvent(domainObject));
    Object savedObject = userRepository.save((User) domainObject);
    publisher.publishEvent(new AfterCreateEvent(savedObject));
    PersistentEntityResource resource = returnBody ? assembler.toFullResource(savedObject) : null;
    HttpHeaders headers = headersPreparer.prepareHeaders(resource);
    addLocationHeader(headers, assembler, savedObject);
    return ControllerUtils.toResponseEntity(HttpStatus.CREATED, headers, resource);
}

private void addLocationHeader(HttpHeaders headers, PersistentEntityResourceAssembler assembler, Object source) {
    String selfLink = assembler.getSelfLinkFor(source).getHref();
    headers.setLocation((new UriTemplate(selfLink)).expand(new Object[0]));
}

}

我发送的代码 - 工作正常。但问题是我需要添加一些请求映射 @RequestMapping("/customPost") 到 Controller 。

没有这个映射 - 方法将不起作用。我尝试使用相同的 Controller 但没有“/customPost”映射。我在应用程序开始时遇到了这个异常:

caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'repositoryEntityController' method 
public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException
to {[/{repository}],methods=[POST],produces=[application/hal+json || application/json]}: There is already 'userController' bean method
public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> com.project.controller.UserController.postCollectionResource(org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.assertUniqueMethodMapping(AbstractHandlerMethodMapping.java:576) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:540) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:264) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]

我还尝试从 Controller 中删除“/customPost”映射并将方法中的映射更改为“/users”。但是对于这种情况,我有这个异常(exception):

java.lang.NullPointerException: null
at org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver.resolveArgument(RootResourceInformationHandlerMethodArgumentResolver.java:86) ~[spring-data-rest-webmvc-2.6.10.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.resolveArgument(PersistentEntityResourceHandlerMethodArgumentResolver.java:113) ~[spring-data-rest-webmvc-2.6.10.RELEASE.jar:na]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.27.jar:8.5.27]

问题是:如何在不添加“/customPost”映射的情况下获得所需的逻辑?

最佳答案

Spring Data REST 发出自己的 events使用实体时:

  • 创建事件前
  • AfterCreateEvent
  • 保存事件前
  • AfterSaveEvent
  • BeforeLinkSaveEvent
  • AfterLinkSaveEvent
  • BeforeDeleteEvent
  • AfterDeleteEvent

您可以监听这些事件以添加额外的业务逻辑。例如,在 SDR 创建一个新的用户(使用 POST 方法)或保存(更新) 存在的 User (使用 PUT/PATCH 方法),你可以使用这样的处理程序:

@Component
@RepositoryEventHandler 
public class UserEventHandler {

  private final UserServie userServie;

  public UserEventHandler(UserServie userServie) {
      this.userServie = userServie;
  }

  @HandleAfterCreate
  public void handleAfterCreateUser(User user) {
      userService.afterCreate(user)  
  }

  @HandleAfterSave
  public void handleAfterSaveUser(User user) {
      userService.afterSave(user)  
  }
}

附言如果我没记错的话,SDR 会在当前事务之外发出这些事件,仅在它开始之前或提交之后。在实现业务逻辑时需要考虑到这一点...

关于java - 覆盖 Spring Data Rest POST 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49504103/

相关文章:

java - 我的选项卡式 Activity 未在选项卡上显示标题

java - 如何通过 Akka Streams for java 创建和使用 Pair 流?

java - 环境变量 CLASSPATH <> Clojure 的 CLASSPATH。为什么?

java - Log4j2 RollingFile Appender - 在每个日志文件的开头添加自定义信息

java - Spring Data JPA - 用于 json 序列化的 ZonedDateTime 格式

spring - 使用 Spring 检查实体/对象是否属于当前登录的用户

spring - 使用 Spring Data MongoDB 查询纯 BSON

java - NoClassDefFound错误: com/mysema/query/mongodb/MongodbQuery

java - spring-data-jpa 中的交叉连接

java - Spring-data-jpa - .save() 什么时候不返回相同的实体?