3 Web 和 Servlet
3.1 快速开始
我们从一个例子开始Guice Web的开发。
首先准备我们的环境,由于是web开发,因此我们需要guice-servlet的jar包。log4j不是必须的,只是为了方便日志记录而已(Guice内部是使用jdk内部的logging包来完成日志记录的)。
必可避免的要在web.xml中都一些手脚,这里先配置一个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>
GuiceFilter中并没有帮我们完成Guice的初始化工作,因此我们必须手动完成Guice的模块注入。
2
3 @Override
4 protected Injector getInjector() {
5 return Guice.createInjector( new ServletModule());
6 }
7 }
8
继续在web.xml中添加东西。
< listener-class > cn.imxylz.study.guice.web.MyGuiceServletContextListener </ listener-class >
</ listener >
显然我们需要将某个PATH映射到一个Servlet上,于是需要在ServletModule上做点事情。
2
3 @Override
4 protected Injector getInjector() {
5 return Guice.createInjector( new ServletModule() {
6 protected void configureServlets() {
7 serve( " /helloworld " ).with(HelloWorldServlet. class );
8 }
9 });
10 }
11 }
12
这里将/helloworld这个地址映射到HelloWorldServlet上。好吧,先写个 “HelloWorld”的Servlet吧。
2 public class HelloWorldServlet extends HttpServlet{
3 private static final long serialVersionUID = 1L ;
4 @Override
5 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
6 IOException {
7 resp.getWriter().append( " Hello, guice! " + new Date());
8 }
9 }
注意,根据Guice的Servlet要求,每一个Servlet必须是单例的,因此这里强制加上@Singleton。
好了,我们来看看输出。
3.2 注入服务
当然了,既然是一个IOC的容器,那么在Guice中也是可以注入服务的。
首先定义一个服务。
2 public interface HelloWorld {
3
4 void execute() throws IOException;
5 }
6
接着是服务的实现,注意在我们的服务中需要request和response对象,并且我们的服务假定是与request绑定的,采用@RequestScoped标签来标识。
2 public class HelloWorldImpl implements HelloWorld {
3
4 private HttpServletRequest request;
5 private HttpServletResponse response;
6 @Inject
7 public HelloWorldImpl(HttpServletRequest request, HttpServletResponse response) {
8 super ();
9 this .request = request;
10 this .response = response;
11 }
12
13 public void execute() throws IOException{
14 String name = request.getParameter( " user " );
15 if (name == null || name.length() < 1 )name = " Guest " ;
16 response.getWriter().append(String.format( " Hello, %s. %s -> sessionId=%s,hashCode=%d " n " , name,new Date(),request.getSession().getId(),hashCode()));
17 }
18
19 }
20
然后在我们的Servlet中可以采用如下实现。
2 public class HelloWorldServlet extends HttpServlet{
3 private static final long serialVersionUID = 1L ;
4 @Inject
5 private Injector inj;
6 @Override
7 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
8 IOException {
9 inj.getInstance(HelloWorld. class ).execute();
10 inj.getInstance(HelloWorld. class ).execute();
11 }
12 }
这里我们自动注入Injector对象,然后通过Inject对象获取我们的服务,注意我们没有将HttpServletRequest和HttpServletResponse手动注入到我们的服务中。
好了,我们再来看看输出。可以看到我们的对象是与request绑定,同一个request使用的同一个HelloWorld服务,不同的request那么是同一个session获取的服务也是不一样的。
老实说,Guice关于WEB的东西其实大概就这么多。其它的关于多规则匹配顺序,正则表达式匹配等等其实不谈也罢,都很弱,用处不大。
3.3 整合Struts 2
Guice可以与Struts 2整合,当然了理论上可以与其它MVC框架整合,只是Guice官方提供了一个Struts 2的插件。
首先看看依赖的jar包,我们尽可能的少用jar包。
aopalliance-1.0.jar是guice-servlet依赖的,因此guice需要aopalliance/guice/guice-servlet/guice-struts2-plugin等包,struts2启动依赖commons-logging/freemarker/ognl/struts2-core/xwork等jar包。lo4j只是为了记录日志方便而已。
首先定义一个服务,服务很简单输出服务器的状态。
2
3 String getStatus();
4 }
5
2
3 public String getStatus() {
4 return " I'am running. " ;
5 }
6 }
7
然后写一个Module绑定服务及其实现,当然如果偷懒可以使用@ImplementedBy,这里为了说明如果在配置文件中配置Module,所以单写一个Module。
2 @Override
3 public void configure(Binder binder) {
4 binder.bind(Service. class ).to(ServiceImpl. class );
5 }
6 }
然后写一个SessionScope级别的对象绑定访问次数。
2 public class AccessCounter {
3
4 private AtomicInteger count = new AtomicInteger( 0 );
5
6 public int visit() {
7 return count.incrementAndGet();
8 }
9
10 @Override
11 public String toString() {
12 return String.format( " AccessCounter#%s:%d " , this .hashCode(), count.get());
13 }
14 }
15
好了,我们的Servlet出场了。
2
3 import com.google.inject.Inject;
4
5 public class AccessStatusAction {
6
7 final AccessCounter counter;
8 final Service service;
9 String message;
10
11 @Inject
12 public AccessStatusAction(AccessCounter counter, Service service) {
13 this .counter = counter;
14 this .service = service;
15 }
16
17 public String execute() {
18 return " success " ;
19 }
20
21 public int getCount() {
22 return counter.visit();
23 }
24
25 public String getStatus() {
26 return service.getStatus();
27 }
28
29 public String getMessage() {
30 return message;
31 }
32
33 public void setMessage(String message) {
34 this .message = message;
35 }
36 }
37
可以看到我们很简单的服务又被Guice给入侵了,所以说Guice对我们业务逻辑的侵入是很大,估计这也是很多程序员不愿意推广Guice的一个原因吧。
要写的Java代码就这么多,剩下的就是一堆的配置了。
首先web.xml中配置struts2的filter,注意这里我们没必要再配置一个guice的listener了,因为在guice的struts2的插件中已经配置一个ServletModule了。
2 < web-app xmlns ="http://java.sun.com/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
4 version ="2.5" >
5
6 < display-name > guice </ display-name >
7 < description > xylz study project - guice </ description >
8
9 < filter >
10 < filter-name > guiceFilter </ filter-name >
11 < filter-class > com.google.inject.servlet.GuiceFilter </ filter-class >
12 </ filter >
13 < filter-mapping >
14 < filter-name > guiceFilter </ filter-name >
15 < url-pattern > /* </ url-pattern >
16 </ filter-mapping >
17 < filter >
18 < filter-name > struts2 </ filter-name >
19 < filter-class > org.apache.struts2.dispatcher.FilterDispatcher
20 </ filter-class >
21 </ filter >
22 < filter-mapping >
23 < filter-name > struts2 </ filter-name >
24 < url-pattern > /* </ url-pattern >
25 </ filter-mapping >
26 <!-- listener>
27 <listener-class>cn.imxylz.study.guice.web.MyGuiceServletContextListener</listener-class>
28 </listener -->
29 </ web-app >
30
下面该配置struts.xml了。
2 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
3 "http://struts.apache.org/dtds/struts-2.0.dtd" >
4
5 < struts >
6
7 < constant name ="guice.module" value ="cn.imxylz.study.guice.web.struts2.ServiceModule" />
8
9 < package name ="default" extends ="struts-default" >
10 < action name ="access-status"
11 class ="cn.imxylz.study.guice.web.struts2.AccessStatusAction" >
12 < result > access-status.jsp </ result >
13 </ action >
14 </ package >
15
16 </ struts >
17
在这里先配置我们的Module,我们的Module就是完成Guice的注入过程。在guice的Struts2插件中类com.google.inject.struts2.GuiceObjectFactory有以下逻辑:
void setModule(String moduleClassName) {
try {
// Instantiate user's module.
@SuppressWarnings({ " unchecked " })
Class <? extends Module > moduleClass =
(Class <? extends Module > ) Class.forName(moduleClassName);
this .module = moduleClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
这段逻辑就是完成我们Module的注入过程。
当然了我们需要配置一个Struts2的action类cn.imxylz.study.guice.web.struts2.AccessStatusAction,访问地址access-status.action正确的时候渲染access-status.jsp页面。
2
3 < html >
4 < body >
5 < h1 > Access Status </ h1 >
6 < h3 >< b > Access in this session: </ b >
7 < s:property value ="count" /></ h3 >
8
9 < h3 >< b > Status: </ b >
10 < s:property value ="status" /></ h3 >
11
12 < h3 >< b > Message: </ b >
13 < s:property value ="message" /></ h3 >
14 < h4 > <% = " sessionId= " + session.getId() %> </ h4 >
15 </ body >
16 </ html >
17
所有的工作就完成了,我们看看浏览器中的渲染结果。
即使如此,Guice整合Struts 2还是比较弱的。
上一篇:Google Guice 入门教程05 - AOP(面向切面编程)
下一篇:Google Guice 入门教程07 - 整合第三方组件(01)
©2009-2014 IMXYLZ