利用felix和struts2实现osgi web(二)

    OSGI(Open Service Gateway Initiative)在java世界中,提供了一种从机制上进行模块划分的理念和实践,对于java的模块化生产将会产生不可估量的推动作用。

    由于OSGI是从嵌入式开发中发展起来的,在Eclipse3.0以后的Equinox实现了OSGI的标准后,OSGI开发模式在java世界中开始流行起来。但是对于企业级的应用,特别是多层的企业级应用,现在流行的OSGi实现Equinox、Felix都提供了实现的方式,在Application Server中嵌入OSGI的运行环境,从而实现Server端的OSGI。在OSGI框架中,推荐的方式是利用应用服务器的OSGI实现,在统一的OSGI模式下,进行WEB应用的部署,但是,任何的技术应用都不是孤立存在和从零开始的,大量的传统应用的融合和继承,注定了第一种模式的生命力。

    文章《使用 Felix 和 Struts2 开发 Web 应用》中详细的介绍了利用Felix框架,开发Struts2应用的过程,美中不足的是,原文没有提供真正的实现工程,在依照这一过程实现中,出现了很多意想不到的情况。

   下面把我实现一个完整的应用的过程进行梳理:

   1、建立接口插件工程:利用Eclipse的标准过程进行,只是在生成工程的过程中,选用OSGI的Standard模式,填入工程名为:com.example.time,在其中生成一个将来用于交互的接口。

 利用felix和struts2实现osgi web(二)

 

  发布出来的接口的代码如下,只是一个示例性的例子,获得一个时间字符串。

package com.example.time.service;

public interface TimeService{
 public String getTime();
 }

 在MANIFEST.MF文件中,把包com.example.time.service发布出去,供其他插件应用。

2、生成提供local和utc时间服务的插件。

    时间服务提供插件生成插件的过程和生成接口插件过程相同,插件分别命名为com.example.time.local和com.example.time.utc,在其中实现的过程如下:

    2.1 插件向外提供服务的方式

         OSGI的插件有两种向外部提供服务的方式,一是通过导出包,如上面的接口插件工程,就是导出了一个包。二是通过提供服务的方式,在插件中发布出提供的服务,供其它插件消费。在OSGI中,第二种方式是被鼓励应用的,因为这样对于实现系统热插拔具有很大的帮助。在本实验中,时间服务就是利用第二种方式提供的。

    2.2 com.example.time.local

         在插件中导入com.example.time.service包,然后TimeService的代码如下:

package com.example.time.local.service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import com.example.time.service.TimeService;

public class LocalTimeService implements TimeService {
	@Override
	public String getTime() {
		Calendar calendar = Calendar.getInstance();
		Date date = calendar.getTime();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return "The local time:" + formatter.format(date);
	}
}

 

获得了本地的时间,并转换为String的格式,向外提供。

在插件中,发布服务的方式有多种,可以再代码中发布,也可以通过声明发布,还可以通过springdm管理发布,由于本例中非常简单,就选有了,利用代码发布的方式,在activator的Start方法中,发布服务:

	public void start(BundleContext context) throws Exception {
	    context.registerService(TimeService.class.getName(), new LocalTimeService(), null);
	}

 

2.3 com.example.time.utc

     utc服务发布插件的实现过程和local服务发布的插件实现过程相同,utc时间的服务类为:

package com.example.time.utc.service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import com.example.time.service.TimeService;

public class UTCTimeService implements TimeService {
	@Override
	public String getTime() {
		Calendar calendar = Calendar.getInstance();
		int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
		int dstOffset = calendar.get(Calendar.DST_OFFSET);
		calendar.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
		Date date = calendar.getTime();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm s");
		return "The UTC time:" + formatter.format(date);
	}
}

 

3、web bundle

    通过上面的三个bundle,实现了对于local和utc时间服务的发布,下面就要在web bundle中,对上面服务的服务进行应用了,为了在web bundle中支持struts2,需要在web bundle的MANIFEST.MF文件中,进行以下的设置:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Web
Bundle-SymbolicName: com.example.time.web
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: EXAMPLE
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Private-Package: time,.
Struts2-Enabled: true 
Import-Package: com.example.time.service,
 com.opensymphony.xwork2,
 org.apache.struts2.osgi.interceptor,
 org.osgi.framework;version="1.3.0"
Export-Package: com.example.time.web.action

 其中Struts2-Enable设置为true,Private-Package设置web中页面的放置位置。

在bundle中,实现一个Action,从ActionSupport继承,实现BundleContextAware接口。BunndleContextAware中定义了一个函数:setBundleContext,在其中Action可以获得bundle的Context,从而访问其他bundle服务出来的服务:

package com.example.time.web.action;

import org.apache.struts2.osgi.interceptor.BundleContextAware;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import com.example.time.service.TimeService;
import com.opensymphony.xwork2.ActionSupport;


public class TimeAction extends ActionSupport implements BundleContextAware{


	private String jsonText = "json text";
	private BundleContext bundleContext;
	private String timeMessage;

	 public String execute(){
			ServiceReference ref = bundleContext.getServiceReference(
		    	    TimeService.class.getName());
		    	    TimeService timeService = (TimeService) bundleContext.getService(ref);
		    	    timeMessage = timeService.getTime();
		    	    return SUCCESS;

				 }
	public String getJsonText() {
		return jsonText;
	}
	public void setJsonText(String jsonText) {
		this.jsonText = jsonText;
	}

	public String getTimeMessage() {
		return timeMessage;
	}
	public void setTimeMessage(String timeMessage) {
		this.timeMessage = timeMessage;
	}
	public void setBundleContext(BundleContext arg0) {
		// TODO Auto-generated method stub
		this.bundleContext = arg0;
	}

}

  为了应用ActionSupport和BundleContextAware,需要导入相应的包,在Eclipse默认的OSGi环境中,是没有plugin提供这两个包的,需要在OSGi的Target Platform中,设置这些bundle。

   在Target Platform中加入OSGI需要的包,在windows->Preferrences出现对话框,选择Plugin development中的Target Platform,默认情况下只有${eclipse-home}目录,为了应用struts2,在其中加入Struts2的lib目录,则Struts2自带的bundle就可以在工程中应用了。利用felix和struts2实现osgi web(二)

 

在time目录下定义freemarker文件time.ftl:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
		<title>Untitled Document</title>
	</head>
	<body>
			<h1> Hello world,Bundle test.${timeMessage}</h1>
	</body>
</html>

 最后进行struts文件的定义:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "file:D:/software/struts-2.2.1/src/core/src/main/resources/struts-2.0.dtd">

 <struts>


    <package name="time-example" namespace="/time" extends="osgi-default">
        <action name="time" class="com.example.time.web.action.TimeAction">
            <result type = "freemarker">/time/time.ftl</result>
        </action>
    </package>

 </struts>



 就完成web bundle了。

你可能感兴趣的:(Web,应用服务器,struts,企业应用,osgi)