SpringBoot整合shiro-spring-boot-starter

2023-10-29

1、项目启动时报错如下:

Description:
The bean 'securityManager', defined in class path resource [org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/ncwu/common/infrastructure/config/ShiroConfig.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

 2、原因分析

      我的自定义ShiroConfig配置类中添加的安全管理器,代码如下:

@Bean
public SecurityManager securityManager(JwtRealm jwtRealm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //配置realm
    securityManager.setRealm(jwtRealm);
    return securityManager;
}

      根据异常信息查看ShiroWebAutoConfiguration源码时发现其中已经定义了securityManager方法,我们在ShiroConfig配置类中再次定义securityManager方法,因返回的类与其不一样导致出错,ShiroWebAutoConfiguration类中定义的securityManager方法代码如下:

@Bean
@ConditionalOnMissingBean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
    return super.securityManager(realms);
}

      下面这些为补充知识:我们都知道@ConditionalOnBean作用是根据value属性按bean的类型或则bean的名称判断它的实例对象是否在IOC容器中,如果存在返回true,否则返回false。而@ConditionalOnMissingBean的作用与@ConditionalOnBean相反。如果@ConditionalOnBean和@ConditionalOnMissingBean这两个注解没有参数,那这两个注解以何种方式来判断呢?在Spring Boot官方文档中找出了答案。

      意思是:在@ConditionalOnMissingBean没有参数的情况下,目标类型默认为方法的返回类型,如果IOC容器中没有类型为SomeService及其子类的实例对象,则将创建 someService bean。

      从源代码中可以看出@ConditionalOnMissingBean没有参数,那么如果IOC容器中没有类型为SessionsSecurityManager及其子类的实例对象,那么该方法则会执行,并且源码securityManager方法返回的是SessionsSecurityManager,而自己定义的ShiroConfig中返回的是SecurityManager(因为@Bean注解会指定改bean的类型为该方法的返回类型),所以它会判断出IOC容器中没有类型为SessionsSecurityManager及其子类的实例对象,源码中的方法执行,故IOC容器中有两个名为securityManager的Bean,因而报错。所以如果要自定义securityManager方法,返回类型只能是SessionsSecurityManager及其子类,而SessionsSecurityManager的子类是DefaultSecurityManager,DefaultWebSecurityManager又继承DefaultSecurityManager,相关类图如下:

      故而正确的代码应该是:

@Bean
public SessionsSecurityManager securityManager(JwtRealm jwtRealm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //配置realm
    securityManager.setRealm(jwtRealm);
    return securityManager;
}

//或者如下,将方法返回类型改为DefaultWebSecurityManager 
/*@Bean
public DefaultWebSecurityManager securityManager(JwtRealm jwtRealm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //配置realm
    securityManager.setRealm(jwtRealm);
    return securityManager;
}*/

3、测试@ConditionalOnMissingBean注解

新建下面3个类:

//动物
@Data
public class Animal {
    private String name;
    private Integer age;
}

//狗
@EqualsAndHashCode(callSuper = true)
@Data
public class Dog extends Animal {
    private String type;
}

//二哈
@EqualsAndHashCode(callSuper = true)
@Data
public class TwoHa extends Dog {
    private String a;
}

启动类:

@SpringBootApplication
//扫描下面的接口生成代理实现类
@MapperScan("com.ncwu.**.domain.mapper")
public class ShiroApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class, args);
    }
    
    //若IOC容器中没有Animal类型及其子类Dog类型的实例对象时,该方法才会执行
    @Bean
    @ConditionalOnMissingBean
    public Animal twoHa(JwtRealm realm) {
        TwoHa twoHa = new TwoHa();
        twoHa.setType("twoHa1");
        twoHa.setAge(10);
        twoHa.setName("twoHa1");
        return twoHa;
    }

    @Bean
    public Dog twoHa() {
        TwoHa twoHa = new TwoHa();
        twoHa.setType("twoHa2");
        twoHa.setAge(20);
        twoHa.setName("twoHa2");
        return twoHa;
    }
}

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShiroApplication.class)
public class TestDao {
    @Autowired
    private ApplicationContext appContext;


    @Test
    public void test() throws Exception{
        /*String[] beanNamesForType = appContext.getBeanNamesForType(Animal.class);
        for (String s : beanNamesForType) {
            System.out.println(s);
        }*/
        appContext.getBean(Animal.class);
        //appContext.getBean("dog");
    }
}

测试结果:


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot整合shiro-spring-boot-starter 的相关文章

随机推荐

  • vue动态组件component详解

    附上代码
  • 演唱会门票抢不到?不要慌,教你用python实现自动化抢票

    前言 之前有小伙伴留言说女朋友快生日了 喜欢某某某但是手动买票根本就是买不到 又不想当大冤种从黄牛手里加钱 于是乎在疯狂星期四的晚上遭到 贿赂 的我连夜搞定了 一丶安装环境和配置文件 要用python实现 下载和安装python自然是不用说
  • P1016 旅行家的预算【模拟+贪心】【详解】

    题目链接 思路 这道题是一道很明显的模拟题 但这道题也需要自己的理解 我自己写了些样例 然后找到了其中的模拟 我们假设从一个点出发 对于它的下一个点我们有很多选择 期间定义一个len用以记录满油 单次最远 到达距离 我们造访这条路上的所有点
  • MYSQL数据库(六)用户、权限管理和DCL语句

    成功不易 加倍努力 1 MySQL用户管理 2 权限管理和DCL语句 3 MySQL的图形化的远程管理工具 1 MySQL用户管理 元数据数据库 mysql 系统授权表 USERNAME HOST HOST 主机名 user1 web1 m
  • 区块链到底是怎么运行的

    为了方便你理解 这一篇文章我将以比特币为例来进行讲解 因为比特币算是区块链应用中最简单 最容易理解的一个案例了 中心化记账的问题 首先 举一个关于中心化记账的经典例子 银行转账 假设小明给小红转200块 银行收到了转账请求 将小明银行账户里
  • 区块链hyperledger fabric架构详解

    hyperledger fabric是区块链中联盟链的优秀实现 主要代码由IBM Intel 各大银行等贡献 目前v1 1版的kafka共识方式可达到1000 s次的吞吐量 本文中我们依次讨论 区块链的共通特性 fabric核心概念 fab
  • vue全局一个格式化时间-format

    vue圈定定义一个format 用来格式化时间 Date prototype format function fmt const o M this getMonth 1 月份 d this getDate 日 h this getHours
  • Sudo: unable to initialize policy plugin 解决方法

    在centos7下 使用sudo 命令对www用户生成ssh秘钥 结果报错如下 Sudo parse error in etc sudoers near line 125 Sudo no valid sudoers sources foun
  • OS - 操作系统实战 - 学习/实践

    1 应用场景 主要用于学习 设计和编写操作系统 同时帮助更加好低理解操作系统 研究Linux系统 提供编程能力 2 学习 操作 1 文档阅读 操作系统实战45讲 操作系统 Linux 计算机基础 底层 内核 后端开发 iOS 彭东 C语言
  • c++中string的substr函数

    在 C 中 substr 函数用于提取字符串的子串 它有两种常用的用法 1 substr pos len 提取从位置 pos 开始的长度为 len 的子串 pos 指定提取子串的起始位置 位置从 0 开始 len 指定提取子串的长度 如果不
  • 2019年3月web前端最新面试题

    最近在找工作 面试了好多家公司 结果都不怎么理想 要么公司环境氛围不行 要么工资达不到理想的薪资 大部分公司对程序员的面试流程几乎都一样 来了先填一份登记表 写一套面试题 然后技术面 人事面 至于有的大牛说 四面web前端 拿到10K 的工
  • js 搜索关键字高亮

    主要是通过replace方法实现的 实现代码
  • SSTI 学习笔记

    PHP SSTI Twig 学习文章 进入环境 左上角有flag hint 都检查看看 flag页面显示ip hint页面源代码有提示 考虑XFF头或者referer头 测试一下 注 这里不用加上 出来了 python flask ssti
  • 30岁之后想转行,可行吗?这20条建议让你少走弯路!

    都说三十而立 可眼看着到了意气风发的年龄 却突然意识到自己仍一事无成 甚至连养活自己都是问题 30多岁 大多数人还要开始买房 买车 结婚生子 养家糊口 于是各种压力逼迫之下 就想到了转行 期望可以通过转行实现 财务自由 不过 俗话说 隔行如
  • 函数strlen的使用

    函数strlen是C语言的提供的函数 它包含在 include
  • Linux命令_printf & 格式化输出信息

    目录 1 语法 1 1 格式化参数 1 2 转义符参数 2 常见用法 2 1 输出字符串 2 2 格式化输出 2 3 设置格式对齐 2 4 控制输出宽度 2 5 替换补全字符 3 设置颜色 3 1 参数选项 3 2 基本用法 3 3 设置文
  • java选择排序(Selection Sort)——详解讲解+案例+时间复杂度

    文章目录 需求 排序原理 案例 选择排序的时间复杂度分析 需求 排序前 4 6 8 7 9 2 10 1 排序后 1 2 4 5 7 8 9 10 排序原理 1 每一次遍历的过程中 都假定第一个索引处的元素是最小值 和其他索引处的值依次进行
  • 剑指 Offer 16. 数值的整数次方 -- 快速幂

    0 题目描述 leetcode原题 剑指 Offer 16 数值的整数次方 1 快速幂解法 快速幂实际上是二分思想的一种应用 二分推导 x n x n
  • Windows下安装DVWA靶场

    Windows下利用phpstudy安装DVWA靶场 1 下载安装phpstudy以及DVWA Master php study下载官网https www xp cn DVWA资源已上传 在这里插入图片描述 https img blog c
  • SpringBoot整合shiro-spring-boot-starter

    1 项目启动时报错如下 Description The bean securityManager defined in class path resource org apache shiro spring config web autoc