一、问题引入
今天我在实现三更博客项目的注册功能时,使用postman进行测试,一直报下图错误:
好久都不知道是啥原因,哎,还是我太菜了,其实bug说得很明白了ClassCastException类型转换异常,但是我当时一直摸不着头绪,因为我看见这个UserLogin就很疑惑,想着我在写注册的代码时,也没用到这个类呀,我反正只记得在权限那一块使用了这个类,为此我还傻不拉几的去看真的跑去权限那块的代码去看,实际上做了无用功,其实和权限根本就没关系 |
二、问题分析
但凡我在往下翻一点,都能马上找到错误,其实这就是惯性思维,总觉得报错信息就在最上面,这也是吃了教训了,这是下面的报错:
下面有inserFill,很明显就是这的问题,开始的疑惑到这里也想明白了,因为我为User类中的公共字段设置了自动填充:
其实开始三更的代码也是没用这个的,我是为了让注册用户时就有相应信息,才设置这个,设置了哪些字段应该在什么时候填充,下面就是设置填充的规则了,如下图所示:
添加填充配置器,就是实现MetaObjectHandler接口,~~啰嗦一句
关键就是这一句:
Long userId = securityUtils.getUserId();
而securityUtils内部实现是这样的:
@Component
public class SecurityUtils {
/**
* 获取Authentication
* @return
*/
public Authentication getAuthentication(){
return SecurityContextHolder.getContext().getAuthentication();
}
/**
* 获取UserLogin
* @return
*/
public UserLogin getUserLogin(){
return (UserLogin) getAuthentication().getPrincipal();
}
/**
* 获取用户Id
* @return
*/
public Long getUserId(){
return getUserLogin().getUser().getId();
}
/**
* 判断用户是否为管理员
*/
public boolean isAdmin(){
Long id = getUserId();
return id!=null && id == 1L;
}
}
具体原因是这一句:
public UserLogin getUserLogin(){
return (UserLogin) getAuthentication().getPrincipal();
}
因为这个注册接口是不需要认证的,所以自然也就没走认证过滤器,在认证过滤器中才setAuthentication,才设置了Principal,就是过滤器器中的下面这一句:
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,null);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
正是没有设置过,所以Principal默认是一段字符串,而在
public UserLogin getUserLogin(){
return (UserLogin) getAuthentication().getPrincipal();
}
这里进行了强转,从字符串转为UserLogin类型,自然就类型转换异常了
三、解决办法
这里不在工具类中添加逻辑代码,在字段填充配置器中,添加特判即可:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Autowired
private SecurityUtils securityUtils;
@Override
public void insertFill(MetaObject metaObject) {
Long userId ;
if(! (securityUtils.getAuthentication().getPrincipal() instanceof UserLogin)){
userId = -1L;
}else{
userId = securityUtils.getUserId();
}
setFieldValByName("createTime",new Date(),metaObject);
setFieldValByName("createBy",userId,metaObject);
setFieldValByName("updateTime",new Date(),metaObject);
setFieldValByName("updateBy",userId,metaObject);
setFieldValByName("delFlag",0,metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
Long userId ;
if(! (securityUtils.getAuthentication().getPrincipal() instanceof UserLogin)){
userId = -1L;
}else{
userId = securityUtils.getUserId();
}
setFieldValByName("updateTime",new Date(),metaObject);
setFieldValByName("updateBy",userId,metaObject);
setFieldValByName("delFlag",0,metaObject);
}
}
关键代码:
Long userId ;
if(! (securityUtils.getAuthentication().getPrincipal() instanceof UserLogin)){
userId = -1L;
}else{
userId = securityUtils.getUserId();
}
四、总结
1 . 看报错,不能只看前面,应该将报错信息看全
2. 刨根问底,思考报错原因