Java Servlets

 

Microsoft Corporation
October 2003

Applies to
    Microsoft® ASP.NET
    Java Server Pages

Summary: Learn about Java servlets and how to convert them to ASP.NET by using the Java Language Conversion Assistant (JLCA). (15 printed pages)

Contents

Introduction
Servlets in J2EE
JLCA Conversion of Servlets
Servlet Equivalents in ASP.NET
Summary

Introduction

Many Java Web applications are built using a variant of the model-view-controller (MVC) paradigm. The MVC paradigm separates the data (the model) from the user interface (the view) and separates both of these from the classes controlling the interaction between the data and the user (the controller). In many Java-based Web applications, a servlet is used as the controller in the MVC paradigm. This is because a servlet is activated by the user, yet runs entirely on the server, allowing the servlet access to both the user interface and the data, while not actually being a component of either. The non-graphical and pure code nature of a servlet makes it the perfect choice for the controller portion.

Even if your Web application does not follow the MVC paradigm, you may use servlets to perform various non-graphical functions in your Web application because of a servlet's ability to receive user input while running on the server. Servlets can also be used to generate the resulting Web page themselves, but this practice has faded with the increasing popularity of JSP.

Microsoft® ASP.NET does not provide a direct equivalent to the servlet class. Instead, there are two basic alternatives. The first alternative, which is used by the Java Language Conversion Assistant (JLCA), is to encapsulate the functionality of a servlet in the codebehind of a non-graphical ASP.NET page. The other alternative is to create a new HttpHandler and direct a URL request to a specified class. The HTTPHandler is actually closer to the new Filter functionality in the servlet specification.

In this article, we will briefly discuss how to use servlets in a traditional Java Web application such as the CodeNotes Web site. We will then discuss how the JLCA converts servlets, and what changes you will likely have to make after the conversion. Finally, we will discuss ASP.NET alternatives to using servlets.

Servlets in J2EE

Two things must be done in order for a servlet to be included in your Web application.

  1. You must create a class which extends the javax.servlet.http.HttpServlet class and provides an implementation for at least one of the following HttpServlet methods: doGet(), doPost(), doPut(), doDelete(), init(), destroy(), or service().
  2. You must configure your Web server so that it has a mapping from one or more URLs to the servlet class.

For example, Listing 1 shows how you can create a simple servlet that retrieves a name from the request parameters and either greets the user, or if no name was supplied in the request string, displays "Hello World". In order to be accessible to your Web application, the HelloServlet class needs to be added to your application's WEB-INF\Classes directory.

Listing 1. HelloServlet.java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloServlet extends HttpServlet {
   public void doGet(HttpServletRequest request,
   HttpServletResponse response) throws IOException,
   ServletException {
      String text = request.getParameter("name");
      if (text == null)
         text = "World";
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.println("<html>");
      out.println("<body>");
      out.println("<h1>Hello " + text + "</h1>");
      out.println("</body>");
      out.println("</html>");
   }
}

As mentioned previously, in addition to creating the class for your servlet, you must also configure your Web server to map one or more URLs to the servlet. Listing 2 contains the XML content that needs to be added to the WEB-INF\web.xml file in order to map the URL "/HelloServlet" to the HelloServlet class in Listing 1.

Listing 2. Configuring your Web server to include the HelloServlet servlet

<servlet>
   <servlet-name>HelloServlet</servlet-name>
   <servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>HelloServlet</servlet-name>
   <url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>

The XML-contained Listing 2 is rather straightforward. The <servlet> element maps the class name of your servlet (in the <servlet-class> element) to an arbitrary name (in the <servlet-name> element). The name is used to refer to the servlet class within the web.xml file. The <servlet-mapping> element then maps a servlet by its name (in the <servlet-name> element, which corresponds to a <servlet-name> element of a <servlet> element) to an associated URL (in the <url-pattern> element). In addition to mapping a servlet to a single URL, the <url-pattern> element can also use two types of wildcard to map the servlet to multiple URLs.

  • "*.extension" will map the servlet to all URLs with a given extension. For example, a <url-pattern> of "/CodeNotes/*.servlet" will map to "/CodeNotes/a.servlet" and "/CodeNotes/b.servlet", and all other similar URLs.
  • "/*" will map the servlet to all URLs with the same beginning. For example, a <url-pattern> of "/CodeNotes/*" will map to "/CodeNotes/a" and "/CodeNotes/b/c" and all other similar URLs.

Servlets in www.codenotes.com

On the CodeNotes site, we use two servlets as part of the Struts framework. One of the two servlets is activated on each page request. The com.codenotes.web.CodenotesServlet servlet is activated on each page request to the regular CodeNotes site, and on the administration site, we use the org.apache.struts.action.ActionServlet for each page request.

As its package name implies, the ActionServlet is included with the Struts framework. In the Struts implementation of MVC, the ActionServlet acts as the controller and maps the incoming URL request to the corresponding action, as well as performing other actions specific to the Struts framework. Our servlet controller intercepts each page request, determines what model action (if any) to take and what view (if any) to return. All of this information is drawn from an xml configuration file.

The CodenotesServlet extends ActionServlet so it also provides the Struts functionality. The CodenotesServlet also instantiates and adds to the session various objects required during the user's visit to the site, such as the User object which represents all of a visitor's information, including the user's first name, last name, password, login, and others.

Because the CodenotesServlet class relies on a lot of CodeNotes-specific classes that do not relate to the use of servlets in a Web application, in this article we will use a simple servlet class that provides similar functionality as our example. In our simple servlet, we will add a Date object to the session when the user first activates the servlet and then we will forward the user to a welcome page. The ForwardServlet class in Listing 3 provides this functionality.

Listing 3. A simple servlet that updates a session (ForwardServlet.java)

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

public class ForwardServlet extends HttpServlet {
   public void doGet(HttpServletRequest request,
   HttpServletResponse response) throws IOException,
   ServletException {
      HttpSession mySession = request.getSession();
      Date myDate = (Date)mySession.getAttribute("firstvisit");
      if (myDate == null) {
         myDate = new Date();
         mySession.setAttribute("firstvisit", myDate);
      }
      RequestDispatcher rd = request.getRequestDispatcher("/Welcome.jsp");
      rd.forward(request, response);
   }
}

There are two important actions taking place in the ForwardServlet.doGet() method:

  1. Interaction with the session object. Using the request.getSession() method we can extract the Date object from the session and add a Date object to the session if one is not already present.
  2. Forwarding the request to the JSP page. By using a RequestDispatcher to forward the request instead of using the response.redirect() method, we do not force a new request to be created (creating a new request would cause the ForwardServlet to be activated again, creating an infinite loop).

As we said, ForwardServlet is a simplified version of the CodenotesServlet. In Struts, the ActionServlet class determines the target JSP page by examining the incoming request to determine the correct action, and then forwards control to the correct JSP page based on the results of the action. Since we are not discussing Struts in this article, we're simply forwarding to a static page.

JLCA Conversion of Servlets

The JLCA will convert your servlets into codebehind classes for corresponding ASP.NET pages. The ASP.NET page will not contain any code in the .aspx file and will have the same name as your servlet class. For example, when converting the HelloServlet class from Listing 1, the JLCA will create an empty "HelloServlet.aspx" ASP.NET page and the codebehind, stored in HelloServlet.aspx.cs (Listing 3), will contain the C# version of the code in HelloServlet.

Listing 4. HelloServlet.aspx.cs

using System;

public class HelloServlet:SupportClass.ServletSupport
{
   // Web Form Designer Region code removed for clarity purposes

   protected override void doGet(System.Web.HttpRequest
   request, System.Web.HttpResponse response)
   {
      //UPGRADE_TODO: Method 'javax.servlet.ServletRequest.getParameter'
      // was converted to 'System.Web.HttpRequest' which has a different
      // behavior.
      'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?
      'keyword="jlca1073_javaxservletServletRequestgetParameter
        _javalangString"'
      System.String text = request["subject"];
      if ((System.Object) text == null)
         text = "World";
      response.ContentType = "text/html";
      System.IO.TextWriter out_Renamed = response.Output;
      out_Renamed.WriteLine("<html>");
      out_Renamed.WriteLine("<body>");
      out_Renamed.WriteLine("<h1>Hello " + text + "</h1>");
      out_Renamed.WriteLine("</body>");
      out_Renamed.WriteLine("</html>");
   }
}

Notice that all the functionality from the Java HelloServlet class is contained in the doGet() method of the C# HelloServlet class even though the Page class, the class that codebehinds normally extend, does not contain a doGet() method. This is because the C# HelloServlet class extends the SupportClass.ServletSupport class, which performs the run-time conversion of a codebehind into a servlet equivalent. All of your converted servlets will extend the ServletSupport class.

The SupportClass.ServletSupport class extends the Page class (a valid codebehind class must extend, at some level, the Page class). In the ServletSupport.Page_Load() method, the type of incoming request is determined ("GET", "POST", and so on.) and the corresponding virtual function (doGet(), doPost(), and so on.) is called. ServletSupport also provides default implementations for all the basic servlet methods (doGet(), doPost(), and so on.) that will simply throw an exception saying the method is not implemented. The implementation of these methods is left to the child class, which is required to provide an implementation for at least one of the methods because that's a requirement for being a valid Java servlet. For example, in our HelloServlet class, the doPost() method is not implemented, so if a POST request is made to HelloServlet.aspx, an exception will be thrown. However, we do provide an implementation for the doGet() method, so when a GET request is made, the doGet() method will be executed.

The only upgrade issue in our conversion is a possible problem caused by the conversion of request.getParameter() to request[]. This change does not affect our simple application and can be ignored in this instance.

You will also have to check, and most likely update, any links to servlets within your Web application. This is because the JLCA will always give the resulting ASP.NET page the name of your servlet class regardless of the mapping within your WEB-INF\web.xml. Depending on the purpose of your servlet, you may wish to re-write/re-design portions of your application, as we did during the conversion of CodenotesServlet.

Conversion in the Codenotes Site

As previously explained, the CodeNotes site required each page request to activate the CodenotesServlet. It was too time consuming and difficult to change every link in our Web site to "CodenotesServlet.aspx" and devise a way to pass the intended link in the query string as well as the parameters that belong in the query string. Instead, we created an HttpHandler that performed the same functionality as the CodenotesServlet. As we will explain in the "HttpHandlers" section, HttpHandlers are objects that are activated by ASP.NET whenever a page request is made. There is a default HttpHandler included with ASP.NET and you can configure your Web application to activate a specified HttpHandler on requests to a specific URL, similar to how you can specify a servlet to be activated for certain URL requests.

In this example, we will walk through how we converted the ForwardServlet from Listing 3, which was our simplified version of the CodenotesServlet, to an HttpHandler. The conversion of the ForwardServlet class resulted in few upgrade issues, as shown in Listing 5.

Listing 5. Conversion of ForwardServlet.java pre-cleanup

using System;

public class ForwardServlet:SupportClass.ServletSupport
{
   // web form designer code omitted for clarity

   protected override void doGet(System.Web.HttpRequest
      request, System.Web.HttpResponse response)
   {
      System.Web.SessionState.HttpSessionState mySession = Session;
      System.DateTime myDate = (System.DateTime) mySession["firstvisit"];
      if (myDate == null)
      {
         myDate = System.DateTime.Now;
         mySession.Add("firstvisit", myDate);
      }
      // UPGRADE_TODO's removed for clarity
      System.Web.HttpServerUtility rd =
         request.getRequestDispatcher("/Welcome.jsp");
      //UPGRADE_TODO removed for clarity
      Server.Transfer("/forwardServlet/Welcome.aspx");
   }
}

The JLCA flagged more issues converting the ForwardServlet than it did with the HelloServlet. However, this is because ASP.NET does not have an equivalent to the request.getRequestDispatcher() method. Instead of retrieving a RequestDispatcher from the request object, in ASP.NET, each Page object has an HttpServerUtility object as a property and the HttpServerUtility.Transfer() method performs the same functionality as the RequestDispatcher.forward() method. The JLCA converts the RequestDispatcher.forward() method properly, so you can just delete the line where request.getRequestDispatcher() is called. Also, because the link is hard-coded, we have to change the link to reflect the new location of the ASP.NET page.

There was also one change that we had to make that was not flagged by the JLCA. DateTime Structures cannot be assigned null because they are Structures and not ordinary Objects. Because of this, comparing the DateTime instance with null is not a valid operation and will prevent compilation. Instead, we can just use an Object because we never actually use the Date stored in the Session.

The updated ForwardServlet, including the previously listed changes is shown in Listing 6.

Listing 6. ForwardServlet after fixing the JLCA issues

using System;

public class ForwardServlet:SupportClass.ServletSupport
{
   // Web Form Designer code omitted for clarity

   protected override void doGet(System.Web.HttpRequest
      request, System.Web.HttpResponse response)
   {
      System.Web.SessionState.HttpSessionState mySession = Session;
      Object myObj = mySession["firstvisit"];
      if (myObj == null)
      {
         DateTime myDate = System.DateTime.Now;
         mySession.Add("firstvisit", myDate);
      }
      Server.Transfer("/Welcome.aspx");
   }
}

As we previously mentioned, the CodenotesServlet was intended to be activated before every page request, instead of being activated on requests to a specific URL. So even though the converted ForwardServlet, once activated, functions similarly to the Java servlet, it is not activated in the same manner.

We need to convert our ForwardServlet into an HttpHandler in order to completely duplicate the functionality of the Java ForwardServlet. When creating our HttpHandler, we can reuse most of the converted code, but instead of extending the ServletSupport class, we must implement the IHttpHandler interface. Also, because the ForwardServlet class requires access to the user's session, we must implement the IRequiresSessionState interface, which has no methods and is simply used as a flag for the ASP.NET process to create a session instance before activating the HttpHandler. Also, our doGet() code must be placed in the ProcessRequest() method, which is where an HttpHandler's functionality is located. Finally, we have to implement the IsReusable Get property, setting it to return true, indicating that the Handler instance can be reused for multiple requests and sessions. Finally, because the original C# version of ForwardServlet was contained in the codebehind for the ForwardServlet.aspx ASP.NET page, we used a different file for storing it, ForwardHandler.cs, which is shown in Listing 7.

Listing 7. ForwardHandler.cs

using System;
using System.Collections;
using System.Web;
using System.Web.SessionState;

public class ForwardHandler : IHttpHandler, IRequiresSessionState
{
   public void ProcessRequest(HttpContext context)
   {
      HttpSessionState mySession = context.Session;
      Object myObj = mySession["firstvisit"];
      if (myObj == null)
      {
         DateTime now = DateTime.Now;
         mySession.Add("firstvisit", now);
      }
      context.Server.Transfer("Welcome.aspx");
   } // ProcessRequest


   public bool IsReusable
   {
      get
      {
         return true;
      }
   }
}

Now that we have created our HttpHandler, we need to configure our Web application to display the HttpHandler when necessary. The CodenotesServlet was intended to be activated upon each page request. We do not want that to be the case in the ASP.NET version, because we want ASP.NET pages to be handled by the default handler. Instead, on the CodeNotes site, we slightly altered all the links that activated servlets to have the format www.codenotes.com/xxxxxAction.aspx (this format was also used to simplify the Struts implementation). So we only need to configure our Web application to direct URL requests of the format *.Action.aspx to the ForwardHandler object. As shown in Listing 8, this is done by adding the <httpHandlers> element to the <system.web> element in the web.config file, and defining a new HttpHandler using the <add> element.

Listing 8. Configuring ForwardHandler

<httpHandlers>
   <add verb="*" path="*Action.aspx" type="ForwardHandler, ServletDemo"/>
</httpHandlers>

The information contained in the <httpHandlers> element is very similar to the information you supply when configuring a servlet in a web.xml file. However, unlike configuring a servlet, where you must add a <servlet> element and a <servlet-mapping> element, an HttpHandler is configured using a single <add> element. The verb attribute indicates the HTTP verbs (such as GET, POST, and DELETE) for which the HttpHandler should be activated. By using "*" as our value for the verb attribute, we are configuring the Web application to use the ForwardHandler regardless of the type of HTTP request. The path attribute is used to map URL requests to the handler. We used "*Action.aspx" so that all URL requests ending with Action.aspx are mapped to ForwardHandler, while at the same time, requests for specific aspx pages that do not end in Action.aspx are handled by the default HttpHandler. Finally, the type attribute specifies which HttpHandler to activate. The format is "NamespaceQualifiedClassName, AssemblyName". When looking at Listing 8, you can see that our class name is ForwardHandler (in the global namespace) and the assembly name is ServletDemo.

Servlet Equivalents in ASP.NET

As we showed in the JLCA Conversion of Servlets section, there are two ways to replace servlet functionality in ASP.NET: using a codebehind for an ASP.NET page with no HTML, or creating an HttpHandler. Because the JLCA Conversion of Servlets section covered how to use the JLCA to create an ASP.NET equivalent of a Java servlet, in this section we will limit the discussion to how to create a new servlet using ASP.NET technology.

ASP.NET Pages That Contain No HTML

When using an ASP.NET codebehind to mimic servlet functionality, you have two options. First, you can extend the ServletSupport class and insert your desired code in the appropriate doXXX() method, similar to servlets produced by the JLCA. Second, you can design your own solution to mimic servlets in ASP.NET by using a codebehind file.

Use of the ServletSupport class was covered in the JLCA Conversion of Servlets section, so we will provide only a brief summary here of the three main steps involved in using the ServletSupport class:

  1. Create a Web form, which will have the URL through which your servlet equivalent will be activated.
  2. In the codebehind of the Web form, extend the ServletSupport class instead of the Page class.
  3. Implement your choice of the doXXX() methods (such as doGet()).

If your original Java project did not contain any servlets, or if you did not convert your project using the JLCA, you can still have access to the ServletSupport class. Create a simple servlet, like the HelloServlet in Listing 1, in its own directory (with no subdirectories) and convert this directory using the JLCA. Once the conversion is complete, you can add the SupportClass.cs file from the conversion to your project and all of its associated classes will be available.

If you wish to provide your own implementation of servlets and do not wish to use the ServletSupport class, you must still create a Web form for your servlet. However, instead of extending the ServletSupport class, you will extend the Page class and include your functionality in the Page_Load() method. For most purposes, you will simply include your servlet functionality within the Page_Load() method and not check they type of HTTP request. However, if you do wish to examine the type of HTTP request and respond accordingly, you will use code similar to that found in Listing 9.

Listing 9. Determining the HTTP data transfer method type

if (Request.HttpMethod.Equals("GET")) {
   // HTTP data transfer method type is "GET"
   doGet();
}
if (Request.HttpMethod.Equals("POST")) {
   // HTTP data transfer method type is "POST"
   doPost();
}
if (Request.HttpMethod.Equals("HEAD")) {
   // HTTP data transfer method type is "HEAD"
   doHead();
}
if (Request.HttpMethod.Equals("DELETE")) {
   // HTTP data transfer method is "DELETE"
   doDelete();
}
if (Request.HttpMethod.Equals("PUT")) {
   // HTTP data transfer method is "PUT"
   doPut();
}

Notice in Listing 9, none of the calls to the doXXX() (such as doGet()) methods pass a request or response object as parameters. There is no need to pass these parameters along, as each Page object has the private members Request and Response, so the request and response objects are already available to the doXXX() methods. Listing 10 contains a sample framework for a codebehind examining the HttpMethod property to determine the action it should take.

Listing 10. Implementing ForwardServlet without using the SupportClass

public class SampleServlet : System.Web.UI.Page
{
   private void Page_Load(object sender, System.EventArgs e)
   {
      if (Request.HttpMethod.Equals("GET"))
      doGet();
   }

   private void doGet()
   {
      // do stuff here
    } // doGet
} 

HttpHandler

If you don't wish for your servlet to solely be activated by a single URL, but instead wish to have multiple URLs invoke your servlet, creating an HttpHandler is one option. ASP.NET maps all HTTP requests to an HttpHandler. The requests are mapped according to the URL with the extension usually being the main method of mapping a URL. Once the URL has been mapped to an HttpHandler, ASP.NET calls the HttpHandler.ProcessRequest() method. For example, in a basic Web application, all URLs with the .aspx extension are mapped to a default HttpHandler included with ASP.NET. The default HttpHandler provides enough implementation to map a URL request to, and to display, the corresponding ASP.NET page. Because of this, you will seldom, if ever, want to create an HttpHandler that works for all .aspx pages. For example, on the CodeNotes site, our CodenotesServlet functionality was placed in an HttpHandler that was activated for all URLs ending in Action.aspx. This allowed us to still use the default HttpHandler to display .aspx pages, while at the same time providing the Struts functionality that was contained within CodenotesServlet. The discussion in this topic is limited to creating, and using, your own HttpHandler.

Unlike a Page object, an HttpHandler does not have private members, such as Request and Response that are initialized for you. Instead, to access the request, response, or other objects, you must work with the HttpContext object that is passed into the ProcessRequest() method. HttpContext objects contain all the information about the current state of the Web application, including the current request, the response, the session state, and others. In the ForwardHandler example in Listing 7, we used the context object to gain access to the user's session and the Server object, which allows you to forward the request to different pages. The specific lines used are shown in Listing 11.

Listing 11. Using the context object

HttpSessionState mySession = context.Session;
context.Server.Transfer("Welcome.aspx");

One important thing to note is that a Session will not automatically be instantiated before the HttpHandler is called. In order to ensure that a Session is created, your HttpHandler must implement the IRequiresSessionState. This marker interface will make ASP.NET create the session (if necessary) before calling ProcessRequest(). However, IRequiresSessionState is simply a marker interface with no methods, so you don't need to do any special implementation. In Listing 12, we have another example of the ForwardHandler, this one written from scratch using the HttpContext parameter to access the Session and Server objects, instead of calling the static HttpContext.Current property.

Listing 12. ForwardHandler

public class ForwardHandler : IHttpHandler,
   IRequiresSessionState
{
   public void ProcessRequest(HttpContext context)
   {
      HttpSessionState mySession = context.Session;
      Object myObj = mySession["firstvisit"];
      if (myObj == null)
      {
         Date now = System.DateTime.Now;
         mySession.Add("firstvisit", now);
      }
   context.Server.Transfer("/Welcome.aspx");
   } // ProcessRequest

   public bool IsReusable
   {
      get
      {
         return true;
      } // get
   } // IsReusable property
}

As we explained in the JLCA Conversion of Servlets section, once you have created an HttpHandler, you must configure it in your web.config file. All HttpHandlers are configured within the <httpHandlers> element in your web.config file. If your web.config file doesn't already have an <httpHandlers> element, you must create one and place it inside the <system.web> element (and not nested within other elements). Once the <httpHandlers> element has been created, you use the <add> element to define a new rule for using an HttpHandler, and configure this rule using the verb, path, and type attributes, which are responsible for the following:

  • verb defines which HTTP verbs will cause the HttpHandler. It can be set to a single HTTP verb (such as "POST"), a comma-separated list (for example, "POST, GET"), or given a value of "*" to work for all HTTP verbs.
  • path contains either a single URL or a simple wildcard string (such as "/servlets/*" or "*.myExtension"). If you wish to activate your HttpHandler for URL requests for extensions other than the default .aspx extension, you must also configure IIS to map the file extension to the ASP.NET ISAPI (aspnet_isapi.dll).

    To add a file extension, open IIS, right-click on the Web site, click Properties, and then click the Home Directory tab. Click Configuration to display the Application Configuration window, which allows you to configure the handling of URL requests according to their extension.

  • type references the class to be used as the HttpHandler. It follows the format "NamespaceQualified.className, assemblyName".

Listing 13 is an example of how to use your web.config file to use the ForwardHandler from the ServletDemo assembly to handle all HTTP requests with URLs ending in "Action.aspx."

Listing 13. Configuring an HttpHandler in your web.config file

<httpHandlers>
   <add verb="*" path="*Action.aspx" type="ForwardHandler, ServletDemo"/>
</httpHandlers>

Summary

Servlets are very powerful components in Java-based Web applications that are activated by the user, yet run entirely on the server. Although ASP.NET has no direct equivalent of servlets, the JLCA does provide a workaround that places the servlet functionality in the codebehind of an ASP.NET Web form. Provided that your servlet is used in very specific instances, aside from changing the links in your Web application to direct them to the new location of your servlet, you should not have to make many changes to your servlets after running the JLCA. However, if you require your servlet to run for a variety of URLs, you may wish to change the implementation of the servlet to one that implements the IHttpHandler interface. HttpHandlers can be configured similarly to servlets in the web.config file of your Web application, allowing you the flexibility of having your servlet-like class be activated through multiple URLs.

Show: