If you are working in a Java Web Application and you are using Spring IoC Container in your application, there is a chance that you might have to inject Spring Beans into a Java Servlet.
Since there is not a direct way to inject Spring Beans into a Java
Servlet, you might try to lookup the Spring Beans from the Spring
Context within your servlet and assign the dependencies which means that
part of injection would no more be IoC and you would be looking for
some concise way of doing this.
To solve this problem, Spring provides a trick which is a class called org.springframework.web.context.support.HttpRequestHandlerServlet
which consists of two behaviors:
- It is-a javax.servlet.http.HttpServlet - completes one of the requirements.
- and, it is a wrapper around org.springframework.web.HttpRequestHandler which has to be Spring Bean configured with bean injections, if any, to achieve the second goal (dependency injection). This is an interface which has a method called handleRequest(HttpServletRequest request, HttpServletResponse response) which the HttpRequestHandlerServlet delegates to while serving a request. So you need to implement this interface and have the dependencies wired in that class.
Note! Your servlet name (1) and you bean id (2) must match because HttpRequestHandlerServlet uses the servlet name to look up the beans form the context.
Now let’s look at an example:
- Write your Spring bean (which is also a request handler / implements HttpRequestHandler). This bean should be configured to be component scanned. In the example below, this bean has a service called HelloService wired using Spring DI annotation @Autowired which will be injected by the Spring IoC container.
/** * AnnotatedHttpServletRequestHandler.java * Feb 15, 2012 */ package com.sourceallies.spring.noxml.demo.web.servlet.handler ; import java.io.IOException ; import java.io.PrintWriter ; import java.util.logging.Logger ; import javax.servlet.ServletException ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; import org.springframework.beans.factory.annotation.Autowired ; import org.springframework.stereotype.Component ; import org.springframework.web.HttpRequestHandler ; import com.sourceallies.spring.noxml.demo.service.HelloService ; /** * @author Lal * */ @Component ( "annotatedServletHandler" ) public class AnnotatedHttpServletRequestHandler implements HttpRequestHandler { private static final Logger LOGGER = Logger.getLogger ( AnnotatedHttpServletRequestHandler.class .getName ( ) ) ; @Autowired private HelloService helloService; @Override public void handleRequest( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType ( "text/html" ) ; PrintWriter writer = response.getWriter ( ) ; writer.write ( "<h1>Spring Beans Injection into Java Servlets!</h1><h2>" + helloService.sayHello ( "World" ) + "</h2>" ) ; }
- Write your Servlet. This servlet class extends org.springframework.web.context.support.HttpRequestHandlerServlet.
package com.sourceallies.spring.noxml.demo.web.servlet ; import javax.servlet.annotation.WebServlet ; import org.springframework.web.context.support.HttpRequestHandlerServlet ; /** * Servlet implementation class AnnotatedHttpServlet */ @WebServlet( description = "Http Servlet using pure java / annotations" , urlPatterns = { "/annotatedServlet" } , name = "annotatedServletHandler" ) public class AnnotatedHttpServlet extends HttpRequestHandlerServlet { private static final long serialVersionUID = 1L; }
Notice the @Component(”annotatedServletHandler”) and @WebServlet(…, name = “annotatedServletHandler”). The bean id and the servlet name are exactly same.
Now, this will absolutely work and in fact you got access to Spring Beans from the Servlet provided that your Spring bean annotatedServletHandler was registered in the Spring Root Context (the context that is setup using org.springframework.web.context.ContextLoaderListener ). However, it could be possible that your Web related beans, annotatedServletHandler for instance, are registered in the Spring Dispatcher Context. If this is the case, the previous example would not work. This leads to a situation where you have to implement your own HttpRequestHandlerServlet that could lookup both root and dispatcher contexts.
Here is an implementation of such a HttpRequestHandlerServlet which is pretty much similar to what Spring provides but with added functionality to support dispatcher context as well.
package com.sourceallies.spring.noxml.demo.web.servlet.framework ; import java.io.IOException ; import java.util.logging.Logger ; import javax.servlet.ServletException ; import javax.servlet.http.HttpServlet ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; import org.springframework.beans.factory.NoSuchBeanDefinitionException ; import org.springframework.context.i18n.LocaleContextHolder ; import org.springframework.util.StringUtils ; import org.springframework.web.HttpRequestHandler ; import org.springframework.web.HttpRequestMethodNotSupportedException ; import org.springframework.web.context.WebApplicationContext ; import org.springframework.web.context.support.WebApplicationContextUtils ; import org.springframework.web.servlet.FrameworkServlet ; import com.sourceallies.spring.noxml.demo.initializer.ApplicationContextInitializer ; @SuppressWarnings( "serial" ) public class MyHttpRequestHandlerServlet extends HttpServlet { private static final Logger LOGGER = Logger.getLogger ( MyHttpRequestHandlerServlet.class .getName ( ) ) ; // Replace ApplicationContextInitializer.DISPATCHER_SERVLET_NAME with the // name of your dispatcher servlet private static final String DISPATCHER_CONTEXT_ATTRIBUTE_NAME = FrameworkServlet.SERVLET_CONTEXT_PREFIX + ApplicationContextInitializer.DISPATCHER_SERVLET_NAME ; private HttpRequestHandler target; @Override public void init( ) throws ServletException { WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext ( getServletContext( ) ) ; try { this .target = ( HttpRequestHandler) wac.getBean ( getServletName( ) , HttpRequestHandler.class ) ; } catch ( NoSuchBeanDefinitionException e) { LOGGER.info ( "HTTP Request Handler bean was not found in Spring Root Context! Now looking up in the Dispatcher Context..." ) ; WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext ( getServletContext( ) , DISPATCHER_CONTEXT_ATTRIBUTE_NAME) ; this .target = ( HttpRequestHandler) context.getBean ( getServletName( ) , HttpRequestHandler.class ) ; } } @Override protected void service( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { LocaleContextHolder.setLocale ( request.getLocale ( ) ) ; try { this .target .handleRequest ( request, response) ; } catch ( HttpRequestMethodNotSupportedException ex) { String [ ] supportedMethods = ( ( HttpRequestMethodNotSupportedException) ex) .getSupportedMethods ( ) ; if ( supportedMethods != null ) { response.setHeader ( "Allow" , StringUtils.arrayToDelimitedString ( supportedMethods, ", " ) ) ; } response.sendError ( HttpServletResponse.SC_METHOD_NOT_ALLOWED , ex.getMessage ( ) ) ; } finally { LocaleContextHolder.resetLocaleContext ( ) ; } } }
The rest are normal Spring configurations.
相关推荐
2.3.3. Injecting with JavaConfig 2.4. Wiring beans with XML 2.4.1. Creating an XML configuration specification 2.4.2. Declaring a simple 2.4.3. Initializing a bean with constructor injection 2.4.4. ...
1) Error injecting constructor, java.lang.NoSuchMethodError: org.apache.maven.model.validation.DefaultModelValidator: method 'void ()' not found at org.jetbrains.idea.maven.server.embedder....
- **The beans**: Bean是Spring中的基本组件,可以是任何Java对象。 **3.3 依赖注入** - **Injecting dependencies**: Spring支持多种方式注入依赖,包括构造函数注入、属性注入等。 - **Constructor Argument ...
Injecting Beans 310 Using Scopes 310 Giving Beans EL Names 312 Adding Setter and Getter Methods 312 Using a Managed Bean in a Facelets Page 313 Injecting Objects by Using Producer Methods 314 ...
在IT行业中,Spring框架是Java开发中的一个核心组件,它以其强大的依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IOC)功能而闻名。本篇文章将详细解析“模拟Spring IOC技术”的...
- **Injecting Dependencies**:Spring提供了多种注入方式,如构造器注入、属性注入等。 - **Constructor Argument Resolution**:当一个Bean需要多个依赖时,可以通过构造器参数的方式进行传递。 - **Bean ...
AngularJs是Google开发的一个开源前端框架,主要用于构建动态网页应用。在AngularJs中,依赖注入(Dependency Injection,简称DI)是一种让代码更加模块化和易于管理的技术,它可以让开发者在运行时根据需要将服务...
标题 "framework for injecting configurations via CDI" 指涉的是一个使用Java企业版(JavaEE)中的Contexts and Dependency Injection(CDI)框架来注入配置的解决方案。CDI是JavaEE平台的一部分,它允许开发者在...
4.1. Introduction to the Spring IoC container and beans .............................................. 22 4.2. Container overview .........................................................................
NDSS2020论文集
Android NDK is all about injecting high performance into your apps. Exploit the maximum power of these mobile devices using high-performance and portable code. This book will show you how to create C...
"injecting"是一个专注于javascript依赖注入的开源库,它的主要目标是简化代码结构,提高模块间的解耦性,使代码更易于测试和维护。 依赖注入(Dependency Injection,简称DI)是一种设计模式,它允许我们在不修改...
Microsoft is injecting new energy into the smart phone marketplace with the sophisticated Windows Phone 7. This new energy equates to new opportunities for you, the mobile developer. Beginning Windows...
4.1. Introduction to the Spring IoC container and beans .............................................. 22 4.2. Container overview .........................................................................
Havij是一款自动化的SQL注入工具,它能够帮助渗透测试人员发现和利用Web应用程序的SQL注入漏洞。Havij不仅能够自动挖掘可利用的SQL 查询,还能够...Havij支持广泛的数据库系统,如 MsSQL, MySQL, MSAccess and Oracle。...
6. **在页面中注入Bean(Injecting Beans into Pages):** - 在页面Java类中注入Spring Bean,方便调用Bean提供的服务。 通过上述核心知识点的学习,开发者可以快速掌握Tapestry 5.1框架的基本用法和高级特性,从而...