最近公司将部分应用迁移到osgi的平台上,我最近也学习了和实践了一下osgi。关于osgi的资料网上并不多,推荐看看《osgi.component.programming.ppt》和 《osgi实践》。
Osgi给我感觉最大优点:模块化~,动态性~,低耦合~。
最近根据《osgi实践》一书,实践了一个web请求的简单应用。osgi在申明服务的时候有两种方式,第一种通过BundleContext的方式注册,第二种通过ds的方式注册。第一种方式根据书中的步骤很容易的实现了,第二种方式书中介绍简略,而且我实践时候出现了ds无法注入服务的问题,不过某一早上灵感一显就搞定了~。我下面把这个简单的工程过程公布出来~我只是想给第一次弄osgi的人一个坚定的信念~,这个东西实现起来很简单~~。
下面就是建立这个工程的全过程。
环境:eclipse Version: 3.3.2 自然用的是Equinox(org.eclipse.osgi)。
还需要javax.servlet,org.eclipse.equinox.ds,org.eclipse.equinox.http,org.eclipse.osgi.services将这些包(网上搜索下载),放入eclipse的plugins文件下面。
1.> 建立工程如图1所示
选择plug-in Project 进入下一步
点击下一步
点击finish,这样我们就建立好了一个插件工程。
2.> 下面我按照上面步骤建立三个插件工程 分别是UserValidatorBundleTwo ,ConfigFileValidatorBundleTwo,UserValidatorWebBundleTwo。
其中UserValidatorBundleTwo工程只是定义一个验证用户名和密码的接口。ConfigFileValidatorBundleTwo才是这个接口真实的实现,所以在后面可以看到他提供了一个配置文件来申明他提供的服务。
UserValidatorWebBundleTwo 是一个提供web服务的工程,它需要依赖两个服务~~,在后面就的配置文件就可以看到了。
1. 首先看UserValidatorBundleTwo这个工程,我们需要建立一个接口
- package com.infotech.uservalidatorbundletwo;
- public interface IValidator {
- public boolean validate(String username, String password) throws Exception;
- }
我们需要将接口提供给别的组件使用,我们需要修改MANIFEST.MF文件
- Manifest-Version: 1.0
- Bundle-ManifestVersion: 2
- Bundle-Name: UserValidatorBundleTwo Plug-in
- Bundle-SymbolicName: UserValidatorBundleTwo
- Bundle-Version: 1.0.0
- Bundle-ClassPath: bin/
- Bundle-Activator: com.infotech.uservalidatorbundletwo.Activator
- Bundle-Vendor: com.infotech
- Import-Package: org.osgi.framework;version="1.3.0",
- org.osgi.service.startlevel;version="1.0.0"
- Export-Package: com.infotech.uservalidatorbundletwo
2. 接着我们修改ConfigFileValidatorBundleTwo工程
首先我们需要引入IValidator这个接口,修改MANIFEST.MF并保存
,如下
- Manifest-Version: 1.0
- Bundle-ManifestVersion: 2
- Bundle-Name: ConfigFileValidatorBundleTwo Plug-in
- Bundle-SymbolicName: ConfigFileValidatorBundleTwo
- Bundle-Version: 1.0.0
- Bundle-ClassPath: bin/
- Bundle-Vendor: com.Infotech
- Service-Component: OSGI-INF/component.xml
- Import-Package: com.infotech.uservalidatorbundletwo,
- org.osgi.framework;version="1.3.0"
注:其中Bundle-Activator这个属性可以要,也可以不要。
在看看实现接口的类ConfigFileValidatorImpl
- package com.infotech.configbundletwo;
- import com.infotech.uservalidatorbundletwo.IValidator;
- public class ConfigFileValidatorImpl implements IValidator{
-
- public ConfigFileValidatorImpl() {
- System.out.println("start ConfigFileValidatorImpl");
- }
- public boolean validate(String username, String password) throws Exception {
- if("MagicLiu".equals(username) && "iloveyou".equals(password))
- return true;
- return false;
- }
- }
同时在工程下面建立OSGI-INF文件夹,并建立component.xml提供给ConfigFileValidatorBundleTwo申明服务,它的具体内容是:
- <?xml version="1.0" encoding="UTF-8"?>
- <component name="ConfigFileValidatorBundleTwo">
- <implementation class="com.infotech.configbundletwo.ConfigFileValidatorImpl"/>
- <service>
- <provide interface="com.infotech.uservalidatorbundletwo.IValidator"/>
- </service>
- </component>
3. 好了修改最后一个UserValidatorWebBundleTwo这个工程了
首先要建立一个Servlet来处理web请求,这个时候我们需要两个服务,一个是http服务,一个是验证用户名和密码的服务,用ds注入的话需要对每一个服务有set和unset方法,接着就是doGet和doPost方法,具体代码如下:
- package com.infotech.web.servlet;
- import java.io.IOException;
- import javax.servlet.Servlet;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.osgi.service.http.HttpService;
- import com.infotech.uservalidatorbundletwo.IValidator;
- public class LoginServlet extends HttpServlet{
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private HttpService http;
- private IValidator validator;
-
- public LoginServlet(){
- System.out.println("Start Servlet!");
- }
-
- public void setIValidator(IValidator validator) {
- System.out.println("set Validator");
- this.validator = validator;
- }
-
- public void unsetIValidator(IValidator validator) {
- if(this.validator != validator) {
- return ;
- }
- this.validator = null;
- }
-
- public void setHttpService(HttpService httpService) {
- this.http = httpService;
- try {
- http.registerServlet("/demo/login", (Servlet) this, null, null);
- http.registerResources("/demo/page", "pages", null);
- System.out.println("已启动用户登录验证web模块,请通过/demo/page/login.htm访问");
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- public void unsetHttpService(HttpService httpService) {
- this.http.unregister("/demo/login");
- this.http.unregister("/demo/page");
- System.out.println("已卸载用户登录验证web模块!");
- this.http = null;
- }
-
- public void doPost(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- doGet(request, response);
- }
-
- public void doGet(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- String username = request.getParameter("username");
- String userpass = request.getParameter("userpass");
- response.setContentType("text/html");
- ServletOutputStream output = response.getOutputStream();
-
- if(this.validator == null ) {
- output.println("No usable validator service");
- output.close();
- return;
- }
- boolean result = false;
- try{
- result = this.validator.validate(username, userpass);
- if(result)
- output.println("Login success");
-
- else
- output.println("Login Fail, please check username and password");
-
- output.close();
- return ;
- }catch(Exception e) {
- output.println("Login error:");
- output.println(e.toString());
- output.close();
- return;
- }
- }
- }
我们需要建立一个页面请求,在这个工程下面建立一个Pages的文件夹,同时建立Login.htm
页面代码如下:
- <BODY>
- <table style="width:45%;border:1px solid;height:100px">
- <form name=frmLogin method="post" action="/demo/login">
- <tr bgcolor="#C0C0C0">
- <td colspan="2" align="center">用户登录模块示例</td>
- </tr>
- <tr>
- <td width="30%">用户名</td>
- <td><input type="text" name="username" size="30"></td>
- </tr>
- <tr>
- <td>密 码</td>
- <td><input type="password" name="userpass" size="33"></td>
- </tr>
- <tr bgcolor="#C0C0C0">
- <td colspan="2" align="center">
- <input type=button name=btnSubmit value="登录" οnclick="login();">
- </td>
- </tr>
- </form>
- </table>
- </BODY>
我们需要修改配置文件了
- Manifest-Version: 1.0
- Bundle-ManifestVersion: 2
- Bundle-Name: UserValidatorWebBundleTwo Plug-in
- Bundle-SymbolicName: UserValidatorWebBundleTwo
- Bundle-Version: 1.0.0
- Bundle-ClassPath: bin/
- Bundle-Vendor: com.infotech
- Import-Package: com.infotech.uservalidatorbundletwo,
- org.osgi.framework;version="1.3.0",
- org.osgi.service.http;version="1.2.0"
- Require-Bundle: javax.servlet
- Service-Component: OSGI-INF/ component.xml
接着再配置component.xml,在工程下面建立OSGI-INF文件夹和文件component.xml
文件修改如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <component name="LoginServlet">
- <implementation class="com.infotech.web.servlet.LoginServlet"/>
- <reference name="IValidator" interface="com.infotech.uservalidatorbundletwo.IValidator"
- bind="setIValidator" unbind="unsetIValidator" policy="dynamic"/>
- <reference name="HttpService" interface="org.osgi.service.http.HttpService"
- bind="setHttpService" unbind="unsetHttpService" policy="dynamic"/>
- </component>
3.> 我们工程基本上都建立完全了,现在需要的是配置系统环境拉
选择debug下面open debug dialog~~如图:
选择osgi Framework 点击右键 选择new,让后在bundles视图中勾选上你选择的三个Bundler ,同时点击add Required bundles 按钮,系统会帮你添加必要的bundle~好了点击“Apply”保存,点击debug按钮。系统运行了出现下面的图
同时输入ss 可以出现以下的bungles.
5.> 后台运行正常 让我们用访问这个web地址
我修改了web服务的端口,大家访问的时候直接可以直接用80端口
终于搞完了~~嘿嘿~~