好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

在zuulFilter中注入bean失败的解决方案

zuulFilter注入bean失败

一、为什么要用到这个

上周想实现在网关层 zuul 实现用户认证操作,即需要在网关过滤器中调用其他的微服务,按常规做法在 filter 中用 @Autowired 注解一个feign 接口,启动 一直失败,用度娘谷歌查了又查,只找到一些类似【在过滤器中注入bean】失败,但说的都是springMVC 并不是springcloud中的网关层

二、解决方法

查了很久,最终发现问题所在,其实在启动报错就提示很明显了,找不到相关实例,没错feign接口的实现类事实上在其他微服务中,自然不能用常规方法去注入,解决方法其实也很简单,就是在 启动类中 加入注解

?

1

@EnableFeignClient

声明这个 zuul 也是一个需要 feign 客户端,问题解决。

过滤器使用与bean注入

一、web.xml中各元素启动顺序

在项目启动时,监听器listener最先初始化,然后是过滤器filter,最后是servlet。

Spring监听器在启动时会读取spring配置文件,进行spring容器的初始化。springMVC的dispatcherServlet初始化时会读取springMVC的配置文件,进行springMVC容器的初始化。Spring容器初始化时会实例化各个bean。(个人认为web容器初始化时其中的各元素是按上述顺序依次初始化的,其他元素全部初始化完成之后web容器才初始化完成。但目前没有看到过一个十分确切的说法,等以后有时间研究一下源码)。

二、过滤器的使用

网上很多资料说在过滤器中拿不到spring注入的bean,原因是过滤器初始化时spring容器还没初始化好,其实并不是。下面看一段代码:

在web.xml中定义过滤器:

?

1

2

3

4

5

6

7

8

< filter >

   < filter-name >demoFilter</ filter-name > 

   < filter-class >xx.framework.filter.demoFilter</ filter-class >

</ filter >

< filter-mapping > 

< filter-name >demoFilter</ filter-name >

    < url-pattern >/*</ url-pattern >

</ filter-mapping >

然后在过滤器的初始化方法init中:

?

1

2

3

4

5

6

@Override

public void init(FilterConfig filterConfig) throws ServletException {

     ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());

     RedisTemplate demoBean = (RedisTemplate)context.getBean( "redisTemplate" );

     System.out.println(demoBean);

  }

经过测试,此时是可以拿到spring中的redisTemplate 这个bean的,说明spring容器确实先于过滤器初始化的。那么回到过滤器中不能注入bean的问题,原因究竟是什么呢?可以看到,这里获取bean是通过applicationContext获取的,而不是直接注入的。

个人理解是:过滤器是servlet规范中定义的,并不归spring容器管理,也无法直接注入spring中的bean(会报错)。当然,要想通过spring注入的方式来使用过滤器也是有办法的,先在web.xml中定义:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

< filter >

   < filter-name >DelegatingFilterProxy</ filter-name >

   < filter-class >org.springframework.web.filter.DelegatingFilterProxy</ filter-class >

   < init-param >

     < param-name >targetBeanName</ param-name >

     < param-value >demoFilter</ param-value >

   </ init-param >

   < init-param >

     < param-name >targetFilterLifecycle</ param-name >

     < param-value >true</ param-value >

   </ init-param >

</ filter >

< filter-mapping >

   < filter-name >DelegatingFilterProxy</ filter-name >

   < url-pattern >/*</ url-pattern >

</ filter-mapping >

然后在spring容器中配置demoFilter这个bean:

?

1

< bean id = "demoFilter" class = "xx.framework.filter.demoFilter" />

在doFilter方法中可以获取到注入的bean了:

?

1

2

3

4

@Override

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {

    System.out.println(redisTemplate.getClientList());

}

其中redisTemplate是通过@Resource注解注入进来的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/kysmkj/article/details/79136347

查看更多关于在zuulFilter中注入bean失败的解决方案的详细内容...

  阅读:18次