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 ...
随机推荐
- Go语言函数
目录 函数定义 函数返回多个值 函数参数 Go 语言函数值传递 Go语言函数引用传递 函数用法 函数作为值 匿名函数 闭包 方法 不定参数的函数 init函数 内建函数 函数调用机制 总结 函数定义 ...
- Java匹马行天下之JavaSE核心技术——Java基础语法
Java基础语法 一. 认识Java 1. Java 简介 java 是一种高级的面向对象的程序设计语言,使用Java语言编写的程序时跨平台的.从pc到手机,都有Java开发的程序和游戏,Java ...
- Http请求-get和post的区别
GET和POST是HTTP请求的两种基本方法. 最直观的区别就是GET把参数包含在URL中,以?的方式来进行拼接,POST通过request body传递参数.并且GET请求在URL中传送的参数是有长 ...
- welcome-file-list修改后不生效
用别的浏览器重新尝试一下,或者清缓存.我就是这样解决的.值得注意的就是,<welcome-file>里面指定的文件可以是.do或者是action.
- Java的语法糖
1.前言 本文记录内容来自<深入理解Java虚拟机>的第十章早期(编译期)优化其中一节内容,其他的内容个人觉得暂时不需要过多关注,比如语法.词法分析,语义分析和字节码生成的过程等.主要关注 ...
- python 装饰方法
def _concurrent(func): @wraps(func) # 加入这个的目的是保持原来方法的属性 def arg_wrapper(self, *args, **kwargs): try: ...
- 【API知识】类型转换工具ConvertUtils引发的思考
前言 在读取Excel文件数据,有时候不可避免地需要把获取到的字符串转型为基本类型的对象.以前都是自己写转换,难度也不大.后来听说,有可以直接用的轮子——Apache 的commons-beanuti ...
- php使用memcached缓存总结
1. 查询多行记录,以sql的md5值为key,缓存数组(个人觉得最好用的方法) $mem = new Memcache(); $mem->connect('127.0.0.1',11211); ...
- 使用centos 7安装conpot
使用CentOS的版本7.3和Conpot 0.5.1(也可能适用于其他CentOS的版本) 1.通过ssh登录系统,并需要具有足够的系统特权(e.g root) 2.系统升级 yum -y upda ...
- 微信支付的JAVA SDK存在漏洞,可导致商家服务器被入侵(绕过支付)XML外部实体注入防护
XML外部实体注入 例: InputStream is = Test01.class.getClassLoader().getResourceAsStream("evil.xml" ...