OSGI企业应用开发(十四)整合Spring、Mybatis、Spring MVC
作为一个企业级的Web应用,MVC框架是必不可少的。Spring MVC目前使用也比较广泛,本文就来介绍一下如何在OSGI应用中实现Spring、Mybatis、Spring MVC框架的整合,其中Spring MVC的整合比较困难,原因是Spring整合到OSGI中后,每个Bundle都拥有一个孤立的ApplicationContext,也就是说不同Bundle中实例化的Bean之间的依赖注入就存在一定的问题,前面文章中提到过,这个问题可以通过Bean的注册和引用机制解决。
而实例化Spring MVC框架中的org.springframework.web.servlet.DispatcherServlet类时也需要指定Bean的配置文件,Spring MVC框架启动后会实例化配置文件中的Bean(例如Controller实例),Spring MVC框架启动后实例化的Bean与Bundle中实例化的Bean属于不同的类加载器,所以Bundle中实例化的Bean无法注入到Spring MVC框架启动时实例化的Bean,比较直接的例子就是Mybatis操作数据库的SqlSession实例无法注入到Spring MVC的Controller中,网上比较多的解决方案是使用Virgo,笔者经过一番钻研,解决了Spring MVC框架与OSGI应用的整合,如果发现有什么问题,可以一起探讨下^_^。
接下来就介绍OSGI应用中Spring、Mybatis、Spring MVC框架的整合,我们依然使用前面文章中已经搭建好的工作空间。
首先新建一个Bundle,名称为com.csdn.osgi.user.web,整个工作空间结构如下图所示:
由于OSGI应用中资源与Servlet都需要注册后才能被客户端访问,我们可以编写几个类专门用于注册Web资源。
首先是图片、CSS、JS等静态资源的注册,在com.csdn.osgi.user.web这个Bundle中新建一个类,名称为com.csdn.osgi.user.web.registry.ResourceRegistry,代码如下:
package com.csdn.osgi.user.web.registry;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.gemini.blueprint.context.BundleContextAware;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ResourceRegistry implements ApplicationContextAware,
BundleContextAware {
Map resMapping;
BundleContext bundleContext;
ApplicationContext applicationContext;
@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public void setResMapping(Map resMapping) {
this.resMapping = resMapping;
}
public void init() {
ServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());
HttpService httpService = (HttpService) bundleContext.getService(serviceReference);
HttpContext commonContext = httpService.createDefaultHttpContext();
try {
Set keySet = resMapping.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
String value = (String) resMapping.get(key);
httpService.registerResources(key, value, commonContext);
}
} catch (NamespaceException e) {
e.printStackTrace();
}
}
}
我们可以通过Spring来实例化这个类,Bean的配置如下:
<bean name="resourceRegistry" class="com.csdn.osgi.user.web.registry.ResourceRegistry" init-method="init">
<property name="resMapping">
<map>
<entry key="/js" value="/WebContent/js"/>
<entry key="/css" value="/WebContent/css"/>
<entry key="/images" value="/WebContent/images"/>
</map>
</property>
</bean>
这样就可以完成静态资源的注册,这种方式比较灵活,如果有新的资源类型,只需要在map标签中增加一个新的entry标签即可。
接下来是JSP的注册,我们在com.csdn.osgi.user.web这个Bundle中新建一个类,名称为 com.csdn.osgi.user.web.registry.JspRegistry,代码如下:
package com.csdn.osgi.user.web.registry;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.servlet.ServletException;
import org.eclipse.equinox.jsp.jasper.JspServlet;
import org.eclipse.gemini.blueprint.context.BundleContextAware;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class JspRegistry implements ApplicationContextAware,
BundleContextAware {
BundleContext bundleContext;
ApplicationContext appContext;
@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
this.appContext = appContext;
}
public void init() {
ServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());
HttpService httpService = (HttpService) bundleContext.getService(serviceReference);
HttpContext commonContext = httpService.createDefaultHttpContext();
Dictionary initparams = new Hashtable<String, String>();
JspServlet jspServlet = new JspServlet(bundleContext.getBundle(), "/WebContent/WEB-INF/jsp", "/jsp");
try {
httpService.registerServlet("/jsp", jspServlet, initparams, commonContext);
} catch (ServletException e) {
e.printStackTrace();
} catch (NamespaceException e) {
e.printStackTrace();
}
}
}
同样,也是在Spring中实例化JspRegistry,Bean的配置如下:
<bean name="jspRegistry" class="com.csdn.osgi.user.web.registry.JspRegistry" init-method="init">
</bean>
最后就是Servlet资源的注册了,使用Spring MVC框架,我们需要实例化一个DispatcherServlet对象,需要注意的是,DispatcherServlet对象不能通过new关键字创建,应该由Spring框架实例化,在com.csdn.osgi.user.web这个Bundle中新建一个类,名称为com.csdn.osgi.user.web.registry.DispatcherServletRegistry,代码如下:
package com.csdn.osgi.user.web.registry;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.servlet.ServletException;
import org.eclipse.gemini.blueprint.context.BundleContextAware;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.servlet.DispatcherServlet;
public class DispatcherServletRegistry implements ApplicationContextAware, BundleContextAware {
String urlPattern;
String servletName;
BundleContext bundleContext;
ApplicationContext applicationContext;
DispatcherServlet dispatcherServlet;
@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public void setServletName(String servletName) {
this.servletName = servletName;
}
public void setUrlPattern(String urlPattern) {
this.urlPattern = urlPattern;
}
public void setDispatcherServlet(DispatcherServlet dispatcherServlet) {
this.dispatcherServlet = dispatcherServlet;
}
public void init() {
ServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());
HttpService httpService = (HttpService) bundleContext.getService(serviceReference);
HttpContext commonContext = httpService.createDefaultHttpContext();
Dictionary<String, String> initparams = new Hashtable<String, String>();
initparams.put("load-on-startup", "1");
initparams.put("servlet-name", servletName);
try {
httpService.registerServlet(urlPattern, dispatcherServlet, initparams, commonContext);
}
catch (ServletException e) {
e.printStackTrace();
} catch (NamespaceException e)
{
e.printStackTrace();
}
}
}
DispatcherServletRegistry 类的实例化也是通过Spring来完成,Bean的配置如下:
<bean name="dispatcherServlet" class="org.springframework.web.servlet.DispatcherServlet">
<property name="contextConfigLocation">
<value>/META-INF/spring/*.xml</value>
</property>
</bean>
<bean name="servletRegistry" class="com.csdn.osgi.user.web.registry.DispatcherServletRegistry" init-method="init">
<property name="urlPattern" value="/*.do"></property>
<property name="servletName" value="dispatcherServlet"></property>
<property name="dispatcherServlet" ref="dispatcherServlet"></property>
</bean>
接下来在com.csdn.osgi.user.web这个Bundle中,新建META-INF/spring/registry.xml文件,用于配置注册Web资源的Bean,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:osgi="http://www.eclipse.org/gemini/blueprint/schema/blueprint"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/osgi-compendium
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://www.eclipse.org/gemini/blueprint/schema/blueprint
http://www.eclipse.org/gemini/blueprint/schema/blueprint/gemini-blueprint.xsd">
<bean name="dispatcherServlet" class="org.springframework.web.servlet.DispatcherServlet">
<property name="contextConfigLocation">
<value>/META-INF/spring/*.xml</value>
</property>
</bean>
<bean name="servletRegistry" class="com.csdn.osgi.user.web.registry.DispatcherServletRegistry" init-method="init">
<property name="urlPattern" value="/*.do"></property>
<property name="servletName" value="dispatcherServlet"></property>
<property name="dispatcherServlet" ref="dispatcherServlet"></property>
</bean>
<bean name="resourceRegistry" class="com.csdn.osgi.user.web.registry.ResourceRegistry" init-method="init">
<property name="resMapping">
<map>
<entry key="/js" value="/WebContent/js"/>
<entry key="/css" value="/WebContent/css"/>
<entry key="/images" value="/WebContent/images"/>
</map>
</property>
</bean>
<bean name="jspRegistry" class="com.csdn.osgi.user.web.registry.JspRegistry" init-method="init">
</bean>
</beans>
然后新建一个META-INF/spring/dmconfig.xml文件,用于引用其他Bundle中注册的Bean,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:osgi="http://www.eclipse.org/gemini/blueprint/schema/blueprint"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/osgi-compendium
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://www.eclipse.org/gemini/blueprint/schema/blueprint
http://www.eclipse.org/gemini/blueprint/schema/blueprint/gemini-blueprint.xsd">
<osgi:reference id="sqlMapService" interface="org.apache.ibatis.session.SqlSession" />
</beans>
然后还需要新建一个META-INF/spring/controllers.xml文件,实例化Spring MVC中的Controller及ViewResolver等,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:osgi="http://www.eclipse.org/gemini/blueprint/schema/blueprint"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/osgi-compendium
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://www.eclipse.org/gemini/blueprint/schema/blueprint
http://www.eclipse.org/gemini/blueprint/schema/blueprint/gemini-blueprint.xsd">
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean name="/test.do" class="com.csdn.osgi.web.controllers.TestController">
</bean>
</beans>
上面配置中,我们实例化了一个TestController对象,用于测试Spring MVC框架是否整合成功,TestController代码如下:
package com.csdn.osgi.web.controllers;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class TestController implements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest req,
HttpServletResponse resp) throws Exception {
System.out.println("Test Controller");
ModelAndView mv = new ModelAndView();
mv.setViewName("test");
return mv;
}
}
接下来还需要增加一个WebContent/WEB-INF/jsp/test.jsp页面,代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Spring MVC测试页面</title>
</head>
<body>
<h1>这是Spring MVC测试页面!</h1>
</body>
</html>
到此为止Spring MVC框架已经整合完毕,同时我们实例化了一个用于测试的TestController对象,整个工程结构如下图所示:
最后,启动OSGI容器,打开浏览器,访问http://localhost:8080/test.do,如下图所示:
可以发现Spring MVC已经成功整合到OSGI应用中,下篇文章,笔者带领大家基于Spring、Mybatis、Spring MVC实现一个简单的登录功能。
注意:不需要启动前面文章演示使用的com.csdn.osgi.test.web这个Bundle,否则JSP注册时指定的URL会有冲突。
本文源码地址:http://download.csdn.net/detail/rongbo_j/9753640
转载请注明原文地址:http://blog.csdn.net/Rongbo_J/article/details/55000418
OSGI企业应用开发(十四)整合Spring、Mybatis、Spring MVC的更多相关文章
- OSGI企业应用开发(四)使用Blueprint整合Spring框架(一)
上篇文章中介绍了如何使用独立的Equinox发行包搭建OSGI运行环境,而不是依赖与具体的Eclipse基础开发工具,本文开始介绍如何使用Blueprint將Spring框架整合到OSGI中. 一.开 ...
- STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- OSGI企业应用开发(十)整合Spring和Mybatis框架(三)
上篇文章中,我们已经完成了OSGI应用中Spring和Mybatis框架的整合,本文就来介绍一下,如何在其他Bundle中,使用Mybatis框架来操作数据库. 为了方便演示,我们新建一个新的Plug ...
- OSGI企业应用开发(八)整合Spring和Mybatis框架(一)
到目前为止,我们已经学习了如何使用Blueprint將Spring框架整合到OSGI应用中,并学习了Blueprint&Gemini Blueprint的一些使用细节.本篇文章开始,我们將My ...
- OSGI企业应用开发(五)使用Blueprint整合Spring框架(二)
上篇文章中,我们开发了一个自定义的Bundle,接着从网络中下载到Spring和Blueprint的Bundle,然后复制到DynamicRuntime项目下. 需要注意的是,这些Bundle并不能在 ...
- OSGI企业应用开发(九)整合Spring和Mybatis框架(二)
上篇文章中,我们完成了在OSGI应用中整合Spring和Mybatis框架的准备工作,本节我们继续Spring和Mybatis框架的整合. 一.解决OSGI整合Spring中的Placeholder问 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十四)——SpringMVC和MyBatis整合
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7010363.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十三)--S ...
- OSGI企业应用开发(十二)OSGI Web应用开发(一)
前面文章中介绍了如何在OSGI应用中整合Spring和Mybatis框架,本篇文章开始介绍如何使用OSGI技术开发Web应用.对于传统的Java EE应用,应用中涉及到的Web元素无非就是Servle ...
- OSGI企业应用开发(十三)OSGI Web应用开发(二)
上篇文章介绍了OSGI Web应用的两种开发模式,并把Jetty应用服务器以Bundle的形式整合到Equinox容器中,已这种模式开发Web应用,所有的应用程序资源,例如Servlet.JSP.HT ...
随机推荐
- Android之控件与布局,结构知识点,基础完结
版权声明:未经博主允许不得转载 在Android中我们常常用到很多UI控件,如TextView,EditText,ImageView,Button,ImageButton,ToggleButton,C ...
- [git] 本地仓库信息的查询
本地仓库信息查询操作 1.1 git status 查看当前暂存区状态 git status 显示当前分支信息: 提交的目的分支信息: git 管理的有修改的文件: 当前仓库未被 git 管理的文 ...
- 初涉Java方法
初涉Java方法 方法就是一段可重复调用的代码段,方法命名规范,第一个单词小写,从第二个单词开始首字母均大写. 格式: public static 返回值类型 ...
- linux下tar.bz2文件的 解压缩方法
一 使用bzip2解压缩命令进行解压缩: bzip2 -d gcc-4.1.0.tar.bz2 二 上面解压完之后执行下面的命令. tar -xvf gcc-4.1.0.tar 或 tar -xvf ...
- 如何开始DDD
在开始DDD之前,你需要了解DDD的一些基础知识,聚合(AggregateRoot).实体(Entity).值对象(ValueObject),工厂(Factory),仓储(Repository)和领域 ...
- mysql 开发进阶篇系列 30 数据库二进制包(安装指定路径,目录介绍)
一. 指定路径 在上一篇里,二进制包解压后,全部放入在/usr/local/mysql目录下,在安装时指定了基础目录和数据目录, --basedir=/usr/local/mysql --datadi ...
- 深入JAVA注解(Annotation):自定义注解 (转)
原文出自:http://blog.csdn.net/yjclsx/article/details/52101922 一.基础知识:元注解 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义 ...
- Netty源码分析之服务启动
本节主要分析server的启动过程. Netty是基于Nio实现的,所以也离不开selector.serverSocketChannel.socketChannel和selectKey等,只不过Net ...
- ASP.NET Core配置环境变量和启动设置
在这一部分内容中,我们来讨论ASP.NET Core中的一个新功能:环境变量和启动设置,它将开发过程中的调试和测试变的更加简单.我们只需要简单的修改配置文件,就可以实现开发.预演.生产环境的切换. A ...
- jquery中innerwidth,outerwidth,outerwidth和width的区别
在jQuery中,width()方法用于获得元素宽度: innerWidth()方法用于获得包括内边界(padding)的元素宽度, outerWidth()方法用于获得包括内边界(padding)和 ...