作为一个企业级的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. Go语言函数

    目录 函数定义 函数返回多个值 函数参数 Go 语言函数值传递 Go语言函数引用传递 函数用法 函数作为值 匿名函数 闭包 方法 不定参数的函数 init函数 内建函数 函数调用机制 总结 函数定义 ...

  2. Java匹马行天下之JavaSE核心技术——Java基础语法

    Java基础语法 一.   认识Java 1. Java 简介 java 是一种高级的面向对象的程序设计语言,使用Java语言编写的程序时跨平台的.从pc到手机,都有Java开发的程序和游戏,Java ...

  3. Http请求-get和post的区别

    GET和POST是HTTP请求的两种基本方法. 最直观的区别就是GET把参数包含在URL中,以?的方式来进行拼接,POST通过request body传递参数.并且GET请求在URL中传送的参数是有长 ...

  4. welcome-file-list修改后不生效

    用别的浏览器重新尝试一下,或者清缓存.我就是这样解决的.值得注意的就是,<welcome-file>里面指定的文件可以是.do或者是action.

  5. Java的语法糖

    1.前言 本文记录内容来自<深入理解Java虚拟机>的第十章早期(编译期)优化其中一节内容,其他的内容个人觉得暂时不需要过多关注,比如语法.词法分析,语义分析和字节码生成的过程等.主要关注 ...

  6. python 装饰方法

    def _concurrent(func): @wraps(func) # 加入这个的目的是保持原来方法的属性 def arg_wrapper(self, *args, **kwargs): try: ...

  7. 【API知识】类型转换工具ConvertUtils引发的思考

    前言 在读取Excel文件数据,有时候不可避免地需要把获取到的字符串转型为基本类型的对象.以前都是自己写转换,难度也不大.后来听说,有可以直接用的轮子——Apache 的commons-beanuti ...

  8. php使用memcached缓存总结

    1. 查询多行记录,以sql的md5值为key,缓存数组(个人觉得最好用的方法) $mem = new Memcache(); $mem->connect('127.0.0.1',11211); ...

  9. 使用centos 7安装conpot

    使用CentOS的版本7.3和Conpot 0.5.1(也可能适用于其他CentOS的版本) 1.通过ssh登录系统,并需要具有足够的系统特权(e.g root) 2.系统升级 yum -y upda ...

  10. 微信支付的JAVA SDK存在漏洞,可导致商家服务器被入侵(绕过支付)XML外部实体注入防护

    XML外部实体注入 例: InputStream is = Test01.class.getClassLoader().getResourceAsStream("evil.xml" ...