作为一个企业级的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的更多相关文章

  1. OSGI企业应用开发(四)使用Blueprint整合Spring框架(一)

    上篇文章中介绍了如何使用独立的Equinox发行包搭建OSGI运行环境,而不是依赖与具体的Eclipse基础开发工具,本文开始介绍如何使用Blueprint將Spring框架整合到OSGI中. 一.开 ...

  2. STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  3. OSGI企业应用开发(十)整合Spring和Mybatis框架(三)

    上篇文章中,我们已经完成了OSGI应用中Spring和Mybatis框架的整合,本文就来介绍一下,如何在其他Bundle中,使用Mybatis框架来操作数据库. 为了方便演示,我们新建一个新的Plug ...

  4. OSGI企业应用开发(八)整合Spring和Mybatis框架(一)

    到目前为止,我们已经学习了如何使用Blueprint將Spring框架整合到OSGI应用中,并学习了Blueprint&Gemini Blueprint的一些使用细节.本篇文章开始,我们將My ...

  5. OSGI企业应用开发(五)使用Blueprint整合Spring框架(二)

    上篇文章中,我们开发了一个自定义的Bundle,接着从网络中下载到Spring和Blueprint的Bundle,然后复制到DynamicRuntime项目下. 需要注意的是,这些Bundle并不能在 ...

  6. OSGI企业应用开发(九)整合Spring和Mybatis框架(二)

    上篇文章中,我们完成了在OSGI应用中整合Spring和Mybatis框架的准备工作,本节我们继续Spring和Mybatis框架的整合. 一.解决OSGI整合Spring中的Placeholder问 ...

  7. Spring+SpringMVC+MyBatis深入学习及搭建(十四)——SpringMVC和MyBatis整合

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7010363.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十三)--S ...

  8. OSGI企业应用开发(十二)OSGI Web应用开发(一)

    前面文章中介绍了如何在OSGI应用中整合Spring和Mybatis框架,本篇文章开始介绍如何使用OSGI技术开发Web应用.对于传统的Java EE应用,应用中涉及到的Web元素无非就是Servle ...

  9. OSGI企业应用开发(十三)OSGI Web应用开发(二)

    上篇文章介绍了OSGI Web应用的两种开发模式,并把Jetty应用服务器以Bundle的形式整合到Equinox容器中,已这种模式开发Web应用,所有的应用程序资源,例如Servlet.JSP.HT ...

随机推荐

  1. java之vector详细介绍

    1 vector介绍 Vector简介 Vector 是矢量队列,它是JDK1.0版本添加的类.继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口 ...

  2. Python基础入门教程(3)

    人生苦短,我学Pyhton Python(英语发音:/ˈpaɪθən/), 是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于199 ...

  3. MarkDown基础语法记录

    基础语法记录,其中有一些博客园暂不支持 <!--标题--> # 一级标题 # ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 一级标题 ...

  4. Liferay平台开发使用详细PPT演示文稿

    主要章节: 概述 功能和使用 开发扩展 安全.认证 高可用 Demo 独立流程演示工程: Liferay集成Activiti开发工程: PPT演示文稿下载 Demo程序分2部分: 独立流程演示工程:h ...

  5. [EXP]Adobe ColdFusion 2018 - Arbitrary File Upload

    # Exploit Title: Unrestricted # Google Dork: ext:cfm # Date: -- # Exploit Author: Pete Freitag of Fo ...

  6. vertical-align_CSS参考手册_web前端开发参考手册系列

    该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐.允许指定负长度值和百分比值.这会使元素降低而不是升高.在表单元格中,这个属性会设置单元格框中的单元格内容的对齐方式. <!DOCTYP ...

  7. Linux编程 4 (创建文件touch,复制文件cp,tab补全,链接文件ln)

    一.创建文件 使用touch 可以创建空文件,例如opt目录下创建test2.txt文件.这种一般是有些程序必须要先创建文件,才能使用. 二. 复制文件 2.1 使用cp命令来复制文件,需要两个参数- ...

  8. 常用的.NET开源项目(转)

    Json.NET http://json.codeplex.com/ Json.Net是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Lin ...

  9. Android生成二维码--保存和分享二维码图片

    之前写过生成自定义二维码的两篇文章:<Android生成自定义二维码><Android生成二维码–拍照或从相册选取图片>,下面就介绍一下Android应用内如何保存以及分享二维 ...

  10. CentOS 6.5的安装详解(图文详解)

    不多说,直接上干货! 主流: 目前的Linux操作系统主要应用于生产环境, 主流企业级Linux系统仍旧是RedHat或者CentOS. 免费: RedHat 和CentOS差别不大,CentOS是一 ...