/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import static com.google.common.base.Preconditions.checkState; import com.google.common.collect.ImmutableList; import com.google.inject.AbstractModule; import com.google.inject.Key; import java.util.Map; import javax.servlet.Filter; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; /** * Configures the servlet scopes and creates bindings for the servlet API objects so you can inject * the request, response, session, etc. * *
You should subclass this module to register servlets and filters in the {@link * #configureServlets()} method. * * @author crazybob@google.com (Bob Lee) * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class ServletModule extends AbstractModule { @Override protected final void configure() { checkState(filtersModuleBuilder == null, "Re-entry is not allowed."); checkState(servletsModuleBuilder == null, "Re-entry is not allowed."); filtersModuleBuilder = new FiltersModuleBuilder(binder()); servletsModuleBuilder = new ServletsModuleBuilder(binder()); try { // Install common bindings (skipped if already installed). install(new InternalServletModule()); // Install local filter and servlet bindings. configureServlets(); } finally { filtersModuleBuilder = null; servletsModuleBuilder = null; } } /** * * *
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() {
*
* {@literal @}Override
* protected void configureServlets() {
* serve("*.html").with(MyServlet.class)
* }
* }
*
*
* This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service
* any web pages ending in {@code .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 {@code bind(..).in(Singleton.class)} rule elsewhere in your
* module. Mapping a servlet that is bound under any other scope is an error.
*
* * *
*
* Guice.createInjector(..., new ServletModule() {
*
* {@literal @}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 "{@code
* /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 {@code 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.
*
* * *
* serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)
*
*
* This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as:
*
*
* Map<String, String> params = new HashMap<String, String>();
* params.put("name", "Dhanji");
* params.put("site", "google.com");
*
* ...
* serve("/*").with(MyServlet.class, params)
*
*
* * *
* ...
* filter("/*").through(Key.get(Filter.class, Fave.class));
*
*
* Where {@code Filter.class} refers to the Servlet API interface and {@code 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 {@link com.google.inject.Binder} for more information on binding syntax. * *
* *
Guice Servlet allows you to register several instances of {@code 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, * {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped to * the same URI pattern, {@code "/*"}: * *
In {@code RpcModule}: * *
* filter("/*").through(RpcFilter.class);
*
*
* In {@code 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 {@code WebServiceFilter} will run first. * * @since 2.0 */ protected void configureServlets() {} private FiltersModuleBuilder filtersModuleBuilder; private ServletsModuleBuilder servletsModuleBuilder; private FiltersModuleBuilder getFiltersModuleBuilder() { checkState( filtersModuleBuilder != null, "This method can only be used inside configureServlets()"); return filtersModuleBuilder; } private ServletsModuleBuilder getServletModuleBuilder() { checkState( servletsModuleBuilder != null, "This method can only be used inside configureServlets()"); return servletsModuleBuilder; } /** * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc. * @since 2.0 */ protected final FilterKeyBindingBuilder filter(String urlPattern, String... morePatterns) { return getFiltersModuleBuilder() .filter(ImmutableList.