Spring Data Rest 覆盖存储库(控制器与 AOP)

2024-04-15

域/存储库

Project {
   User owner;
}

//Querydsl repositories
@RepositoryRestResource
public interface ProjectRepository extends PagingAndSortingRepository<Project, Long>, QueryDslPredicateExecutor<Project>, QuerydslBinderCustomizer<QProject> {  
   default void customize(QuerydslBindings bindings, QProject project) {
      (...)
   }
}

要求:根据经过身份验证的用户上下文过滤数据:

  • 如果用户是ROLE_PUBLIC显示项目根据predicate其中 user 是owner.
  • 如果用户是ROLE_ADMIN显示项目根据predicate filter.

我尝试通过几种替代方案解决:

Option 1:覆盖@RepositoryRestController正如所说弹簧数据休息 https://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.overriding-sdr-response-handlers doc:

@RepositoryRestController
public class ProjectController {

@RequestMapping(value = "/projects", method = RequestMethod.GET)
@ResponseBody
public PagedResources<?> search(
        @QuerydslPredicate(root=Project.class ,bindings =ProjectRepository.class) Predicate predicate,
        @PageableDefault Pageable pageable, //
        @AuthenticationPrincipal Principal principal) {

        (...) // Update predicate wit user context

        projectRepository.findAll(predicate,pageagle);
        (...)
    }

}

由于 @QueryDslPredicat 不在 RepositoryRestHandlerAdapter 列表中(数据休息-838 https://jira.spring.io/browse/DATAREST-838):

Failed to instantiate [com.querydsl.core.types.Predicate]: Specified class is an interface

列表中最相似的 argumentResolver 是QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver但我不知道它是否对这个问题有用。

Option 2:这个问题是一个典型的横切问题,所以我尝试应用AOP。定义建议并更新参数(谓词):

@Around("this(com.xxx.yyy.repository.ProjectRepository)")
public void filterProjectsByUser(final ProceedingJoinPoint pjp) throws Throwable {
   Object[] args = pjp.getArgs();
   // .. Find args Predicate, update it adding user profile expression and procceed.
  pjp.proceed(args);
}

结果与默认存储库方法不同,而不是原始 JSON 对象(带有 _embedded、page、_links),响应是:

{
  "_links" : {
    "profile" : {
      "href" : "http://localhost:8087/api/profile/projects"
    }
  }
}

Option 3 Using @RestController:

@RestController
public class ProjectController {

@RequestMapping(value = "/projects/search", method = RequestMethod.GET)
@ResponseBody
public PagedResources<?> search(
        @QuerydslPredicate(root=Project.class ,bindings =ProjectRepository.class) Predicate predicate,
        @PageableDefault Pageable pageable, //
        @AuthenticationPrincipal Principal principal) {

        (...) // Update predicate wit user context

        projectRepository.findAll(predicate,pageagle);
        (...)
    }

}

使用相同的路径@RequestMapping("/projects",...)还覆盖其他端点(PUT,POST,...),这是不希望的。这迫使定义另一个端点("projects/search")。 我认为这种解决方法并不优雅,并且需要新闻端点。我确信 Spring Data REST 存在更好的替代方案。

问题:

  • 关于如何解决这个需求有什么建议吗?
  • 如何将AOP应用于Spring Data REST来解决横切需求?
  • 为什么在参数解析器中使用@QuerydslPredicate?

Spring Data REST 版本 2.5.6

虽然已经解决了,但我希望收到反馈和建议。我希望 QueryDSLPredicate 注释能够得到修复,并且文档能够通过更多关于此问题的示例得到改进。


最后我运行了Option 2我的错误没有返回proceed调用结果:

@Aspect
@Transactional
@Component
public class FilterProjectsAspect {

@Pointcut("execution(*  com.xxx.ProjectRepository.findAll(..))")
    public void projectFindAll() {
    }

    @Around("projectFindAll()")
    public Object  filterProjectsByUser(final ProceedingJoinPoint pjp) throws Throwable {

        Object[] args = pjp.getArgs();
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof Predicate) {
                Predicate predicate=(Predicate) args[i];
                BooleanExpression isProjectOwner =buildExpressionForUser()
                predicate = ExpressionUtils.allOf(isProjectOwner, predicate);
                args[i]=predicate;  //Update args
            }
        return pjp.proceed(args);
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Data Rest 覆盖存储库(控制器与 AOP) 的相关文章

  • Spring @Validated 在服务层

    Hej 我想使用 Validated group Foo class 在执行方法之前验证参数的注释 如下所示 public void doFoo Foo Validated groups Foo class foo 当我将此方法放入 Spr
  • Java:无安全管理器:RMI 类加载器已禁用

    您好 我有 RMI 应用程序 现在我尝试从客户端调用服务器上的一些方法 我有以下代码 public static void main final String args try Setting the security manager Sy
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • Ant 中回显目标描述

  • AWS SDK 2 承担角色

    Bean public DynamoDbClient amazonDynamoDB final AssumeRoleRequest assumeRoleRequest AssumeRoleRequest builder roleSessio
  • 为本地@ExceptionHandler编写JUnit测试

    我有以下控制器 class Controller ResponseStatus HttpStatus OK RequestMapping value verifyCert method RequestMethod GET public vo
  • 使用java在网页中进行字符编码

    如何使用java找出网页中的字符编码类型 打开与 URL 的连接 使用URL openConnection http download oracle com javase 6 docs api java net URL html openC
  • 开发人员实际上是否使用 vim 在 Windows 操作系统上编写代码(Java)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何构建和使用 TimeSeriesCollections

    我想在图表的 X 轴上显示一些日期 并且here https stackoverflow com questions 5118684 jfreechart histogram with dates据说我必须使用 TimeSeriesColl
  • 如何将测试类打包到jar中而不运行它们?

    我正在努力将我的测试类包含到 jar 包中 但不运行它们 经过一番谷歌搜索后 我尝试过mvn package DskipTests 但我的测试类根本没有添加到 jar 中 有任何想法吗 如果您遵循 Maven 约定 那么您的测试类位于src
  • Java 常量枚举[重复]

    这个问题在这里已经有答案了 可能的重复 理解 Java 中的枚举 https stackoverflow com questions 1419835 understanding enums in java 为什么我们应该使用枚举而不是 Ja
  • java中的第三个布尔状态是什么?

    虽然我知道根据定义 布尔值仅包含两种状态 真或假 我想知道布尔值在用这些状态之一初始化之前有什么值 它默认为 false http java sun com docs books tutorial java nutsandbolts dat
  • 动态创建 JSON 对象

    我正在尝试使用以下格式创建 JSON 对象 tableID 1 price 53 payment cash quantity 3 products ID 1 quantity 1 ID 3 quantity 2 我知道如何使用 JSONOb
  • 测量 tomcat 的排队请求数

    因此 使用tomcat 您可以设置acceptCount值 默认为100 这意味着当所有工作线程都忙时 新连接被放置在队列中 直到队列满 之后它们被拒绝 我想要的是监视此队列中项目的大小 但无法确定是否有办法通过 JMX 获取此值 即不是队
  • Spring Redis删除不删除key

    我正在尝试删除一个 Redis 键 但由于某种原因它没有删除 但也没有抛出异常 这是我要删除的代码 import com example service CustomerService import com example model Cu
  • 在java中创建一个XML树并将其转换为json对象

    我尝试创建也能够转换为 json 的树 但对于只有一个xpath 当我尝试实现多个 xpath 时 我无法获得所需的输出 这里我分享一下我的实现 private static Document addElemtbypath List
  • 设置 Firefox 配置文件以使用 Selenium 和 Java 自动下载文件

    我想使用 Selenium WebDriver 和 Java 验证文件下载 要下载的文件为 PDF 格式 当 WebDriver 单击 AUT 中的 下载 链接时 Firefox 将打开以下下载确认窗口 我希望 Firefox 自动下载文件
  • 如何让JComboBox中的内容居中显示?

    目前我有这个JComboBox 我怎样才能将其中的内容居中 String strs new String 15158133110 15158133124 15158133458 JComboBox com new JComboBox str
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即
  • 在 for 循环比较中使用集合大小

    Java 中 Collections 的 size 方法是否有编译器优化 考虑以下代码 for int i 0 i

随机推荐