【问题标题】:Access to spring beans from OncePerRequestFilter从 OncePerRequestFilter 访问 spring bean
【发布时间】:2017-03-01 20:48:27
【问题描述】:

我想从OncePerRequestFilter类访问一个spring组件,但是当我访问服务时得到空指针,我认为这是配置的原因。 我认为由于配置,过滤器在 spring 调度程序 servlet 之前被调用。有什么好的方法可以完成这项工作,请提出建议。

<servlet>
    <servlet-name>SpringDispatcherServer</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/springConfig.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>SpringDispatcherServer</servlet-name>
    <url-pattern>/test/api/*</url-pattern>
</servlet-mapping>

<filter>
  <filter-name>AuthCheck</filter-name>
  <filter-class>org.test.util.AuthCheckFilter</filter-class>
</filter>    
<filter-mapping>
  <filter-name>AuthCheck</filter-name>
  <url-pattern>/test/api/*</url-pattern>
</filter-mapping>`

public class AuthCheckFilter extends OncePerRequestFilter 
{
@Autowired
private AuthCheckService authCheckService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
log.info("authCheckService"+authCheckService);

记录器为“authCheckService”打印空

【问题讨论】:

  • 添加AuthCheckFilter的代码。
  • 不确定上面的链接是否有帮助,因为控件甚至不会转到“Spring Dispatcher Servlet”,所以即使我们在spring config xml中将Filter注册为bean,它也不会我想帮助我们。
  • 我不知道我是幸运还是问题已经解决,但春季版本为 4.3.3。自动接线对我有用,没有任何问题。

标签: spring spring-mvc filter


【解决方案1】:

我不知道为什么@Autowire 不工作,但我通过使用 setter 注入让它工作了。

详情:

将它包含在您的 applicationContext.xml 文件中

    <bean name="AuthCheckFilter" class="x.y.AuthCheckFilter">
       <property name="authCheckService" ref="authCheckService"/>
    </bean>

    <bean name="authCheckService" class="x.y.AuthCheckService"/>

记得在 AuthCheckFilter 类中为 AuthCheckService 提供一个设置器。

将其包含在您的 web.xml 中:

 <filter>
    <filter-name>AuthCheckFilter</filter-name>
    <filter-class>
        org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>AuthCheckFilter</filter-name>
    <url-pattern>/test/api/*</url-pattern>
</filter-mapping>

就是这样。现在,如果您点击 url,您将获得非空 authCheckService。

【讨论】:

  • 注入到 authCheckService bean 中的其他 bean 怎么样,我认为所有这些都应该在 spring 上下文 xml 中声明。我也有 mybatis 配置,它正在使用 spring 加载。所以我猜现在必须手动加载而不是弹簧。
  • 即使在配置文件中声明了bean,也不是手动加载;您只是在声明哪个 bean 需要什么(告诉依赖项,spring 会解决它)。此外,您不必在 XML 中声明所有 bean,因为您可以简单地混合 XML 和注释。所以只对这些bean使用XML配置,其他bean仍然可以使用注解和&lt;component-scan /&gt;加载
  • 是的,是的。我在这个 authCheckFilter 之前有其他过滤器,不知道为什么,但我收到错误,
  • com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E:[Servlet 错误]-[SpringDispatcherServer]:java.lang.IllegalStateException:未找到 WebApplicationContext:未注册 ContextLoaderListener?org.springframework.web .filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:252)com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:195)com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java :91)com.ibm.tsc.qa.util.ValidationFilter.doFilterInternal(ValidationFilter.java:32)
  • 你有 ContextLoaderListener 添加到 web.xml 吗?
【解决方案2】:

您的过滤器是在 Spring 容器之外配置的。因此,您的 @Autowired 依赖项不会被注入。

要让您的 Filter bean 由 Spring 管理,而不通过建议使用 SpringBeanAutowiringSupport 将其紧密耦合到 Spring 基础架构,您可以使用 DelegatingFilterProxy 抽象

将 AuthCheckFilter 过滤器定义为应用程序上下文中的 bean,例如

@Bean
public Filter authCheckFilter(){
     AuthCheckFilter filter = new AuthCheckFilter();
     //supply dependencies
     return filter;
}

然后在您的 web.xml 中使用 filter-class 指定您的过滤器为 org.springframework.web.filter.DelegatingFilterProxy 并且过滤器名称必须与上下文中的 authCheckFilter bean 名称匹配

在运行时 DelegatingFilterProxy 过滤器将委托给上下文中名称为 authCheckFilter 的完全配置的 bean(它必须是一个过滤器)

<filter>
  <filter-name>authFilterCheck</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>    
<filter-mapping>
  <filter-name>authCheckFilter</filter-name>
  <url-pattern>/test/api/*</url-pattern>
</filter-mapping>

使用此设置,您不必担心过滤器、根上下文或 servlet 的生命周期

【讨论】:

    【解决方案3】:

    将此添加到您的 init() OncePerRequestFilter 中,以便 spring 可以连接您的自动装配 bean

    public void init(FilterConfig filterConfig) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
                filterConfig.getServletContext());
    }
    

    【讨论】:

    • 你能解释一下它在这种情况下的帮助吗?
    • /* 是侵入式 url 模式,它将覆盖所有其他映射,添加 /* 到过滤器,以便请求在调度 servlet 之前进行过滤。 / 表示这将是默认映射,如果没有找到任何映射,它将从这里提供。那么哪个应该是你的 dispath servlet 映射阅读更多stackoverflow.com/questions/4140448/…
    • 即使是现在,请求也会在到达 spring dispatcher servlet 之前进行过滤,这就是我认为服务为空的原因。
    • 是的,过滤器没有被弹簧实例化,因此它不能被弹簧自动装配。我已经更新了我的答案
    • OncePerRequestFilter 不能覆盖 final init 方法。此外,覆盖 initFilterBean() 并在其中调用 getFilterConfig() 会返回 null。不确定,这对支持者有何影响。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    相关资源
    最近更新 更多