我想实现一些功能来获取当前登录的用户(代表当前登录人员的JPA实体)。但不是以经典的方式做到这一点
CurrentUserService.getCurrentUser(){load the user from db by login})
我想以更多的CDI方式进行。
我希望有一个CurrentUserFactory
,它将当前用户作为请求范围bean提供,并提供自定义限定符(当前bean)。
限定符:
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface CurrentUser {
}
厂:
@Component
public class CurrentUserFactory {
@CurrentUser
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public User currentUser() throws IllegalStateException {
return
<DoWhatIMean>
User load form DB by:
SecurityContextHolder.getContext().getAuthentication().getName()
</dwim>
}
用法:
@Controller
@RequestMapping(…)
public AccountController() {
@Resource
@CurrentUser
private User currentUser;
@RequestMapping(params=”my”)
public String myAccount () {
return “redirect:/account/”+currentUser.id;
}
}
工作正常。
但如果我使用当前用户进行直接JPA(Hibernate)之类的操作,例如通过引用currentUser来搜索实体或者存储一个引用currentUser的实体,它就失败了(并没有真正有用的例外)。 - (这个失败很明显。)
原因是spring在currentUser中注入一个CGI代理。只要只使用此代理的属性,这样就可以正常工作,但如果开始使用引用本身就会失败。
我知道我正在规范的边缘工作,如果我的想法不起作用,我会接受。但是我想问你我有一个想法让它运作起来。这样开发人员就可以像普通的JPA加载实体一样使用这个currentUser对象。
至少我想要的只是当前用户非常容易使用:
@Resouce
@CurrenctUser
User currentUser;
就是这样。
可能有人有想法让它工作,例如AspectJ技巧(我使用编译时AspectJ)?
无论如何:正如我之前所说,例外不是我的问题,我理解它们,因为它们只是所描述问题的指标。
当我尝试按currentUser(Select b From Bookmark b Where user=?
)
java.lang.IllegalStateException
:org.hibernate.TransientObjectException
:对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:domain.User
我尝试保存书签时出现例外情况(书签有字段用户)
无法插入:[
domain.Bookmark
]; SQL [insert into bookmark (businessId, reference_Folder_fk, title, user_fk) values (?, ?, ?, ?)
];约束[null
];嵌套异常为org.hibernate.exception.ConstraintViolationException
:无法插入:[domain.Bookmark
]
答案 0 :(得分:1)
Spring代理由ScopedProxyFactoryBean创建。它的文档说代理实现了'ScopedObject',它允许你访问原始的bean。
@Resource
@CurrentUser
private User currentUser;
public static <T> T unwrapScopedProxy(T maybeProxy) {
if (maybeProxy instanceof ScopedObject) {
return (T) ((ScopedObject) maybeProxy).getTargetObject();
} else {
return maybeProxy;
}
}
...
query.setParameter("user", unwrapScopedProxy(currentUser));