OSGI Enterprise Application Development (XIV) Integrating Spring, Mybatis and Spring MVC

Keywords: Attribute Spring Eclipse JSP

As an enterprise-level Web application, MVC framework is essential. Spring MVC is widely used at present. This article will introduce how to integrate Spring, Mybatis and Spring MVC framework in OSGI applications. The integration of Spring MVC is difficult because each Bundle has an isolated Application Context after Spring is integrated into OSGI. That is to say, there exists dependency injection among beans instantiated in different Bundles. As mentioned in the previous article, this problem can be solved through the Bean registration and reference mechanism.

When instantiating the class of org.spring framework.web.servlet.Dispatcher Servlet in Spring MVC framework, we need to specify the configuration file of beans. When the Spring MVC framework starts, we instantiate the beans in the configuration file (such as Controller instance). The beans instantiated after the Spring MVC framework starts are different class loaders from those instantiated in Bundle, so there are no instantiated beans in Bundle. The direct example is that SqlSession instance of Mybatis operation database can not be injected into Controller of Spring MVC. Virgo is the most popular solution on the Internet. After some research, the author solved the integration of Spring MVC framework and OSGI application. If we find any problems, we can discuss ^uuuuuuuuuuuuuuu

Next, we introduce the integration of Spring, Mybatis and Spring MVC frameworks in OSGI applications. We still use the workspace already built in the previous article.

First, create a new Bundle named com.csdn.osgi.user.web. The whole workspace structure is shown in the following figure:

Since resources and servlets in OSGI applications need to be registered before they can be accessed by the client, we can write several classes specifically for registering Web resources.

First is the registration of static resources such as images, CSS and JS. A new class named com.csdn.osgi.user.web.registry.ResourceRegistry is created in the Bundle of com.csdn.osgi.user.web. The code is as follows:

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();
        }
    }
}

We can instantiate this class through Spring. Bean s are configured as follows:

    <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>

In this way, the registration of static resources can be completed, which is more flexible. If there is a new type of resources, you only need to add a new entry tag to the map tag.

Next is the registration of JSP. We create a new class named com.csdn.osgi.user.web.registry.JspRegistry in the Bundle com.csdn.osgi.user.web. The code is as follows:

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();
        }
    }
}

Similarly, JspRegistry is instantiated in Spring, and Bean is configured as follows:

<bean name="jspRegistry" class="com.csdn.osgi.user.web.registry.JspRegistry" init-method="init">
</bean>

Finally, the registration of Servlet resources. Using Spring MVC framework, we need to instantiate a Dispatcher Servlet object. It should be noted that the Dispatcher Servlet object can not be created by new keywords. It should be instantiated by Spring framework. A new class named com.csdn.osgi.user.web.registry.Dispatcher Servlet Register is created in the Bundle of com.csdn.osgi.user.web. Try, the code is as follows:

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();
        }
    }
}

The instantiation of the Dispatcher ServletRegistry class is also accomplished through Spring. The configuration of the Bean is as follows:

    <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>

Next, in the Bundle com.csdn.osgi.user.web, a new META-INF/spring/registry.xml file is created to configure the beans registered for Web resources, which is as follows:

<?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>

Then a new META-INF/spring/dmconfig.xml file is created to refer to beans registered in other Bundle s, as follows:

<?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>

Then you need to create a META-INF/spring/controllers.xml file to instantiate the Controller and ViewResolver in Spring MVC. The configuration is as follows:

<?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>

In the above configuration, we instantiated a TestController object to test whether the Spring MVC framework was successfully integrated. The TestController code is as follows:

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;
    }

}

Next, you need to add a WebContent/WEB-INF/jsp/test.jsp page with the following code:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Spring MVC Test page</title>
</head>
<body>
<h1>This is Spring MVC Test page!</h1>
</body>
</html>

So far, the Spring MVC framework has been integrated, and we instantiated a TestController object for testing. The whole engineering structure is shown in the following figure:

Finally, start the OSGI container, open the browser, access http://localhost:8080/test.do As shown in the following figure:

It can be found that Spring MVC has been successfully integrated into OSGI applications. In the next article, I will lead you to implement a simple login function based on Spring, Mybatis and Spring MVC.

For reproducing, please indicate the original address: http://blog.csdn.net/Rongbo_J/article/details/55000418

Posted by kathas on Sat, 05 Jan 2019 19:27:10 -0800