An analysis of the implementation principle of OSGI Servletbrige

Source: Internet
Author: User

These two days let us deploy the OSGI environment on the server, and the application server uses WebLogic. As a result, the knowledge of OSGi Web is not understood, leading to a lot of detours. Finally, there is no way to see the Felix Http service part of the source code, only to finally solve the problem. Next take a note and analyze the implementation principle of Felix OSGI Servlet Brige.

There are two main implementations of OSGi Web applications, one of which is embedding webserver into an OSGi environment, and the other is embedding OSGi into webserver. At present the first way only jetty support better, and the second is not yet relevant webserver can be very good support. Another way to achieve this is to use Servletbrige to establish a connection between webserver and OSGi. The Servletbrige currently known are Felix and Equinox, which are said to have not been updated and are inefficient. We use Apache Felix's Servletbrige in the production environment of the division blue Company. Next, we will analyze the implementation of Felix's Servletbrige. First of all, the main job of Servletbrige is to link webserver and OSGi together. From a code perspective, ServletContext and OSGi bundlecontext are associated so that webserver can pass the request to OSGi when the HTTP request arrives at webserver. Servletbrige also needs to use ServletContext when implementing OSGi httpservice services. is the general schematic diagram of Felix Servletbrige. Parsing to enter code analysis, combined with an example of an official given to analyze. First look at the configuration in Web. xml: <listener>
<listener- class>org.apache.felix.http.samples.bridge.startuplistener</listener- class>
</listener>

<servlet>
<servlet- name>proxy</servlet- name>
<servlet- class>org.apache.felix.http.proxy.proxyservlet</servlet- class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet- name>proxy</servlet- name>
< URL-pattern>/*</ URL-pattern>
</servlet-mapping> first saw a servletcontextlistener registered, and then registered a Proxyservlet, the servlet's pattern is/*, This means that all requests are processed by the servlet. Combined with the above schematic diagram, it is generally possible to know the effect of these configurations. First look at the source of Startuplistener: Public voidContextinitialized (Servletcontextevent event) {
This. Service= NewFrameworkservice (Event.getservletcontext ());
This. Service.start ();
The Frameworkservice start method is called, and the Dostart method is called internally: Private voidDostart () throwsexception{
Felix tmp= NewFelix (Createconfig ());
Tmp.start ();
This. Felix=tmp
This invokes the Createconfig method to generate the configuration information and then launches Felix: PrivateMap<String, Object>Createconfig () throwsexception{
Properties Props= NewProperties ();
Props.load ( This. Context.getresourceasstream ("/web-inf/framework.properties"));

HashMap<String, Object>Map= NewHashMap<String, Object>();
for(Object key:Props.keyset ()) {
Map.put (Key.tostring (), Props.get (key));
}
map.put (Felixconstants.systembundle_activators_prop, Arrays.aslist (New Provisionactivator (This.context)));
returnMap
There is an important piece of information in the configuration information, and the Red Code section sets the Felix.systembundle.activators property, which is the function of invoking the configured Bundleactivator when the framework's system bundle is started. Then look at the start method of the Provisionactivator class: Public voidStart (Bundlecontext context) throwsexception{
Servletcontext.setattribute (BundleContext.class.getName (), context);
ArrayList<Bundle>Installed= NewArrayList<Bundle>();
for(URL url: Findbundles()) {
This. ServletContext.log ("Installing bundle [" +Url+ "]");
Bundle bundle = Context.installbundle (Url.toexternalform ());
Installed.add (bundle);
}

for(Bundle bundle:Installed) {
Bundle.start ();
}
By code in red, you can see that the bundlecontext of OSGi is set to the ServletContext property (for later use) and then gets the bundle (jar) from the specified directory and installs it into the OSGi framework. Then start these bundles. Here, the OSGi framework starts, and webserver successfully gets the bundlecontext. Next, we analyze the servletbrige internal implementation. Using Felix's Servletbrige requires placing the Org.apache.felix.http.bridge.jar in an OSGi environment, which means that the bundle is very important. First look at its bundleactivator: Public Final classBridgeactivator extendsabstracthttpactivator{
protected voidDostart () throwsException {
Super.dostart ();
Hashtable<String, Object>Props= NewHashtable ();
Props.put ("Http.felix.dispatcher", Getdispatcherservlet (). GetClass (). GetName ());
Getbundlecontext (). Registerservice (HttpServlet.class.getName (), Getdispatcherservlet (), props);
}
The two lines of code highlighted here are very important, calling the parent class to make some necessary settings, and then publishing a service (Servlet). Look at the Dostart method of the parent class Abstracthttpactivator: protected voidDostart () throwsexception{
Controller= NewHttpservicecontroller (Getbundlecontext ());
Dispatcher= NewDispatcherservlet (Controller);
This is just an instance of two objects, the latter being a servlet and using the controller in front of it. And this dispatcher is the service to be released in the previous step. Let's look at this servlet first: Public voidInit (servletconfig config) throwsservletexception{
Super. init (config);
Controller.register (Getservletcontext ());
}

Public voidDestroy () {
Controller.unregister ();
Super. Destroy ();
}

protected voidService (HttpServletRequest req, httpservletresponse Res) throwsServletexception, ioexception{
Controller.getdispatcher (). Dispatch (req, res);
You can see that there is a lot of internal controller processing. The request processing is also called by the Controller to handle. To view the controller's Register method: Public voidRegister (ServletContext ServletContext) {
Httpservicefactory Factory= NewHttpservicefactory (ServletContext, registry);
String[] Ifaces={Httpservice. class. GetName (), Exthttpservice. class. GetName ()};
Servicereg = Bundlecontext.registerservice (Ifaces, Factory, serviceprops);
In this method, the Httpservice service is registered with OSGi, using its own implementation. So the servlet registered in OSGi is collected here. I'm not going to analyze Httpservice's implementation here. Analysis here, ServletContext in the BUNDLECONTEXT,OSGI framework also has a httpservice service. OSGi also publishes the Dispatcherservlet service, and its service method invokes the controller to distribute the HTTP request to the servlet registered in OSGi. What needs to be done is to deliver the request in Wevserver to the Dispacherservlet hand that OSGi releases. This work is done by the Proxyservlet registered in Web. XML: Public voidInit (servletconfig config) throwsservletexception{
Super. init (config);
//Omit exception capture code
Doinit ();
}
Private voidDoinit () throwsexception{
tracker = new Dispatchertracker (Getbundlecontext (), NULL, Getservletconfig ());
Tracker.open ();
}
protected voidService (HttpServletRequest req, httpservletresponse Res) throwsServletexception, ioexception{
HttpServlet Dispatcher = Tracker.getdispatcher ();
if(Dispatcher!=NULL) {
Dispatcher.service (req, res);
} Else{
Res.senderror (503);
}
}
Public voidDestroy () {
Tracker.close ();
Super. Destroy ();
This uses an OSGi servicetracer to refer to the previously published Dispacherservlet service, and calls the services method of Dispatcherservlet when processing the request. Then the request was passed from Proxyservlet to the Dispacherservlet in Servletbrige, and the subsequent processing was clear. Here's another question, although the Dispacherservlet service was released in brigade, but it was not initialized. If you want to get to Webserver's ServletContext, then this servlet must get the servletconfig in the container. This means that proxyservlet, after acquiring an instance of the Dispacherservlet service, needs to initialize it before it can be used. The first line in the red section of the code above instantiates a dispachertracker, with Bundlecontext in the parameters, and ServletConfig: PublicDispatchertracker (Bundlecontext context, String filter, ServletConfig config) throwsexception{
Super(Context, Createfilter (context, filter), NULL);
This. config=Config
Because this class is a subclass of Servicetracker, the AddService method of Servicetracker is called when there is a qualifying service available: PublicObject Addingservice (servicereference ref) {
Object Service= Super. Addingservice (ref);
if(Service instanceofHttpServlet)) {
Setdispatcher ((httpservlet) service);
}
returnService
}
Private voidSetdispatcher (HttpServlet Dispatcher) {
Destroydispatcher ();
This. Dispatcher=Dispatcher
Initdispatcher ();
}
Private voidInitdispatcher () {
if(Dispatcher==NULL) {
return;
}

dispatcher.init (config);

This code will see the process of Dispacherservlet being fetched and initialized.

An analysis of the implementation principle of OSGI Servletbrige

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.