Servlet Mapping EDSL
Part of the EDSL builder language for configuring servlets
and filters with guice-servlet. Think of this as an in-code replacement for web.xml.
Filters and servlets are configured here using simple java method calls. Here is a typical
example of registering a filter when creating your Guice injector:
Guice.createInjector(..., new ServletModule() {
@Override
protected void configureServlets() {
serve("*.html").with(MyServlet.class)
}
}
This registers a servlet (subclass of
HttpServlet) called
MyServlet to service
any web pages ending in
.html. You can also use a path-style syntax to register
servlets:
serve("/my/*").with(MyServlet.class)
Every servlet (or filter) is required to be a singleton. If you cannot annotate the class
directly, you should add a separate
bind(..).in(Singleton.class) rule elsewhere in
your module. Mapping a servlet that is bound under any other scope is an error.
Dispatch Order
You are free to register as many servlets and filters as you like this way. They will
be compared and dispatched in the order in which the filter methods are called:
Guice.createInjector(..., new ServletModule() {
@Override
protected void configureServlets() {
filter("/*").through(MyFilter.class);
filter("*.css").through(MyCssFilter.class);
filter("*.jpg").through(new MyJpgFilter());
// etc..
serve("*.html").with(MyServlet.class);
serve("/my/*").with(MyServlet.class);
serve("*.jpg").with(new MyServlet());
// etc..
}
}
This will traverse down the list of rules in lexical order. For example, a url
"
/my/file.js" (after it runs through the matching filters) will first
be compared against the servlet mapping:
serve("*.html").with(MyServlet.class);
And failing that, it will descend to the next servlet mapping:
serve("/my/*").with(MyServlet.class);
Since this rule matches, Guice Servlet will dispatch to
MyServlet. These
two mapping rules can also be written in more compact form using varargs syntax:
serve("*.html", "/my/*").with(MyServlet.class);
This way you can map several URI patterns to the same servlet. A similar syntax is
also available for filter mappings.
Regular Expressions
You can also map servlets (or filters) to URIs using regular expressions:
serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)
This will map any URI containing the text "ajax" in it to
MyAjaxServlet. Such as:
- http://www.google.com/ajax.html
- http://www.google.com/content/ajax/index
- http://www.google.com/it/is_totally_ajaxian
Initialization Parameters
Servlets (and filters) allow you to pass in init params
using the
tag in web.xml. You can similarly pass in parameters to
Servlets and filters registered in Guice-servlet using a
java.util.Map of parameter
name/value pairs. For example, to initialize
MyServlet with two parameters
(
name="Dhanji", site="google.com") you could write:
Map<String, String> params = new HashMap<String, String>();
params.put("name", "Dhanji");
params.put("site", "google.com");
...
serve("/*").with(MyServlet.class, params)
Binding Keys
You can also bind keys rather than classes. This lets you hide
implementations with package-local visbility and expose them using
only a Guice module and an annotation:
...
filter("/*").through(Key.get(Filter.class, Fave.class));
Where
Filter.class refers to the Servlet API interface and
Fave.class is a
custom binding annotation. Elsewhere (in one of your own modules) you can bind this
filter's implementation:
bind(Filter.class).annotatedWith(Fave.class).to(MyFilterImpl.class);
See
com.google.inject.Binder for more information on binding syntax.
Multiple Modules
It is sometimes useful to capture servlet and filter mappings from multiple different
modules. This is essential if you want to package and offer drop-in Guice plugins that
provide servlet functionality.
Guice Servlet allows you to register several instances of
ServletModule to your
injector. The order in which these modules are installed determines the dispatch order
of filters and the precedence order of servlets. For example, if you had two servlet modules,
RpcModule and
WebServiceModule and they each contained a filter that mapped
to the same URI pattern,
"/*":
In
RpcModule:
filter("/*").through(RpcFilter.class);
In
WebServiceModule:
filter("/*").through(WebServiceFilter.class);
Then the order in which these filters are dispatched is determined by the order in which
the modules are installed:
install(new WebServiceModule());
install(new RpcModule());
In the case shown above
WebServiceFilter will run first.