作为一个企业级的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. MySQL-Cluster 和主从(Master,Slave)搭建总结

    双主互备,主从 什么是双主 MultiSource 多源复制 原理及流程图 主要步骤 1,在 Master Server 上开启 bin log 日志 和 设置 server-id  :(在my.cn ...

  2. Iptables-redhat/centos

    6用iptables 7默认用firewalld firewalld 与 iptables 过滤点,表 做nat是使用postrouting,prerouting表 Samba服务所使用的端口和协议: ...

  3. callback vs async.js vs promise vs async / await

    需求: A.依次读取 A|B|C 三个文件,如果有失败,则立即终止. B.同时读取 A|B|C 三个文件,如果有失败,则立即终止. 一.callback 需求A: let read = functio ...

  4. vue 自学笔记(七) 组件细节问题

    前情提要: 这里盘点一下,组件细节的问题 现在我们观察一些用框架开发的网页BiliBili.掘金,会发现很多部分都十分相似或者一模一样,我们甚至可以将其拆分归类.而事实上,页面的确是被一个个组件构成的 ...

  5. LeetCode:105_Construct Binary Tree from Preorder and Inorder Traversal | 根据前序和中序遍历构建二叉树 | Medium

    要求:通过二叉树的前序和中序遍历序列构建一颗二叉树 代码如下: struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode ...

  6. Mobility Model and Routing Model about the ONE

    ONE主要的功能是节点的移动,节点间的相遇情况,路由情况以及消息的处理机制.下面简要介绍下目前ONE自带的六种移动模型和六种路由模型. Mobility Model: 从大的方面,可以分为三种,1)随 ...

  7. iOS-Xcode解决【workspace integrity couldn't load project'】

    出现如标题提示的项目打不开情况,多半可能是因为Xcode版本不同,或者是SVN/Git使用导致 解决办法一: 删除冲突代码,"项目文件->Pod文件夹->Pods.xcodepr ...

  8. SqlServer 更改数据库名称

    1.首先选中需要更改数据库右击属性找到文件, 此处可直接修改数据库逻辑名称 2.选中数据库右击选择重命名修改数据库名称. 3.将数据库进行分离,找到数据库文件mdf与ldf文件,直接更改文件名称 4. ...

  9. 图形数据库Neo4j基本了解

    在深入学习图形数据库之前,首先理解属性图的基本概念.一个属性图是由顶点(Vertex),边(Edge),标签(Lable),关系类型和属性(Property)组成的有向图.顶点也称作节点(Node), ...

  10. RC1015 cannot open include file 'atlres.h'

    fatal error RC1015: cannot open include file 'atlres.h' 问题:此问题是由于rc文件没有找到 atlres.h导致的 (原因不详) 解决:工程   ...