配置Guice Servlet

Installing a Servlet Module

如果你已经增加了GuiceFilter并且运行, Guice Servlet就已经建立. 不管如何, 你将要安装一个ServletModule的实例一边真正的使用Guice Servlet :

   Guice.createInjector(new ServletModule());

 这个模块创建request和session的周期中,并且提供一个配置filter和Servlet的地方。这时在你想要找个地方自由的创建注入器(injector),通常这个地方是在一个ServletContextListener中。

 ServletContextListener是个在web应用部署后就触发的Java servlet 组件,时机是在任何请求到达之前。Guice Servlet 提供了一个便利的实用程序,你可以编写他的子类以便注册你的ServletContextListener:

public class MyGuiceServletConfig extends GuiceServletContextListener {

  @Override
  protected Injector getInjector() {
    return Guice.createInjector(new ServletModule());
  }
}

往下继续, 增加如下内容到 web.xml,这样servlet容器在程序部署完成后触发这个类 so the servlet container triggers this class when the app is deployed:

<listener>
  <listener-class>com.example.MyGuiceServletConfig</listener-class>
</listener>

现在你可以在每个你需要的地方使用Guice Servlet了。注意,使用Guice Servlet 并不一定需要ServletContextListener 只要你记住创建你的注入器的时候安装ServletModule就可以了。

绑定语言

ServletModule 是一个用内部编码方式的web.xml部署描述符的替代品。filter和Servlet使用普通java方法调用来配置。下面是个典型的在创建Guice注册器时注册一个servlet的例子:

   Guice.createInjector(..., new ServletModule() {

     @Override
     protected void configureServlets() {
       serve("*.html").with(MyServlet.class);
     }
   }

这样注册了一个叫MyServlet的Servlet(一个HttpServlet的子类)对所有.html结尾的请求进行服务。. 你也可以使用路径风格的语法注册servlet,类似于web.xml里面的形式。:

       serve("/my/*").with(MyServlet.class);

Filter Mapping

你也可以用非常简单的语法做Filter的映射:

      filter("/*").through(MyFilter.class);

每个到来的请求都通过MyFilter处理。然后继续经过其他匹配的filter,最终被分发到实际处理的servlet。

注意:每个servlet(或者filter)需要注解为@Singleton。如果不能直接对这个类进行注解,你必须使用bind(..).in(Singleton.class)的方式使其成为@Singleton,独立于filter() 或者 servlet()规则。映射成其他的scope都是错误的。这是与Servlet保持一致的规范。Guice Servlet不支持过时的单线程模式(SingleThreadModel)

可用的注解

安装这个Servlet模块将你自动的可以访问一些servlet框架类。这样非常有助于使用servlet编程模式并且可注入任何Guice默认注入的对象,当你安装ServletModule后:

@RequestScoped
class SomeNonServletPojo {

  @Inject
  SomeNonServletPojo(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
    ...
  }

}

这个请求和响应(The request and response)周期是当前http请求。类似于http session对象周期是当前用户的session。另外你还可以注入当前的ServletContext,并且可以通过使用注解@RequestParameters映射请求的参数,像下面:

@Inject @RequestParameters Map<String, String[]> params;

这个必须是一个Map类型,并且map的value必须为String数组(译者注:必须为以上的代码形式),因为http协议允许多个值绑定到一个请求参数,尽管通常只有一个值。注意如果你想通过单实例或者更宽生命周期类访问request或者singletons session周期的类,你需要使用Provider<T>方式进行注入来代替普通的@Inject。 

分发的顺序

你可以随意按自己的喜好注册很多servlet和filter。他们将按ServletModule里面顺序比较和分发:

   Guice.createInjector(..., new ServletModule() {

     @Override
     protected void configureServlets() {
       filter("/*").through(MyFilter.class);
       filter("*.css").through(MyCssFilter.class);
       // etc..

       serve("*.html").with(MyServlet.class);
       serve("/my/*").with(MyServlet.class);
       // etc..
      }
    }

这将按代码中从上到下的顺序进行适配。例如,一个url是/my/file.js首先与下面的映射匹配:

       serve("*.html").with(MyServlet.class);

匹配失败后,将继续向下找下一个映射进行适配:

       serve("/my/*").with(MyServlet.class);

一旦映射的规则匹配,Guice Servlet将分发请求给MyServlet并且停止继续匹配。这个规则同时适用于filter(规则就是,匹配与映射列表中的第一个匹配)。

可变参数映射

以上两个映射规则也可以用更精简的可变参数与发来书写 syntax:

       serve("*.html", "/my/*").with(MyServlet.class);

这种方式可以让你把多个URI映射到同一个servlet。filter也可以用类似的方式映射。

Using RequestScope

每个servlet都在请求周期中,由ServletModule 配置完成。

默认的,有一些可用元素可进行注入,每个都被绑定在请求周期内:

  • HttpServletRequest / ServletRequest
  • HttpServletResponse / ServletResponse
  • @RequestParameters Map<String, String[]>

记住,如果一个类在请求周期外被创建并且注入点在类上时,要用Provider对这些元素进行注入,例如,一个单例的Servlet在请求周期外被创建,这样它在创建后才接受到request请求(通常是service()方法),就需要在请求周期依赖调用Provider.get()方法进行注册


The most common way to seed a value within RequestScope is to add a Filter in front of your servlet. This filter should seed the scope by adding the value as a request attribute.

For example, assume we want to scope the context path of each request as a String so that objects involved in processing the request can have this value injected.

过滤器可能如下:

   protected Filter createUserIdScopingFilter() {
     return new Filter() {
       @Override public void doFilter(
          ServletRequest request,  ServletResponse response, FilterChain chain)
           throws IOException, ServletException {
         HttpServletRequest httpRequest = (HttpServletRequest) request;
         // ...you'd probably want more sanity checking here
         Integer userId = Integer.valueOf(httpRequest.getParameter("user-id"));
         httpRequest.setAttribute(
             Key.get(Integer.class, Names.named("user-id")).toString(),
             userId);  
         chain.doFilter(request, response);
       }

      @Override public void init(FilterConfig filterConfig) throws ServletException { }

      @Override public void destroy() { }
     };
  } 

绑定可能像如下:

  public class YourServletModule extends ServletModule {
     @Override protected void configureServlets() {
         .....
        filter("/process-user*").through(createUserIdScopingFilter());
    }
  }

And the servlet to use this might look like this:

@Singleton
class UserProcessingServlet extends HttpServlet {

      private final Provider<Integer> userIdProvider;
      ....
   
      @Inject UserProcessingServlet(
         Provider<Integer> userIdProvider,
         .....) {
            this.userIdProvider = userIdProvider;
       }

      ....

     @Override public void doGet(
          HttpServletRequest req,  HttpServletResponse resp)
        throws ServletException, IOException {
             ...
            Integer userId = userIdProvider.get();
       }
}
太多了,待续。。。

你可能感兴趣的:(java,Guice)