将业务逻辑添加到 spring-data-rest 应用程序

Adding business logic to a spring-data-rest application

我一直在试验 spring-data-rest (SDR),我对建立休息的速度如此之快印象深刻 api。我的应用程序基于以下存储库,它为我提供了 GET /attachments 和 POST /attachements

package com.deepskyblue.attachment.repository;

import java.util.List;

import org.springframework.data.repository.Repository;

import com.deepskyblue.attachment.domain.Attachment;

public interface AttachmentRepository extends Repository<Attachment, Long> {

    List<Attachment> findAll();

    Attachment save(Attachment attachment);
}

但我感到困惑的一件事是如何添加自定义业务逻辑。如果我只想 API 处理我的数据,SDR 似乎很棒,但是传统的 Spring 应用程序通常会有一个服务层,我可以在其中拥有业务逻辑。有没有办法使用 SDR 添加此业务逻辑?

我猜你说的是 3 层架构业务层、表示层和持久层。

我通常按照这个将我的代码组合在一起表示层将是具有所有 类 [@RestController] 直接与 post 交互并获取的 Rest 注释和方法的层前端调用 .

这些 类 将依次自动装配业务层和服务层,以从数据库获取数据或在从数据库获取数据之前添加一些业务逻辑。

您甚至可以使用 RepositoryRestController。要利用 Spring Data REST 的设置、消息转换器、异常处理等,

希望这就是您所看到的。

有很多可能性。

  1. 验证器 (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#validation) 用于验证接收到的对象。

  2. 事件处理程序 http://docs.spring.io/spring-data/rest/docs/current/reference/html/#events) 将在验证正常时调用。

  3. 自定义控制器(http://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.overriding-sdr-response-handlers)当你想手动处理请求时。

我最终创建了一个围绕存储库方法的自定义方面。像这样 (groovy):

@Aspect
@Component
@Slf4j
class AccountServiceAspect {

@Around("execution(* com.test.accounts.account.repository.AccountRepository.save*(..))")
    Object saveAccount(ProceedingJoinPoint jp) throws Throwable {
        log.info("in aspect!")
        Object[] args = jp.getArgs()

        if (args.length <= 0 || !(args[0] instanceof Account))
            return jp.proceed()

        Account account = args[0] as Account

        account.active = true
        jp.proceed(account)
    }
}

不理想,但您可以在保存之前修改模型,而无需从头开始编写 spring 数据其余控制器。

要在 Spring-Data-Rest 中添加自定义逻辑,您必须注册您的拦截器以在请求进入存储库之前接收请求。这是您可以做到的方法

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

import static java.lang.String.format;

public class MyInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private MyRepository myRepository;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Simple check to see if database object exists for requesting urls otherwise 
        // throw runtime exception to be picked up by handler for error response

        Map pathVariables = getUrlPathVariables(request);
        String myId = (String) pathVariables.get("myId"); // e.g. /rest/path/${myParam}

        if (myId != null && myRepository.findById(myId) == null) {
            throw new RuntimeException("My Object not found");
        }

        return true;
    }

    private Map getUrlPathVariables(HttpServletRequest request) {
        return (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
    }

}

来源:https://gist.github.com/m-x-k/03a87252d2458010e1d69f37e35af6f1

更多详细信息:https://www.baeldung.com/spring-mvc-handlerinterceptor

一个很好的答案:https://www.reddit.com/r/java/comments/90wk5y/spring_rest_business_logic/

If your future service might have any of business logic, even simple, you should not use Spring Data Rest.

Spring Data Rest is perfectly suits case when you only need basic control of entities(think CRUD).

With the case one could start with spring web, rest controllers and use JSON representation as your views.

如果您的逻辑只处理一个实体,EventsValidator 会有所帮助。

不要误会我的意思,在一个普通的项目中你会发现很多地方没有繁重的逻辑,Spring Data Rest 适合退出并且可以节省很多时间。