记录:
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
Employee employee = employeeService.getEmployeeByLoginname(username);
if (employee == null) {
throw new UsernameNotFoundException("用户不存在,或密码错误!");
}
String password = employee.getLoginpassword();
boolean enabled = employee.isLoginAllow();
Set<Role> roles = employee.getRoleSet(); //②
List<GrantedAuthority> anthoritieList = new ArrayList<GrantedAuthority>();
for (Role role : roles) {
Set<Authority> authorities = role.getAuthoritySet(); //①
for (Authority authority : authorities) {
anthoritieList.add(new GrantedAuthorityImpl(authority.getName()));
}
}
return new User(username, password, enabled, anthoritieList
.toArray(new GrantedAuthority[0]));
}
①部分很重要,执行到此的时候,我的程序报懒加载异常:说 session已经被关闭了。
我的session用的是OpenSessionView。
也就是说sesion是在请求到来时打开,页面加载完毕后关闭。
可是在执行到此的时候,居然告诉我 session已经被关闭了。
那么说明:OpenSessionView的session管理,到不了 spring-security中。
解释可能是:
spring-security跳过了spring管理。因为它的登陆过程,其实是个黑盒。
因此,要记得给role.getAuthoritySet()属性设置lazy="false" ,也就是Role的映射文件的<set>标签,设置lazy="false"。
另:
观察②处在映射文件的映射,是:
<set name="roleSet" lazy="false" table="EMS_EMPLOYEE_ROLE_TABLE" order-by="EMPLOYEE_ID" fetch="subselect">
<key column="EMPLOYEE_ID"/>
<many-to-many column="ROLE_ID" class="Role"/>
</set>
很明显的看到 它设置了 lazy="false"
如果拿掉这个属性 同样在②也会报错
结论:spring-security流程中不能出现懒加载对象。因为session已经关闭。因此,要为默认栏架载的对象设置lazy="false".
但这不是最佳解决方案。因为,这会影响其它地方的运行效率。最好,将这一过程,后置到Service或者DAO里面。或者将session注入到流程里。