域/存储库弹簧数据休息覆盖库(控制器VS AOP)
Project {
User owner;
}
//Querydsl repositories
@RepositoryRestResource
public interface ProjectRepository extends PagingAndSortingRepository<Project, Long>, QueryDslPredicateExecutor<Project>, QuerydslBinderCustomizer<QProject> {
default void customize(QuerydslBindings bindings, QProject project) {
(...)
}
}
Requeriment:根据经认证的用户上下文 滤波数据:
- 如果用户是
ROLE_PUBLIC
显示项目根据predicate
和用户是owner
。 - 如果用户是
ROLE_ADMIN
根据predicate
过滤显示项目。
我试图解决throught几种选择:
选项1:覆盖@RepositoryRestController
为Spring DATA REST医生说:
@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名单上( DATAREST-838):
Failed to instantiate [com.querydsl.core.types.Predicate]: Specified class is an interface
列表中最类似的argumentResolver是QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver
,但我不知道它是否对这个问题有用。
选项2:这个问题是一个典型的交叉问题,所以我尝试应用AOP。定义建议和更新ARGS(谓语):
@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,页面,_links)的反应是:
{
"_links" : {
"profile" : {
"href" : "http://localhost:8087/api/profile/projects"
}
}
}
选项3 使用@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存在更好的选择。
问题:
- 有关如何解决这个requeriment任何建议吗?
- 如何将AOP应用于Spring Data REST以解决横切需求?
- 为什么@QuerydslPredicate在参数解析器?
Spring Data REST version 2.5。6
虽然已经解决,但我想获得反馈和建议。我希望QueryDSLPredicate注解将被修复,文档将会被更多关于这个问题的示例所改进。