Java 使用SpEL原理的Spring
我试图在本文档中使用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 ] 我已经设置了以下代码,并且正在执行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
@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} ")