zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    使用express+multer实现node中的图片上传
    利用H5构建地图和获取定位地点
    移动端开发基础 干货分享
    关于angularJS的一些用法
    你好 JSONP !!!!
    CentOS7使用Alien将RPM从DE转换为DEB和DEB转换为RPM包
    [Windows] visio2019破解激活
    python---九九乘法表代码
    HTTP 请求方式: GET和POST的比较
    win10WLAN没有有效的ip配置
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468136.html
Copyright © 2011-2022 走看看