Many users of Jetty will not ever need to write a Jetty Handler, but instead will simply use the Servlet API. The existing jetty handlers for context, security, sessions and servlets can be reused without the need for extension.
However, some users may have special requirements or footprint concerns that prohibit the use of the full servlet API. For them implementing a Jetty handler is a straight forward way to provide dynamic web content with a minimum of fuss.
See also the Architecture page to understand more about Handlers vs Servlets.
The org.mortbay.jetty.Handler interface provides Jetty's core of content generation or manipulation. Classes that implement this interface are used to coordinate requests, filter requests and generate content.
The core API of the Handler interface is
public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException; |
The target of a handler is an identifier for the resource that should handle the passed request. This is normally the URI that is parsed from a HTTP Request. However, in two key circumstances the target may differ from the URI of the passed request:
The request and response objects used in the signature of the handle method are HttpServletRequest and HttpServletResponse. These are the standard APIs and are moderately restricted in what can be done to the request and response. More often than not, access to the jetty implementations of these classes is required: Request and Response. However, as the request and response may be wrapped by handlers, filters and servlets, it is not possible to pass the implementation directly. The following mantra will retrieve the core implementation objects from under any wrappers:
Request base_request = request instanceof Request?(Request)request:HttpConnection.getCurrentConnection().getRequest(); Response base_request = response instanceof Response?(Response)request:HttpConnection.getCurrentConnection().getResponse(); |
Note that if the handler passes the request on to another handler, it should use the
request/response objects passed in and not the base objects. This is to preserve any wrapping done by up stream handlers.
The dispatch argument indicates the state of the handling of the call and may be:
These mostly have significance for servlet and related handlers. For example, the security handler only applies authentication and authorization to REQUEST dispatches.
A Handler may handle a request by:
The OneHandler embedded example shows how a simple handler may generate a response.
The normal servlet response API may be used and will typically set some status, content headers and the write out the content:
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello OneHandler</h1>");
|
It is also very important that a handler indicate that it has completed handling the request and that the request should not be passed to other handlers:
Request base_request = (request instanceof Request) ? (Request)request:HttpConnection.getCurrentConnection().getRequest(); base_request.setHandled(true); |
Once the base request or response object is obtained, it may be modified. Typically modifications are done to achieve:
The context of the request may also be updated:
Typically a modified request is passed to another handler and then the modifications are undone in a finally block afterwards:
try
{
base_request.setSession(a_session);
next_handler.handle(target,request,response,dispatch);
}
finally
{
base_request.setSession(old_session);
}
|
The classes that implement the HandlerWrapper class are typically handler filters of this style.
A handler may simply inspect the request and use the target, request URI or other information to select another handler to pass the request to. These handlers typically implement the HandlerContainer interface.
Examples include:
See org.mortbay.jetty.handler package for some examples.