记录下今天摸鱼的一天
夜深终于把自己写的demo跑起来了,来总结下,事情是这样的,最近想学一下Spring Security,于是对着开源项目一顿Copy,在拖拖拉拉几天之后,一个登陆接口终于Cpoy完了,正当暗自高兴的时候,跑一下项目,得到如下
创建Bean失败,🥲是我太久没写Java了嘛,开始想着是不是因为我用的是SpringBoot3的版本,依赖注入有改动,经过一番折腾后,按照官网给的改成构造函数注入,无果…
想想就Controller、Service、Mapper这三层,对应的注解我都加了不应该啊,后面对着报错结果看到,有一个依赖我引用了但没有注入进来。
内容是这样的
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.crypto.password.PasswordEncoder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@jakarta.annotation.Resource(shareable=true, lookup="", name="", description="", authenticationType=CONTAINER, type=java.lang.Object.class, mappedName="")}
可以看到我引用了PasswordEncoder,但没有注入
因为是登陆,需要对密码进行encode跟数据库里做比对,这个是Spring Security自带的一个类,我们需要将其注入到bean中。
所以需要创建一个配置类
@Configuration
public class SecurityAutoConfiguration {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
如此以来,报错解决,项目可以正常跑起来,那么开测(预先在用户表里设置了一个账号密码)😏
直接401,没有接口访问权限
解决办法
在SecurityAutoConfiguration类加入配置,将接口设置成所有人都可以访问
、、、SecurityAutoConfiguration.class
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/system/auth/login").permitAll()
.anyRequest().authenticated()
)
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
如此一来,我的system/auth/login接口就有权限测试了😁
结果。。。
从报错结果可以看到create_time字段为空
我的函数是这样写的
咋的一看确实没有给create_time赋值,但我的代码是copy的,别人的开源项目也没有啊,首先找到这个字段
使用了@TableField(fill = FieldFill.INSERT)表示在插入数据的时候自动填充,怪我之前知识面太浅,以为只要加了这个注解就完事了,后面什么都不用管,可事实很残酷,并不是我想的那样,好在,现在有GPT,菜鸡的福音🥹
原来还需要配置,然后再翻一下源码,果然如此,首先添加配置类
public class DefaultDBFieldHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
LocalDateTime current = LocalDateTime.now();
// 创建时间为空,则以当前时间为插入时间
if (Objects.isNull(baseDO.getCreateTime())) {
baseDO.setCreateTime(current);
}
// 更新时间为空,则以当前时间为更新时间
if (Objects.isNull(baseDO.getUpdateTime())) {
baseDO.setUpdateTime(current);
}
Long userId = WebFrameworkUtils.getLoginUserId();
// 当前登录用户不为空,创建人为空,则当前登录用户为创建人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
baseDO.setCreator(userId.toString());
}
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
baseDO.setUpdater(userId.toString());
}
}
}
@Override
public void updateFill(MetaObject metaObject) {
// 更新时间为空,则以当前时间为更新时间
Object modifyTime = getFieldValByName("updateTime", metaObject);
if (Objects.isNull(modifyTime)) {
setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
}
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
Object modifier = getFieldValByName("updater", metaObject);
Long userId = WebFrameworkUtils.getLoginUserId();
if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
setFieldValByName("updater", userId.toString(), metaObject);
}
}
}
再创建一个config类,将上面的配置注入到spring容器中
@Configuration
public class MyBatisAutoConfig {
/**
* @Author luoguodong
* @Description //TODO
* @Date 23:44 2023/8/30 注入自动填充
* @return com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
**/
@Bean
public MetaObjectHandler defaultMetaObjectHandler(){
return new DefaultDBFieldHandler(); // 自动填充参数类
}
}
如此就完成了,BaseDO类里面带有@TableField注解的将会自动赋值。一个接口终于能正常跑了。😩
想想今天几乎所有的时间都在写自己的demo,公司的业务是几乎没动呀。
自己的:
公司的:
就加了这么点东西哈哈。
另外Copy的项目是ruoyi-vue-pro,太牛逼了。