如果读者对于Guice没有大体的了解,可以参考本人的另一篇Guice基础文章
Guice 提供了一个完整的体系使得我们在web应用中也可以使用它作为依赖注入的工具.
为什么使用 Guice :
使用Guice的好处:
- 构造函数注入
- 类型安全的, 方便的配置方式(只需要在web.xml中进行很少的配置)
- 模块化
- Guice AOP
同时, Guice并不会改变标准servlet的生命周期
如何配置呢?
在开始之前首先获取最新的 guice-servlet.jar.
小编用maven做,所以这块如果读者使用其他方式需要根据自己的情况进行配置.这里贴上小编的 maven 文件内容:
<dependency><groupId>com.google.inject</groupId><artifactId>guice</artifactId><version>4.0</version></dependency><dependency><groupId>com.google.inject.extensions</groupId><artifactId>guice-servlet</artifactId><version>4.0</version></dependency>
在web.xml中配置GuiceFilter
过滤器:
在所有依赖包都配置好之后,我们需要做的第一件事是配置GuiceFilter
. 这个过滤器重新路由所有的客户端请求.
<filter><filter-name>guiceFilter</filter-name><filter-class>com.google.inject.servlet.GuiceFilter</filter-class></filter><filter-mapping><filter-name>guiceFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
安装ServletModule
在完成上面的操作之后,接下来要做的事情是安装ServletModule
Guice.createInjector(new ServletModule());
这个模块是用来设置请求和会话范围(scopes),同时提供一个配置你的过滤器和servlet的方法. 一个不错的建议是在一个ServletContextListener
中进行,当然你也可以在其他你需要该注入器(injector)的地方.
Guice Servlet提供了一个GuiceServletContextListener
,我们可以继承该类实现自己的ServletContextListener
:
public class MyGuiceServletConfig extends GuiceServletContextListener {@Overrideprotected Injector getInjector() {return Guice.createInjector(new ServletModule());}
}
然后在web.xml中配置该listener.然后当Servlet 容器启动Web 应用时,该监听器便会被执行.我们的ServletModule
被安装.
<listener><listener-class>com.up.MyGuiceServletConfig</listener-class>
</listener>
Binding Language
我们可以将ServletModule
看做一个代码形式的web.xml文件.过滤器和servlet可以通过简单的调用一些java api 实现.下面看一个简单的例子:
Guice.createInjector(..., new ServletModule() {@Overrideprotected void configureServlets() {serve("/*").with(MyServlet.class);filter("/*").through(MyFilter.class);}}
serve("/*").with(MyServlet.class);
等价于
<servlet><servlet-name>MyFilter</servlet-name><servlet-class>com.up.servlet.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyFilter</servlet-name><url-pattern>/*</url-pattern></servlet-mapping>
filter("/*").through(MyFilter.class);
等价于
<filter><filter-name>MyFilter</filter-name><filter-class>com.up.filter.MyFilter</filter-class></filter><filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
Note: 每个 servlet 或者 filter 需要是单例的.如果你不能直接注解该类,那么你需要使用bind(..).in(Singleton.class)
. Guice servlet不支持SingleThreadModel
可用的注入:
安装了ServletModule
之后我可方便的注入一些servlet体系中的类.
@RequestScoped
class SomeNonServletPojo {@InjectSomeNonServletPojo(HttpServletRequest request, HttpServletResponse response, HttpSession session) {...}}
请求和响应是当前http请求作用域。同样的http会话对象是当前用户会话作用域。除此之外你也可以使用绑定注释@RequestParameters注入当前ServletContext和请求参数如下:
@Inject @RequestParameters Map<String, String[]> params;
这里必须是Map<String, String[]>
,因为http允许多个value对应于同一个key.
Note: 如果你想给一个大作用域的对象注入一个请求作用域或者会话作用域的对象, 你应该使用Provider<T>
多对一映射
我们可以将多个 url 映射到相同的 servlet.
serve("*.html", "/my/*").with(MyServlet.class);
该方法对于过滤器也同样适用.
正则表达式映射
我们也可以使用正则表达式方式映射 url 到特定的 servlet 或 filter.
serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)
上述实例会将所有包含 “ajax” 的 URI 映射到 MyAjaxServlet
.
初始化参数
在有 web.xml 时,我们可以通过配置<init-param>
给 servlet 或 filter 传入初始化参数. Guice Servlet 中完成该任务只需要在配置该 servlet 或 filter 时传入一个Map<String, String>
实例就ok了.
Map<String, String> params = new HashMap<String, String>();params.put("coffee", "Espresso");params.put("site", "google.com");serve("/*").with(MyServlet.class, params)
绑定Key
你也可以不绑定特定的实现类,取而代之的是绑定一个接口,然后通过 Guice 注入特定的实现类.
filter("/*").through(Key.get(Filter.class, Fave.class));
这里的Filter.class
是 Servlet API javax.seervlet.Filter
, Fave.class
是一个自定义的绑定注解.
然后在你自己的模块中将特定的filter绑定到该接口.
bind(Filter.class).annotatedWith(Fave.class).to(MyFilterImpl.class);
注入injector
你可以在任何时刻取得injector对象,只需要像下面这样一行代码就可以了.
@Singleton
public class MyServlet extends HttpServlet {@Inject private Injector injector;...
}// elsewhere in ServletModule
serve("/myurl").with(MyServlet.class);
恭喜你,到此你可以开始你自己的 Guice Servlet 之旅了.