【问题标题】:Spring Boot: Inject Bean into HttpServletSpring Boot:将 Bean 注入 HttpServlet
【发布时间】:2017-04-27 09:57:32
【问题描述】:

我有一个 Spring Boot,我在其中自动配置了一个路由器 bean。 这一切都很完美,但是当我想将该 bean 注入自定义 servlet 时,它就成了一个问题:

public class MembraneServlet extends HttpServlet {
    @Autowired
    private Router router;

    @Override
    public void init() throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        new HttpServletHandler(req, resp, router.getTransport()).run();
    }
}

这应该是要走的路,但是

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

不会自动连接路由器,因为WebapplicationContext 始终为空。应用程序在 MVC 环境中运行。

【问题讨论】:

  • 你的httpservlet是否被spring boot嵌入?
  • 这不是stackoverflow.com/questions/18745770/…的复制品吗?
  • 您是否考虑过使用@Controller@RestController 代替servlet?我认为这是在 spring-boot 中做事的一种更可取的方式

标签: spring spring-boot


【解决方案1】:

假设您将 Spring Application Context 连接到 Servlet Context,您可能希望将 ServletContext 传递给 SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext

public class MembraneServlet extends HttpServlet {

  @Autowired
    private Router router;

    @Override
    public void init() throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this, getServletContext());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        new HttpServletHandler(req, resp, router.getTransport()).run();
    }
}

【讨论】:

    【解决方案2】:

    注入'Router'作为构造函数参数怎么样。

    所以你会得到这个:

    public class MembraneServlet extends HttpServlet {
    
        private Router router;
    
        public MembraneServlet(Router router){
            this.router = router;
        }
    
        @Override
        public void init() throws ServletException {
            SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        }
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            new HttpServletHandler(req, resp, router.getTransport()).run();
        }
    }
    

    然后您可以像这样以编程方式创建 servlet 注册:

    @Bean
    public ServletRegistrationBean membraneServletRegistrationBean(){
        return new ServletRegistrationBean(new MembraneServlet(),"/*");
    }
    

    【讨论】:

    • 那行不通,因为 Spring 没有实例化 HttpServlet。
    • 抱歉,我复制了 OP 的代码,但没有删除 SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);,如果只需要 Router bean,这是不必要的。
    【解决方案3】:

    嵌入式服务器

    您可以使用 @WebServlet 注释您的 servlet 类:

    @WebServlet(urlPatterns = "/example")
    public class ExampleServlet extends HttpServlet 
    

    并在基类上启用@ServletComponentScan

    @ServletComponentScan
    @EntityScan(basePackageClasses = { ExampleApp.class, Jsr310JpaConverters.class })
    @SpringBootApplication
    public class ExampleApp 
    

    @ServletComponentScan 注入仅适用于嵌入式服务器:

    启用对 Servlet 组件(过滤器、servlet 和 听众)。仅在使用嵌入式 Web 时执行扫描 服务器。

    更多信息:The @ServletComponentScan Annotation in Spring Boot

    外部服务器

    使用外部服务器时,将HttpServlet类标记为@Component

    @Component
    public class ExampleServlet extends HttpServlet 
    

    并创建配置类:

    @Configuration
    @ComponentScan(value = "com.example.servlet.package")
    public class ServletConfig {
    
        @Autowired
        private ExampleServlet exampleServlet;
    
        @Bean
        public ServletRegistrationBean resetServletRegistrationBean(){
            return new ServletRegistrationBean(exampleServlet, "/example");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 2020-05-11
      • 1970-01-01
      • 2012-02-19
      • 2011-05-29
      • 1970-01-01
      相关资源
      最近更新 更多