4 整合第三方组件
在《Google Guice 入门教程06 – Web 和Servlet》 中我们看到了Guice 整合Struts 2的应用。本章节继续讨论Guice整合其它第三方组件的应用。
本章节重点谈Guice与DWR和Spring的整合。
4.1 整合DWR
DWR作为Ajax远程调用的服务端得到了很多程序员的追捧,在DWR的2.x版本中已经集成了Guice的插件。
老套了,我们还是定义一个HelloWorld的服务吧,哎,就喜欢HelloWorld,不怕被别人骂!
2
3 String sayHello();
4
5 Date getSystemDate();
6 }
7
然后写一个简单的实现吧。
2
3 @Override
4 public Date getSystemDate() {
5 return new Date();
6 }
7
8 @Override
9 public String sayHello() {
10 return " Hello, guice " ;
11 }
12 }
13
然后是与dwr有关的东西了,我们写一个dwr的listener来注入我们的模块。
2
3 import org.directwebremoting.guice.DwrGuiceServletContextListener;
4
5 /**
6 * @author xylz (www.imxylz.cn)
7 * @version $Rev: 105 $
8 */
9 public class MyDwrGuiceServletContextListener extends DwrGuiceServletContextListener{
10
11 @Override
12 protected void configure() {
13 bindRemotedAs( " helloworld " , HelloWorld. class ).to(HelloWorldImpl. class ).asEagerSingleton();
14 }
15 }
16
这里使用bindRemotedAs来将我们的服务开放出来供dwr远程调用。
剩下的就是修改web.xml,需要配置一个dwr的Servlet并且将我们的listener加入其中。看看全部的内容。
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-dwr </ display-name >
7 < description > xylz study project - guice </ description >
8
9 < listener >
10 < listener-class > cn.imxylz.study.guice.web.dwr.MyDwrGuiceServletContextListener
11 </ listener-class >
12 </ listener >
13 < servlet >
14 < servlet-name > dwr-invoker </ servlet-name >
15 < servlet-class > org.directwebremoting.guice.DwrGuiceServlet </ servlet-class >
16 < init-param >
17 < param-name > debug </ param-name >
18 < param-value > true </ param-value >
19 </ init-param >
20 </ servlet >
21 < servlet-mapping >
22 < servlet-name > dwr-invoker </ servlet-name >
23 < url-pattern > /dwr/* </ url-pattern >
24 </ servlet-mapping >
25
26 </ web-app >
27
非常简单,也非常简洁,其中DwrGuiceServlet的debug参数只是为了调试方便才开放的,实际中就不用写了。
好了,看看我们的效果。
2 < head >< title > dwr - test (www.imxylz.cn) </ title >
3 < script type ='text/javascript' src ='/guice-dwr/dwr/interface/helloworld.js' ></ script >
4 < script type ='text/javascript' src ='/guice-dwr/dwr/engine.js' ></ script >
5 < script type ='text/javascript' src ='/guice-dwr/dwr/util.js' ></ script >
6 < script type ='text/javascript' >
7 var showHello = function (data){
8 dwr.util.setValue('result',dwr.util.toDescriptiveString(data, 1 ));
9 }
10 var getSystemDate = function (data){
11 dwr.util.setValue('systime',dwr.util.toDescriptiveString(data, 2 ));
12 }
13 </ script >
14 < style type ='text/css' >
15 input.button { border : 1px outset ; margin : 0px ; padding : 0px ; }
16 span { background : #ffffdd ; white-space : pre ; padding-left : 20px ; }
17 </ style >
18 </ head >
19 < body onload ='dwr.util.useLoadingMessage()' >
20 < p >
21 < h2 > Guice and DWR </ h2 >
22 < input class ='button' type ='button' value ="Call HelloWorld 'sayHello' service" onclick ="helloworld.sayHello(showHello)" />
23 < span id ='result' ></ span >
24 </ p >
25 < p >
26 < input class ='button' type ='button' value ="Call HelloWorld 'getSystemDate' service" onclick ="helloworld.getSystemDate(getSystemDate)" />
27 < span id ='systime' ></ span >
28 </ P >
29 </ body >
30 </ html >
我们通过两个按钮来获取我们的远程调用的结果。
我对DWR的认识也仅限于此就不献丑了。有兴趣的可以研究http://directwebremoting.org/dwr/。
4.2 整合Spring
仍然使用我们的HelloWorld服务。
2
3 String sayHello(String user);
4 }
5
2
3 @Override
4 public String sayHello(String user) {
5 return String.format( " Welcome to Guice with spring, %1$s. Now is %2$tF %2$tH:%2$tM:%2$tS. " , user, new Date());
6 }
7 }
8
当然了,我们定义一个简单的spring配置文件,只有一个bean。
2 < beans xmlns ="http://www.springframework.org/schema/beans"
3 xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation ="http://www.springframework.org/schema/beans
5 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
6 < bean id ="helloworld" class ="cn.imxylz.study.guice.spring.HelloWorldImpl"
7 scope ="singleton" />
8 </ beans >
然后看我们的Demo程序。
2
3 final ApplicationContext context = new ClassPathXmlApplicationContext( " /applicationContext.xml " , GuiceSpringDemo. class );
4 Injector injector = Guice.createInjector( new AbstractModule() {
5 protected void configure() {
6 bind(BeanFactory. class ).toInstance(context);
7 bind(HelloWorld. class ).toProvider(SpringIntegration.fromSpring(HelloWorld. class , " helloworld " ));
8 }
9 });
10 HelloWorld hw1 = injector.getInstance(HelloWorld. class );
11 String msg = hw1.sayHello( " xylz " );
12 System.out.println(msg);
13 HelloWorld hw2 = (HelloWorld)context.getBean( " helloworld " );
14 String msg2 = hw2.sayHello( " xylz " );
15 System.out.println(msg2);
16 System.out.println(hw1 == hw2);
17 }
18
最后我们通过Injector和ApplicationContext都能够得到我们的服务,并且我们的服务hw1==hw2。
如果闲一个个服务的注入麻烦,这里还有一个简便的方法,一次将spring中的所有服务都注入。
Injector injector = Guice.createInjector( new Module() {
@Override
public void configure(Binder binder) {
SpringIntegration.bindAll(binder, context);
}
});
但是Guice获取服务的方式就不一样了。
String msg=injector.getInstance(Key.get(HelloWorldImpl.class, Names.named("helloworld"))).sayHello("xylz");
System.out.println(msg);
这里我们不能getInstance(HelloWorld.class)来获取一个服务了,为什么呢?因为注入所有服务的时候,Guice并不能知道我们的服务是什么类型,于是将当作实际的类型注入了,另外由于spring允许一种类型的多个服务(bean)存在,所以自动注入的时候为了区分就需要带一个命名的注解,比如我们的helloworld,这个名称就是spring中的id。在Injector中为了获取一个带注解的类型服务,我们需要com.google.inject.Key<T>对象,此对象可以讲类型和注解关联起来,这样我们就能从Guice容器中获取一个服务了。
那如果我们想屏蔽真实的服务代码,也就是我们只是想客户端拿到HelloWorld服务而不是HelloWorldImpl实现怎么做?
目前只能在spring中使用代理服务。
2 < beans xmlns ="http://www.springframework.org/schema/beans"
3 xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation ="http://www.springframework.org/schema/beans
5 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
6 < bean id ="helloworldTarget" class ="cn.imxylz.study.guice.spring.HelloWorldImpl"
7 scope ="singleton" />
8 < bean id ="helloworld" class ="org.springframework.aop.framework.ProxyFactoryBean" >
9 < property name ="proxyInterfaces" value ="cn.imxylz.study.guice.spring.HelloWorld" />
10 < property name ="target" ref ="helloworldTarget" />
11 </ bean >
12 </ beans >
然后我们在Guice中这样获取服务:
System.out.println(msg);
显然,如果客户端知道服务的实际类型并且知道spring中的id,那么仍然可以调用我们的服务,比如下面的例子:
System.out.println(msg3);
上一篇:Google Guice 入门教程06 – Web 和 Servlet
下一篇:Google Guice 入门教程08 - 整合第三方组件(2)
©2009-2014 IMXYLZ