上篇文章介绍了OSGI Web应用的两种开发模式,并把Jetty应用服务器以Bundle的形式整合到Equinox容器中,已这种模式开发Web应用,所有的应用程序资源,例如Servlet、JSP、HTML页面等,都需要使用OSGI规范提供的HttpService服务进行注册,否则无法通过浏览器请求服务器端资源。

一、HttpService服务详解

接着我们就来了解一些HttpService服务,它实际上就是一个接口,具体的服务类由OSGI框架(例如Felix、Equinox等)实现,HttpService接口的定义如下:

org.osgi.service.http.HttpService

package org.osgi.service.http;

import java.util.Dictionary;
import javax.servlet.Servlet;
import javax.servlet.ServletException; public interface HttpService { public void registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext context) throws ServletException, NamespaceException; public void registerResources(String alias, String name, HttpContext context) throws NamespaceException; public void unregister(String alias); public HttpContext createDefaultHttpContext();
}

如上面代码所示,HttpService接口仅有4个方法,而且这些方法在实际开发中使用非常广泛,所以我们必须清楚的知道每个方法的作用,以及每个参数的含义。

registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext context)

传统Java EE应用中Servlet只需要在web.xml文件中配置即可,但是使用將应用服务器整合到OSGI容器这种模式开发Web应用,Servlet实例必须被注册后才能被客户端访问。

HttpService接口的registerServlet()方法就是用于注册Servlet,参数含义如下:

第一个参数alias用于指定请求Servlet的URL模式,例如参数值为/login.do时,我们可以在浏览器中以http://localhost:8080/login.do的形式请求该Servlet,除此之外该参数还支持使用通配符,如/*.do,表示任意以.do结尾的请求都会被该Servlet处理。

第二个参数是一个Servlet实例,通常我们通过new关键字实例化一个Servlet对象即可。

大家在传统Java EE项目web.xml配置Servlet时,可以指定一些初始化参数,第三个参数作用就是为Servlet指定初始化参数。

第四个参数是一个HttpContext实例,他表示Http请求上下文,可以通过createDefaultHttpContext()方法创建一个默认的HttpContext实例,也可以將该参数指定为null。

registerResources(String alias, String name, HttpContext context)

该方法的作用和registerServlet()方法类似,只不过它用于注册静态的资源,例如CSS、图片、JavaScript文件等,使用方法也很简单,参数含义如下:

前面两个参数要结合起来使用,第一个参数表示客户端请求资源的URL模式,第二个参数表示资源映射在Bundle中的位置。

例如alias参数内容为”/js”,name参数值为”/WebContent/js”时,当客户端请求的URL为http://localhost:8080/js/index.js时,会返回Bundle中WebContent/js/index.js文件。

第三个参数和registerServlet()方法一样,不在赘述。

unregister()方法就比较简单了,当资源不需要被客户端请求时,可以调用该方法卸载资源;createDefaultHttpContext()方法用于创建默认的HttpContext实例。

二、Web应用开发实战

前面介绍了一些HttpService的理论基础,这对我们后面整合Spring MVC框架非常重要,接下来就介绍一下实际项目中何如使用HttpService的。

我们在前面文章中搭建的环境基础上进行演示,首先新建一个新的Plug-in Project,名称为com.csdn.osgi.test.web,完成后整个项目结构如下图所示:



需要注意的是,在新建com.csdn.osgi.test.web工程选择模版时,选择Hello OSGI Bundle,这样Eclipse会为我们生成一个Activator类,我们可以在该类中完成资源的注册操作,当然并不一定要使用工具生成,读者也可以自己注册一个Bundle生命周期类。

接下来我们就来新建一个Servlet,由于是演示用的,名称就叫TestServlet,代码如下:

com.csdn.osgi.web.servlet.TestServlet

import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{ @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { PrintWriter writer = resp.getWriter();
writer.println("Hello OSGI Web Appication!");
} @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
}

如上面代码所示,我们重写了HttpServlet的doPost()和doGet()方法,在doPost()方法中,向客户端返回一段简单的文本信息,接下来还需要注册该Servlet。

修改Eclipse为com.csdn.osgi.test.web工程生成的Activator类,增加如下内容:

package com.csdn.osgi.test.web;

import java.util.Dictionary;
import java.util.Hashtable; import javax.servlet.Servlet; import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService; import com.csdn.osgi.web.servlet.TestServlet; public class Activator implements BundleActivator { public void start(BundleContext bundleContext) throws Exception { ServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());
HttpService service = (HttpService) bundleContext.getService(serviceReference); // 注册Servlet
Servlet testServlet = new TestServlet();
Dictionary<String, String> initparams = new Hashtable<String, String>();
initparams.put("load-on-startup", "1");
initparams.put("servlet-name", "testServlet"); service.registerServlet("/testServlet.do", testServlet, initparams, null); } public void stop(BundleContext bundleContext) throws Exception {
System.out.println("Goodbye World!!");
} }

我们首先通过下面两行代码获取HttpService实例,如下:

ServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());
HttpService service = (HttpService) bundleContext.getService(serviceReference);

接着new了一个TestServlet实例,然后调用HttpService实例的registerServlet()方法注册testServlet对象,请求的URL为/testServlet.do。

接下来我们可以重新启动OSGI容器,然后打开浏览器访问http://localhost:8080/testServlet.do,如下图所示,会发现浏览器中显示Servlet返回的文本内容:

接下来我们再来了解一下JSP的注册,首先在com.csdn.osgi.test.web工程中新建一个WebContent/jsp目录,然后在该目录中新建一个test.jsp文件,内容如下:

<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<title>首页面</title>
</head>
<body>
<h1>这是首页面!</h1>
</body>
</html>

在这种情况下,客户端是没办法访问到JSP页面的,Jetty服务器也不会把test.jsp文件作为JSP解析,这就需要我们对JSP进行注册,將客户端请求的URL映射到Bundle中的JSP文件。

我们依然在Activator 类的start()方法中对JSP进行注册,代码如下:

package com.csdn.osgi.test.web;

import java.util.Dictionary;
import java.util.Hashtable; import javax.servlet.Servlet; import org.eclipse.equinox.jsp.jasper.JspServlet;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService; import com.csdn.osgi.web.servlet.TestServlet; public class Activator implements BundleActivator { public void start(BundleContext bundleContext) throws Exception { ServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());
HttpService service = (HttpService) bundleContext.getService(serviceReference); // 注册Servlet
Servlet testServlet = new TestServlet();
Dictionary<String, String> initparams = new Hashtable<String, String>();
initparams.put("load-on-startup", "1");
initparams.put("servlet-name", "testServlet"); service.registerServlet("/testServlet.do", testServlet, initparams, null); Dictionary jspParams = new Hashtable<String, String>();
JspServlet jspServlet = new JspServlet(bundleContext.getBundle(), "/WebContent/jsp", "/jsp");
service.registerServlet("/jsp", jspServlet, jspParams, null);
} public void stop(BundleContext bundleContext) throws Exception {
System.out.println("Goodbye World!!");
} }

其中下面几行代码为新增:

Dictionary jspParams = new Hashtable<String, String>();
JspServlet jspServlet = new JspServlet(bundleContext.getBundle(), "/WebContent/jsp", "/jsp");
service.registerServlet("/jsp", jspServlet, jspParams, null);

注册JSP需要使用JspServlet类,该类的构造方法有三个参数,第一个参数为bundle实例,后面两个参数需要配合起来使用,第二个参数为请求URL映射到Bundle中JSP文件的路径,第三个参数为请求的URL模式,上面代码中创建的JspServlet实例的含义为:

將请求URL中的/jsp/*.jsp映射到Bundle中/WebConten/jsp目录下对应的JSP文件,例如请求URL为http://localhost:8080/jsp/test.jsp时,则返回Bundle中/WebConten/jsp/test.jsp文件内容。

注意:需要將org.eclipse.equinox.jsp.jasper这个Bundle添加到运行环境中。

接下来我们可以重新启动OSGI容器,然后打开浏览器访问http://localhost:8080/jsp/test.jsp,如下图所示,可以发现页面中显示对应JSP文件的内容:

最后就是图片资源的注册,也很简单,以图片资源为例,注册代码如下:

service.registerResources("/img", "/WebContent/img", null);

重新启动OSGI容器,在/WebContent/img目录下放一张test.png图片,浏览器中访问http://localhost:8080/img/test.png,如下图所示:

再来看一下com.csdn.osgi.test.web工程的项目结构,如下图所示:

到此为止,OSGI Web应用开发的内容就介绍的差不多了,下篇文章开始介绍在Web应用中整合Spring MVC框架,尽请期待!

OSGI企业应用开发(十三)OSGI Web应用开发(二)的更多相关文章

  1. amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules

    amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules 一.总结 1.见名知意:见那些class名字知意,见函数名知意,见文件名知意 例如(HISTORY.md Web 组件更新历史 ...

  2. WEB前端开发--1(Web前端开发综述)

    Web前端开发 Web--Web系统      前端--网页上为用户呈现的部分   开发--编写代码 1. 前端与后端 前端:网页上为用户呈现的部分 后端:与数据库进行交互,完成数据存取 2. 网站与 ...

  3. 《开发技巧》WEB APP开发调试技巧

    前言 随着html5和nodejs的兴起.web APP越来越火,一套代码可以多平台使用.减少了很大的开发成本.很多APP中也集成了很多的html5页面,增强很高的应用体验.所以移动端页面也事关重要! ...

  4. go语言开发教程之web项目开发实战

    Golang介绍Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性.谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软件 ...

  5. Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十三】

    <Web 前端开发精华文章推荐>2014年第2期(总第23期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  6. Web 前端开发精华文章集锦(jQuery、HTML5、CSS3)【系列十七】

    <Web 前端开发精华文章推荐>2013年第五期(总第十七期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HTML5 和 C ...

  7. Web 前端开发人员和设计师必读文章推荐【系列二十八】

    <Web 前端开发精华文章推荐>2014年第7期(总第28期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  8. Web 前端开发精华文章集锦(jQuery、HTML5、CSS3)【系列十八】

    <Web 前端开发精华文章推荐>2013年第六期(总第十八期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HTML5 和 C ...

  9. Web 前端开发人员和设计师必读精华文章【系列二十六】

    <Web 前端开发精华文章推荐>2014年第5期(总第26期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  10. Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十二】

    <Web 前端开发精华文章推荐>2014年第一期(总第二十二期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML ...

随机推荐

  1. vs2017配置pthread.h的方法

    一.背景(以下为走不通的配置方法!) 笔者最开始配置pthread.h,采用的是vs自动安装的方法,如图所示. 点击完“管理NuGet程序包”之后,弹出一个页面,如下,在“浏览”中输入pthread. ...

  2. WebDriver高级应用实例(6)

    6.1精确比较网页截图图片 目的:对于核心界面进行截屏,并且使用测试过程中的截图和以前测试过程中的截图进行比较.确认页面是否发生了改变 被测网页的网址: http://www.baidu.com Ja ...

  3. 基于GTK+3 开发远程控制管理软件(C语言实现)系列二 Centos7下开发环境搭建

    一.安装gcc gcc-c++ make等编译工具 yum install gcc gcc-c++ kernel-devel 这一步,其实可以不用做,你在安装Centos7的时候,如果选择开发模式安装 ...

  4. (转)学会数据库读写分离、分表分库——用Mycat,这一篇就够了!

    原文:https://www.cnblogs.com/joylee/p/7513038.html 系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理 ...

  5. 用SpringSecurity从零搭建pc项目-01

    注:之前写过一些列的SpringSecurity的文章,重新写一遍是为了把某些不必要的步骤省去,留下精简的,因为工作中有一些不需要. 在java的权限框架里,shiro和SpringSecurity是 ...

  6. Android系统架构及启动流程

  7. MVC返回文件

    上一篇 介绍了Action 返回View, 顺便也看到了返回Json的处理, 这一篇并不看文件返回的源码, 此篇是为了应用. 1. Response返回文件 在MVC的项目中, 还是能看到很多同事, ...

  8. Redis安装以及主从实现

    Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串). list(链表).set(集合)和zset(有序 ...

  9. 面试:C++二叉树遍历(递归/非递归)

    #include <vector> #include <stack> #include <queue> using namespace std; struct Tr ...

  10. JS pop push unshift shift的作用与区别

    白话JS中数组方法pop push unshift shift的作用与区别,通过本文,你大概能知道这四种数组方法的基本使用与大致区别. 首先,这四种方法会直接修改数组,请先记住这一点. 我们先把pop ...