java - Servlet 3.0 配置中将 Bean 声明为 Scope request 的问题

标签 java spring servlets servlet-3.0

我正在将我的应用程序从使用 web.xml 配置 servlet 迁移到使用实现 WebApplicationInitializer 的类来配置我的 Web 应用程序。 将所有内容迁移到实现 WebApplicationInitializer 的类后,我无法启动我的应用程序,它提示因为它无法注入(inject)已使用请求范围声明的 bean。我在 servlet 上下文中添加了 RequestContextListener,但它仍然无法注入(inject) bean。

这是服务器在尝试部署后返回的堆栈跟踪:

SEVERE: Servlet /TopUp-Services threw load() exception
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestCon textHolder.currentRequestAttributes(RequestContext Holder.java:131)
at org.springframework.web.context.request.AbstractRe questAttributesScope.get(AbstractRequestAttributes Scope.java:41)
at org.springframework.beans.factory.support.Abstract BeanFactory.doGetBean(AbstractBeanFactory.java:330 )
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.findAutowireCandidates(DefaultL istableBeanFactory.java:912)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.doResolveDependency(DefaultList ableBeanFactory.java:855)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.resolveDependency(DefaultListab leBeanFactory.java:770)
at org.springframework.beans.factory.support.Construc torResolver.resolveAutowiredArgument(ConstructorRe solver.java:811)
at org.springframework.beans.factory.support.Construc torResolver.createArgumentArray(ConstructorResolve r.java:739)
at org.springframework.beans.factory.support.Construc torResolver.autowireConstructor(ConstructorResolve r.java:193)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.autowireConstructor(Abs tractAutowireCapableBeanFactory.java:1075)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBeanInstance(Abst ractAutowireCapableBeanFactory.java:979)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.doCreateBean(AbstractAu towireCapableBeanFactory.java:487)
at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.Abstract BeanFactory$1.getObject(AbstractBeanFactory.java:2 96)
at org.springframework.beans.factory.support.DefaultS ingletonBeanRegistry.getSingleton(DefaultSingleton BeanRegistry.java:223)
at org.springframework.beans.factory.support.Abstract BeanFactory.doGetBean(AbstractBeanFactory.java:293 )
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:628)
at org.springframework.context.support.AbstractApplic ationContext.finishBeanFactoryInitialization(Abstr actApplicationContext.java:932)
at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:479)
at org.springframework.web.servlet.FrameworkServlet.c onfigureAndRefreshWebApplicationContext(FrameworkS ervlet.java:658)
at org.springframework.web.servlet.FrameworkServlet.i nitWebApplicationContext(FrameworkServlet.java:530 )
at org.springframework.web.servlet.FrameworkServlet.i nitServletBean(FrameworkServlet.java:484)
at org.springframework.web.servlet.HttpServletBean.in it(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.j ava:158)
at org.apache.catalina.core.StandardWrapper.initServl et(StandardWrapper.java:1284)
at org.apache.catalina.core.StandardWrapper.load(Stan dardWrapper.java:1090)
at org.apache.catalina.core.StandardContext.loadOnSta rtup(StandardContext.java:5210)
at org.apache.catalina.core.StandardContext.startInte rnal(StandardContext.java:5493)
at org.apache.catalina.util.LifecycleBase.start(Lifec ycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild. call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild. call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.jav a: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)

这是我的 WebApplicationInitializer 实现类:

package com.topup.services.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.apache.catalina.filters.CorsFilter;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.request.RequestCon textListener;
import org.springframework.web.context.support.Annotation ConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterPro xy;
import org.springframework.web.servlet.DispatcherServlet;

public class WebApp implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext)
throws ServletException {
setWebApplicationContext(servletContext);
setFilters(servletContext);
setListeners(servletContext);

}

/**
* Return the WebApplicationContext
* 
* @param servletContext
* An instance of {@link javax.servlet.ServletContext}
*/
private void setWebApplicationContext(ServletContext servletContext) {

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.topup.services");

ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/TopUp-Services");

}

/**
* Set ServletContext Filters
* 
* @param servletContext
* An instance of {@link javax.servlet.ServletContext}
*/
private void setFilters(ServletContext servletContext) {

servletContext.addFilter("corsFilter", new CorsFilter())
.getUrlPatternMappings().add("/TopUp-Services");
servletContext
.addFilter("springSecurityFilterChain",
new DelegatingFilterProxy("springSecurityFilterChain") )
.getUrlPatternMappings().add("/TopUp-Services");

}

/**
* Set ServletContext listeners
* 
* @param servletContext
* An instance of {@link javax.servlet.ServletContext}
*/
private void setListeners(ServletContext servletContext) {

servletContext.addListener(new RequestContextListener());
}
}

这是我的配置类:

package com.topup.services.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configurati on;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationCont ext;

import com.topup.services.user.service.UserProfileService ;
import com.topup.services.user.service.UserProfileService Impl;

/**
* 
* Application configuration class
*
*/
@Configuration
public class AppConfig {

/**
* Returns instance of UserProfileService for the request
* 
* @return A request instance of
* {@link com.topup.services.user.service.UserProfileService }
*/
@Bean
@Scope(WebApplicationContext.SCOPE_REQUEST)
public UserProfileService getUserProfileService() {
return new UserProfileServiceImpl();
}

}

我非常感谢您尝试解决该问题的帮助,如果有人想观看完整的源代码,该项目位于此 git hub 存储库中。

https://github.com/alexzm1/TopUp-Services/tree/migrate-java8-servlet3-spring4

希望各位 Spring 专家能帮我解决这个问题,谢谢:)

最佳答案

当然,Spring无法在Web应用程序初始化期间实例化和注入(inject)您的bean(当时没有 Activity 请求)。您需要允许 Spring 为此创建所谓的作用域代理 - 即,将创建一个特殊的代理而不是您的 bean,并将其用作注入(inject)的依赖项(实际的目标 bean 将以惰性方式实例化):

@Bean
@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode=ScopedProxyMode.INTERFACES)
public UserProfileService getUserProfileService() {
    return new UserProfileServiceImpl();
}

这类似于 <aop:scoped-proxy /> XML配置

关于java - Servlet 3.0 配置中将 Bean 声明为 Scope request 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23724716/

相关文章:

java - HttpURLConnection 保持缓存

java - 请求方法 'GET' 不受支持,但它实际上存在于 Controller 中

java - 最佳实践,java web应用程序,jsp文件放在哪里?

java - 重定向不适用于 Https

java - 无法在Spring Cloud中调用Rest Endpoint

java - 为什么多态性在这种情况下不起作用?

java - Maven:MojoExecutionException。请添加 'mainClass' 属性

java - 可以在浏览器工具中查看httpservletrequest数据吗?

java - 有没有办法用比这更少的代码扩展现有的接口(interface)实现?

java - Spring-security session 在 java 线程中不可用