问题描述
DelegatingFilterProxy 有两个构造函数,我可以在我的应用程序中使用
DelegatingFilterProxy has two constructors that I can use in my application
new DelegatingFilterProxy(String beanName);
new DelegatingFilterProxy(Filter delegate);
在我的 webappIntializer
中,我有以下内容.(请参阅下面的完整代码).
In my webappIntializer
, I have the following. (please see below for full code).
servletContext.addFilter("counterMetricsFilter", new DelegatingFilterProxy("counterMetricsFilter").addMappingForUrlPatterns(null,
false, MAPPING_URL);
我不确定 DelegatingFilterProxy
在我的情况下是否按预期运行.
I am not sure if DelegatingFilterProxy
is functioning as expected in my case.
控制器
@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();
}
}
经理
@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;
}
}
过滤器
@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);
}
}
注意:容器启动正常.请求顺利通过.因为上面 CounterMetricsFilter
中的这一行 manager.incrementRequestCounter(url)
抛出异常,我正在捕获它,我看到空响应.我怀疑 delegateFilterProxy
没有正确autowiring
.
NOTE: The container start-up fine. Requests go through fine. because this line manager.incrementRequestCounter(url)
in CounterMetricsFilter
above is throwing exception, and I am catching it, I see empty response.I suspect delegateFilterProxy
is not autowiring
properly.
另请注意,manager
bean 是在应用程序上下文中加载的,因为我可以在 CounterController
中检查 bean.
Also Note that manager
bean is loaded in Application Context because I can inspect the bean in CounterController
.
我无法修复它.这里的任何提示都会非常有帮助.
I am unable to fix it. Any tips here would be very helpful.
编辑
通过更改为 constructor injection
而不是 CounterMetricsFilter
中的字段注入,我得到以下异常.
by changing to constructor injection
instead of field injection in CounterMetricsFilter
, I get the following exception.
//我去掉了上面的无参数构造函数@自动连线公共 CounterMetricsFilter(HealthManager healthManager){this.healthManager=healthManager;}
//I removed the no-arg constructor above @Autowired public CounterMetricsFilter(HealthManager healthManager){ this.healthManager=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 配置.
I don't see configuration class itself among the code snippets above, so listing the general solution how to make DelegatingFilterProxy
work with Spring Java Config.
初始化程序
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);
}
...
}
希望它对某人有用.
这篇关于如何在 Java 配置中使用 delegatingFilterproxy?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!