spring - 如何在 Java 配置中使用 delegatingFilterproxy?

标签 spring spring-mvc servlet-filters

DelegatingFilterProxy 有两个可以在我的应用程序中使用的构造函数

new DelegatingFilterProxy(String beanName);
new DelegatingFilterProxy(Filter delegate);

在我的 webappIntializer ,我有以下。 (请参阅下面的完整代码)。
servletContext.addFilter("counterMetricsFilter", new DelegatingFilterProxy("counterMetricsFilter").addMappingForUrlPatterns(null,
                false, MAPPING_URL);

我不确定 DelegatingFilterProxy在我的情况下按预期运行。
Controller
@Controller
@RequestMapping("/counter")
public class CounterController {

@Autowired
CounterManager manager;

 @RequestMapping(value = "/counterMetrics", method = RequestMethod.GET)
    @ResponseBody
    public Map getFeatureStatus(final HttpServletResponse response) {
        System.out.println("returning feautre status");
        return manager.getQueryCounts();
    }
}
Manager
@Service
public class CounterManager {

private Map<String,Integer> queryCounts =
            new ConcurrentHashMap<String,Integer>(1000);

int threshold;
long timestamp;

 @Autowired
  public CounterManager(@Value("${healthThreshold: 10}")
                                 int threshold) {
      this.threshold = threshold * MEGABYTES;
      this.timestamp = System.currentTimeMillis();
  }


 public void incrementRequestCounter(String urlPath){
     Integer oldVal, newVal;
     do {
       oldVal = queryCounts.get(model);
       newVal = (oldVal == null) ? 1 : (oldVal + 1);
     } while (!queryCounts.replace(model, oldVal, newVal));
 }

public Map<StatusUrlModel, Integer> getQueryCounts() {
    return queryCounts;
}

}
Filter
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component(value="counterMetricsFilter")
public class CounterMetricsFilter extends OncePerRequestFilter {

    @Autowired
    CounterManager manager;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain) throws ServletException,
            IOException {
        String path = new UrlPathHelper().getPathWithinApplication(request);
        try {
            chain.doFilter(request, response);
        }
        finally {
            recordMetrics(request, path);
        }
    }

   private void recordMetrics(String path) {
        try {
        manager.incrementRequestCounter(url);
        }
        catch (Exception ex){
            System.out.println("exception is thrown " + ex.getCause());
            ex.printStackTrace();
        }
    }
}

DelegatingFilterProxy
public class myAppWebAppInitializer implements WebApplicationInitializer {

             private static final String CONFIG_LOCATION = "com.myapp.sample.config";
            public static final String MAPPING_URL = "/*";

            @Override
            public void onStartup(ServletContext servletContext) throws ServletException {

     AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    context.setConfigLocation(CONFIG_LOCATION);

                servletContext.addListener(new ContextLoaderListener(context));

                servletContext.addFilter("counterMetricsFilter", new DelegatingFilterProxy("counterMetricsFilter").addMappingForUrlPatterns(null,
            false, MAPPING_URL);

                ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(
                        context));
                dispatcher.setLoadOnStartup(1);
                dispatcher.addMapping(MAPPING_URL);
            }

    }

注意 : 容器启动正常。请求顺利通过。因为这条线manager.incrementRequestCounter(url)CounterMetricsFilter上面是抛出异常,我正在捕捉它,我看到空响应。
我怀疑 delegateFilterProxy不是 autowiring适本地。

另请注意 manager bean 被加载到应用程序上下文中,因为我可以在 CounterController 中检查 bean .

我无法修复它。这里的任何提示都会非常有帮助。

编辑

通过更改为 constructor injection而不是 CounterMetricsFilter 中的现场注入(inject),我得到以下异常。

//我删除了上面的无参数构造函数
@自动连线
公共(public) CounterMetricsFilter(HealthManager healthManager){
this.healthManager=健康管理器;
}

堆栈跟踪
SEVERE: Exception starting filter counterMetricsFilter
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'counterMetricsFilter' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:638)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1159)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:282)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:979)
    at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:324)
    at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:235)
    at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:199)
    at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:281)
    at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:111)
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4775)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5452)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1113)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1671)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
  [1]: http://stackoverflow.com/questions/32573742/why-is-autowired-bean-null-in-filter-in-this-spring-application

最佳答案

我在上面的代码片段中没有看到配置类本身,所以列出了如何制作 DelegatingFilterProxy 的通用解决方案使用 Spring Java 配置。

初始化器

public class MyWebAppInitializer implements WebApplicationInitializer {
    ...
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        ...
        servletContext.addFilter("myFilter", new DelegatingFilterProxy("myFilter"))
                .addMappingForUrlPatterns(null, true, "/*");
        ...
    }
    ...
}

过滤器
public class MyFilter implements Filter {
    ...
    // I added this parameter just as example of how Spring-managed dependencies
    // could be injected. Note, there is no any annotations in this class.
    private String someParameter;
    public MyFilter(String someParameter) {
        this.someParameter = someParameter;
    }
    ...
}

配置
@Configuration
@EnableWebMvc
@PropertySource(value = {
        "classpath:my.properties"
})
@Import({
        PropertySourcesPlaceholderConfigurer.class
})
public class MyConfig {
    ...
    @Bean
    public MyFilter myFilter(@Value("${someParameter}") String someParameter) {
        return new MyFilter(someParameter);
    }
    ...
}

希望它对某人有用。

关于spring - 如何在 Java 配置中使用 delegatingFilterproxy?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32592931/

相关文章:

java - 查看 Spring MVC 中的逻辑

java - Spring Controller 请求映射未被识别

java - 使用 Stripes 框架拦截和更改请求 url

java - 如何使用基于 Java 的注释配置的 Spring MVC 全局处理 404 异常

java - 如何将数据传递给作为 MethodInvokingJobDetailFactoryBean 运行的方法?

java - 使用AOP后注入(inject)的bean变为null

java - 我们是否有任何机制可以使用 Keycloak IDP 的 java servlet 适配器在客户端应用程序上进行注销后 Activity ?

spring - 如何仅以 thymeleaf 形式传递字符串?

java - 使用 Spring 时为 Controller 使用不同的包

java - 在 applicationcontext.xml 中添加自定义过滤器类