`
yangzb
  • 浏览: 3471685 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Injecting Spring Beans into Java Servlets

阅读更多

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:

  1. It is-a javax.servlet.http.HttpServlet - completes one of the requirements.
  2. 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.

References

分享到:
评论

相关推荐

    Manning.Spring.in.Action.4th.Edition.2014.11.epub

    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. ...

    Pro CDI 2 in Java EE 8.pdf

    Programmatically retrieve bean instances from the CDI container in both Java SE and Java EE when injecting them into an object isn’t possible Dynamically replace beans using the @Alternative ...

    maven3.6.3资源包

    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 Java EE 6 Tutorial Basic Concepts 4th Edition

    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 ...

    AngularJs Injecting Services Into Controllers详解

    本文主要介绍AngularJs Injecting Services Into Controllers的知识,这里整理了一下相关资料,及示例代码,帮助大家学习和理解,有兴趣的小伙伴可以参考下

    Spring的学习笔记

    三、 注入类型(Injecting dependencies) 9 (一) setter注入类型Setter Injection 9 (二) 构造方法Constructor Injection 10 四、 id、name 11 五、 简单属性的注入 11 六、 Bean的作用范围scope 12 七、 集合注入 12...

    NDSS2020论文集

    NDSS2020论文集

    spring2.5 学习笔记

    三、 注入类型(Injecting dependencies) 9 (一) setter注入类型Setter Injection 9 (二) 构造方法Constructor Injection 10 四、 id、name 11 五、 简单属性的注入 11 六、 Bean的作用范围scope 12 七、 集合注入 12...

    spring-framework-reference-4.1.2

    4.1. Introduction to the Spring IoC container and beans .............................................. 22 4.2. Container overview .........................................................................

    Android Native Development Kit Beginner’s Guide

    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...

    framework for injecting configurations via CDI

    framework for injecting configurations via CDI

    前端开源库-injecting

    前端开源库-injecting注入,一个简单的javascript依赖注入模块

    Beginning Windows Phone 7 Development

    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...

    Android NDK Beginner's Guide

    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...

    spring-framework-reference4.1.4

    4.1. Introduction to the Spring IoC container and beans .............................................. 22 4.2. Container overview .........................................................................

    Havij SQL Injection

    Havij是一款自动化的SQL注入工具,它能够帮助渗透测试人员发现和利用Web应用程序的SQL注入漏洞。Havij不仅能够自动挖掘可利用的SQL 查询,还能够...Havij支持广泛的数据库系统,如 MsSQL, MySQL, MSAccess and Oracle。...

    Fault insertion testing of a novel CPLD-based fail-safe system.pdf

    This allows injecting a fault into this CPLD. The other CPLD is configured as fault-free device. The entire system has to detect the injected fault using its safety integrity measures. Consequently ...

    Beginning.Windows.Phone.7.Development

    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...

Global site tag (gtag.js) - Google Analytics