Java 使用SpEL原理的Spring

Java 使用SpEL原理的Spring,java,spring,hibernate,spring-mvc,Java,Spring,Hibernate,Spring Mvc,我试图在本文档中使用SpEL has 按{principal.id}执行查询筛选结果的步骤 问题是Spring返回一个异常 org.hibernate.QueryException:未设置所有命名参数: [1] [从产品p加入p商店s中选择p、p商店、p类别 加入p.category c,其中p.store.id=:id和p.keywords类似:keyword p.store.ownerId=?1];嵌套异常是 java.lang.IllegalArgumentException:org.hi

我试图在本文档中使用SpEL has 按{principal.id}执行查询筛选结果的步骤

问题是Spring返回一个异常

org.hibernate.QueryException:未设置所有命名参数: [1] [从产品p加入p商店s中选择p、p商店、p类别 加入p.category c,其中p.store.id=:id和p.keywords类似:keyword p.store.ownerId=?1];嵌套异常是 java.lang.IllegalArgumentException:org.hibernate.QueryException:Not 已设置所有命名参数:[1][选择p,p.store, p、 来自产品p的类别加入p.store s加入p.category c其中 p、 store.id=:id和p.keywords,如:keyword和p.store.ownerId=?1 ]

我已经设置了以下代码,并且正在执行

@Service
public class SecurityEvaluationContextExtension extends EvaluationContextExtensionSupport {

    @Override
    public String getExtensionId() {
        return "security";
    }

    @Override
    public SecurityExpressionRoot getRootObject() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("SER >>>>> " + authentication.getPrincipal().toString() + " -- " );
        return new SecurityExpressionRoot(authentication) {};
    }
}

@Configuration
@EnableJpaRepositories
public class SecurityConfiguration {

    @Bean
    EvaluationContextExtension securityExtension() {
        return new SecurityEvaluationContextExtension();
    }

}
我使用的这个服务器有一个Spring资源服务器,因此使用下面的翻译来从授权服务器获取Id。我确认代码执行和翻译都很好,但是我得到了上面的异常

@Service
public class myPrincipalExtractor implements PrincipalExtractor {

    @Override
    public UserInfo extractPrincipal(Map<String, Object> map) {

        Map<String,Object> principal = null;

        if (map.containsKey("principal")) {
            principal = (Map<String, Object>) map.get("principal");
        }

        UserInfo user = new UserInfo();

        if (principal != null ) {
            if (principal.containsKey("id")) {
                user.setId(Long.parseLong(principal.get("id").toString()));
            }

            if (principal.containsKey("username")) {
                user.setUsername(principal.get("username").toString());
            }

            if (principal.containsKey("email")) {
                user.setEmail(principal.get("email").toString());
            }
        }

        System.out.println("----> " + user.getUsername() + " -> " + user.getId());

        return user;
    }
}
在网站示例中,它们指定您可以使用?{principal.id},并且在执行上述代码时确实会调用它,但由于某种原因,@Query绑定失败。 但是我试着用另一个例子来运行它

@Query("select p , p.store, p.category from Product p JOIN p.store s " +
            " JOIN p.category c " +
            " WHERE p.store.id = :id AND p.keywords LIKE %:keyword% AND p.store.ownerId = ?#{#security.principal.id} ")
这起作用了。 我在这里发现了另一个例子:

我在一个示例项目中使用了一个类似的spel,您可以在github上看到它,但在我的例子中,我没有使用PincipalExtractor,在这个示例中,我使用UserDetailService来检索具有自定义id字段的主体:我使用的是OAuth2 ResourceServer,它从授权服务器获取信息。根据您的解决方案,我需要构建一个restTemplate客户端?您好,Fernando,我认为这个示例结合了oauth2和UserDetailService这两种方法,以便使用需要注入@Query注释的值填充principal objects字段,请参阅AuthorizationServerConfigurerAdapter和WebSecurityConfiguration部分。可能与此错误有关,但我能够将SpEL与securiy.principal一起使用,而不仅仅是principal
return new SecurityExpressionRoot(authentication) {
            @Override
            public UserInfo getPrincipal() {
                System.out.println("Fetching the principal has user " + authentication.getPrincipal().toString());
                return (UserInfo) authentication.getPrincipal();
            }
        };
@Query("select p , p.store, p.category from Product p JOIN p.store s " +
            " JOIN p.category c " +
            " WHERE p.store.id = :id AND p.keywords LIKE %:keyword% AND p.store.ownerId = ?#{#security.principal.id} ")