zoukankan      html  css  js  c++  java
  • Spring Security和Swagger2集成报错

      出现问题的项目算是一个新项目,但基本的脚手架代码是从另一个项目里迁过来的,原项目并没有报错,只有新项目才报异常。看报错内容,判断发生冲突的主要是spring-boot-starter-security和springfox-swagger2这两个jar包的文件。

      新项目错误如下:

    Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    15:22:32.350 spotcheck-system [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter - 
    
    ***************************
    APPLICATION FAILED TO START
    ***************************
    
    Description:
    
    Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
        - requestMappingHandlerMapping: defined by method 'requestMappingHandlerMapping' in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]
        - swagger2ControllerMapping: defined by method 'swagger2ControllerMapping' in class path resource [springfox/documentation/swagger2/configuration/Swagger2DocumentationConfiguration.class]
    
    Action:
    
    Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
    
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping' available: expected single matching bean but found 2: requestMappingHandlerMapping,swagger2ControllerMapping

      我的项目中出错代码是这一行,在原项目并没有报错。

    Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();

      getBean方法默认是byType来加载bean对象的,如果取到相同类型的2个就会报错。我分别查看了错误中提示的DelegatingWebMvcConfiguration.class和Swagger2DocumentationConfiguration.class。

      1. DelegatingWebMvcConfiguration.class里并没有requestMappingHandlerMapping方法,DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport.class类,在WebMvcConfigurationSupport.class类中有requestMappingHandlerMapping方法,返回值是RequestMappingHandlerMapping.class。代码如下:

        /**
         * Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping
         * requests to annotated controllers.
         */
        @Bean
        public RequestMappingHandlerMapping requestMappingHandlerMapping() {
            RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
                    ......
            }

      2. Swagger2DocumentationConfiguration.class里有swagger2ControllerMapping方法如下:

      @Bean
      public HandlerMapping swagger2ControllerMapping(
          Environment environment,
          DocumentationCache documentationCache,
          ServiceModelToSwagger2Mapper mapper,
          JsonSerializer jsonSerializer) {
          return new PropertySourcedRequestMappingHandlerMapping(environment, new Swagger2Controller(environment, documentationCache, mapper, jsonSerializer));
      }

      这个方法里的返回值类型PropertySourcedRequestMappingHandlerMapping继承了RequestMappingHandlerMapping类,

    public class PropertySourcedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
        ......
    }

      所以可能Spring加载时,根据byType形式会认错了吧。

      解决办法:既然Spring加载时使用byType形式会报错,那我们就用byName形式加载。Spring中使用@Bean声明的方法,如果没有指定名称,默认的name就是方法名。所以我们把出错代码改成:

            RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
            Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();

      到此问题解决。

    补充一下:

      假设自己项目中有一个接口,同时有两个实现类,并且实现类都使用了@Service注解,你在使用过程中使用了@Autowired注解进行引用。这时Spring初始化时就会报错:expected single matching bean but found 2 ,因为@Autowired默认是byType形式加载的。

      解决办法就是用@Primary、@Qualifier这两个注解来解决问题

      @Primary注解是用来声明2个实现类那个是主要的。与@Component、@Service等注解放到一起使用。这时Spring通过@Autowired加载时,就会判断一下, 优先使用@Primary注解的类。

      @Qualifier显示声明加载类的名称,与@Autowired放到一起使用,这样Spring加载时判断类型相同,会在通过名称筛选出需要的类,就不会报错了。其实@Autowired + @Qualifier = @Resource,如果真需要byName形式加载,直接使用@Resource就可以了。

  • 相关阅读:
    win8.1下安装双系统ubuntu14.04.3
    如何使用cmd
    My Test about Mat
    访问Mat矩阵中的元素并为其赋值
    Mat代码操作
    waitKey()
    ASCII码对照表
    vector 中的clear()
    vector 介绍
    Mat的详解
  • 原文地址:https://www.cnblogs.com/huanshilang/p/13093712.html
Copyright © 2011-2022 走看看