据DWR开发人员讲,目前(2013年11月)DWR的开发基于java5,要等到基于java6后才会添加CDI支持。
如果想要使DWR能与CDI合作,第一种办法,可以使用CDI的一个扩展来实现,即apache deltaspike。可以参照
<DWR不能得到CDI注入bean的一个解决办法 >
另外一种办法就是自己添加CdiCreator.java类来与CDI集成。
这个类在DWR开发人员帮助下已实现,并在tomcat8,jboss7.1.1.final下做过测试。
/*
* Copyright 2005 Joe Walker
*
* 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 org.directwebremoting.create;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.directwebremoting.extend.AbstractCreator;
import org.directwebremoting.extend.Creator;
import org.directwebremoting.util.LocalUtil;
/**
* Get a CDI managedBean,
* and get the original instance from managedBean.
* @author Joe Walker [joe at getahead dot ltd dot uk]
* @author mihaisheng [mihaisheng at sina.com.cn]
*/
public class CdiCreator extends AbstractCreator implements Creator
{
/**
* this Creator make DWR work with CDI bean.
* @param cdiBeanName is the name of the cdi managedBean.
* the concept of cdi socpe unlike servlet scope,recommend not set scriptScpope.
*/
/*
* must add this dependency
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
* */
//Get cdi BeanManger
@Inject private BeanManager manager;
public void setClass(String classname)
{
try
{
clazz = LocalUtil.classForName(classname);
if (getJavascript() == null)
{
setJavascript(clazz.getSimpleName());
}
}
catch (ExceptionInInitializerError ex)
{
throw new IllegalArgumentException("Error loading class: " + classname, ex);
}
catch (ClassNotFoundException ex)
{
throw new IllegalArgumentException("Class not found: " + classname, ex);
}
}
/* (non-Javadoc)
* @see org.directwebremoting.Creator#getType()
*/
public Class<?> getType()
{
return clazz;
}
/* (non-Javadoc)
* @see org.directwebremoting.Creator#getInstance()
*/
public Object getInstance() throws InstantiationException
{
try
{
//Lookup BeanManger from JNDI
if(null==manager){
InitialContext initCtx;
initCtx = new InitialContext();
try{
//lookup JNDI BeanManager for jboss
manager = (BeanManager) initCtx.lookup("java:comp/BeanManager");;
} catch (NamingException e) {
System.out.println("cant get BeanManager from java:comp/ ");
}
if(null==manager){
//lookup JNDI BeanManager for tomcat
try{
manager = (BeanManager) initCtx.lookup("java:comp/env/BeanManager");
} catch (NamingException e) {
System.out.println("cant get BeanManager from java:comp/env/ ");
}
}
if(null==manager){
System.out.println("CDI not support on this environment.");
return null;
}
}
//Get a defalut managedBeanName if cdiBeanName is blank
if(cdiBeanName==null || cdiBeanName.equals("")){
String className=clazz.getSimpleName();
cdiBeanName=className.substring(0,1).toLowerCase()+className.substring(1);
//may be cdiBeanName not equal with real cdi beanName
}
//Get cdi managedBeanName by beanName
Set<Bean<?>> cdiBeans=manager.getBeans(cdiBeanName);
if(!cdiBeans.isEmpty()){
Bean<?> cdiBean = cdiBeans.iterator().next();
CreationalContext<?> crtCtx = manager.createCreationalContext(cdiBean);
Object instance=manager.getReference(cdiBean, clazz, crtCtx);
return instance;
}else{
System.out.println("fail to get CDI bean with cdiBeanName [ "+cdiBeanName+" ]");
return null;
}
}
catch (Exception ex)
{
throw new InstantiationException("Illegal Access to default constructor on " + clazz.getName());
}
}
/**
* Sets the class name to create.
* @param className The name of the class to create
*/
public void setClassName(String className)
{
setClass(className);
}
/**
* Gets the name of the class to create.
* @return The name of the class to create
*/
public String getClassName()
{
return getType().getName();
}
/**
* Set The cdi managed BeanName
*/
public void setCdiBeanName(String name){
this.cdiBeanName=name;
}
/**
* Get The cdi managed BeanName
*/
public String getCdiBeanName(){
return this.cdiBeanName;
}
/**
* The cdi managed BeanName
*/
private String cdiBeanName=null;
/**
* The type of the class that we are creating
*/
private Class<?> clazz;
}
有了这个类后,就可以把CDI bean转化成DWR调用的方式了,如下:
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.directwebremoting.create.CdiCreator;
@Named
@SessionScoped
@RemoteProxy(creator=CdiCreator.class)
public class Action1 implements Serializable
{
private static final long serialVersionUID = -1231439157655757940L;
@Inject User user;
@RemoteMethod
public String setUser(){
user.setUsername("david");
user.setSex("man");
return user.getUsername();
}
@RemoteMethod
public String showUser(){
return "The user is: "+user.getUsername()+" sex is: "+user.getSex();
}
}
如果CDI bean的name为默认,那么在dwr里也不要设置,或设置为默认的action1。
如果CDI bean的name做了非默认设置,那么在dwr里也要设置,比如@Name("mybean"),
那么就要@RemoteProxy(creator=CdiCreator.class
,creatorParams =
{@Param(name = "cdiBeanName", value = "mybean")})
然后在页面里就可以用js调用了。
<h:head>
<title>Welcome</title>
<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>
<script type='text/javascript' src='dwr/interface/Action1.js'></script>
</h:head>
<h:body>
<h:form>
<input type="button" value="setUser(david)" οnclick="Action1.setUser(function(i){alert(i);});"/>
<input type="button" value="getUser" οnclick="Action1.showUser(function(i){alert(i);});"/>
</h:form>
我用了jsf,但jsp我没有试过,我认为也是可以的。
最后,还要添加servlet-api支持
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
如果给tomcat8添加BeanManger,可以参照 为tomcat8配置BeanManger。