by Steven J. Owens (unless otherwise attributed)
First I'll discuss the general concept of the servlet engine. Feel free to skip ahead to the next section, but even if you think you already know it, you might want to read this section. A lot of people seem to miss the fundamental concept.
A servlet engine, is essentially a web server written in java, designed to run applications - collections of java classes - as part of the server, instead of only serving static data.
When a servlet engine with webapp and servlets is loaded and running, i.e. in full-on production state, the servlet engine listens for incoming HTTP requests on a port.
Maybe directly on port 80 if it's acting as the sole webserver on that machine, or customarily 8080 if there's a more normal web server already on port 80.
Note: For a long time it was typical for people to run the Apache web server on port 80, and use an apache module called mod_jk to connect it to the Tomcat server for requests to URLs defined in the mod_jk config. Essentially Apache httpd was acting as a proxy to Tomcat. Some of that was because people needed or wanted features that apache provided (like htaccess or urlrewriting) but mostly it was because of the belief that Apache httpd was significantly faster at serving static data. However, these days the Tomcat server is quite fast, so if performance is your goal, you're only hurting yourself by running it this way.
Note: These days the apache httpd proxying should be done using the post-apache-2.1 mod_proxy. Orignally it was done using the old mod_proxy which just used HTTP between httpd and tomcat. That was replaced by one with mod_jk, which used a special servlet-specific binary protocol between httpd and the servlet engine. This was way faster. However, when Apache 2.1 came out, the mod_jk binary protocol was rolled back into mod_proxy.
The servlet engine has a set of configurations (we'll get to that in a bit) for which requests get handled by which servlet objects instances. When an HTTP request comes in, the engine checks the URL against the configuration and hands it off to the right servlet object instance. Which particular servlet method it passes them to depends on the HTTP request's verb (most of the time it's GET or POST, but unlike vanilla CGI scripts, it won't be both unless the developer makes sure to code it to handle both).
Before passing the HTTP request into the servlet method, the engine parses it into a javax.servlet.HttpServletRequest object, and also sets up a javax.servlet.HttpServletResponse object for the response.
The servlet class can be stateful but must be thread-safe. Multiple HTTP requests will be passed to the servlet object at any time. Any thread-specific state has to be kept elsewhere - usually in either the request object or in the user's HttpSession.
The actual object instances that handle the requests are instantiated only when the first request comes in for URL that maps to that class. The engine keeps the instance in memory afterward. Theoretically the engine has the option of unloading the instance at any point for resource management, though that doesn't really seem to happen often. The engine will call certain methods on the class when instantiating it and when unloading it, which gives the servlet a chance to do housekeeping tasks like saving state, closing any open resources, etc.
Tomcat, the reference implementation for servlet engines from jakarta.apache.org, is available for download bundled with a bunch of limited implementations of other J2EE components, to make it feasible to do limited J2EE development with Tomcat and then migrate to a full-blown J2EE environment.
For example, Tomcat's download includes a limited JNDI implementation. The tomcat JNDI server is single-JVM only, whereas a full-blown JNDI server would include a stand-alone server that could serve requests to multiple other applications via network.
Additionally, there are other limitations that mostly don't come up, but may cause problems. For example, if you use the popular Hibernate package for object-relational mapping, you'll find that Tomcat's JNDI implementation does NOT allow you to bind Hibernate's SessionFactory to JNDI.
If I talk about servlet-engine-specific stuff at all, assume I'm talking about Tomcat, because it's the reference servlet engine, and because it's easy for you to get your own copy of Tomcat and follow along, and because I know a little bit about Tomcat.