在AppFuse实现级联下拉列表最方便的方式是使用DWR了,AppFuse默认就支持DWR。web.xml里DWR配置部分开始就存在了。
web.xml:
1
<servlet>
2
<servlet-name>dwr-invoker</servlet-name>
3
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
4
<init-param>
5
<param-name>debug</param-name>
6
<param-value>true</param-value>
7
</init-param>
8
</servlet>
9
10
<servlet-mapping>
11
<servlet-name>dwr-invoker</servlet-name>
12
<url-pattern>/dwr/*</url-pattern>
13
</servlet-mapping> 有一点非常要注意到,web.xml里staticFilter默认是包含dwr部分了,如果我们不屏蔽掉dwr这部分,获得dwr的响应是不正常的。在我没有屏蔽的时候,DWR调用java是可以的,java返回的内容也是正常的,但是dwr执行回调函数时怎样也没有反映。这个问题困扰了我很久,直到发现这个配置后屏蔽调就好了。
1
<filter>
2
<filter-name>staticFilter</filter-name>
3
<filter-class>org.appfuse.webapp.filter.StaticFilter</filter-class>
4
<init-param>
5
<param-name>includes</param-name>
6
<!--<param-value>/scripts/dojo/*,/dwr/*</param-value>-->
7
<param-value>/scripts/dojo/*</param-value>
8
</init-param>
9
</filter> 完成DWR的配置,我们就可以通过DWR调用我们的Java代码实现级联下拉列表了。刚开始我想通过DWR直接调Action来实现,但是调用Action时发现通过Spring注入的Manager和DAO是没有办法获得的。DWR官方号称是整合了Struts,但是文档里的例子只举到怎么调用ActionForm,Struts2都已经取消了烦人的ActionForm,还调他做甚?不过,有一句提示:“一个比较好方法是重构你想调用的Action,提取出Action的逻辑。DWR和你的Action就可以同时调用相同的方法了。”所以,用DWR调用逻辑的Service看来是比较可行的办法。
我们可以参照AppFuse生产的dwr.xml里UserManager的实现,来实现我们的Service。
CompanyService:
1
package com.reda.app.service;
2
3
import java.util.Map;
4
public interface CompanyService
{
5
6
public Map selectInput(String companyTypeId);
7
} CompanyServiceImpl:
1
package com.reda.app.service.impl;
2
3
import com.reda.app.service.CompanyService;
4
import com.reda.app.model.Company;
5
import com.reda.app.model.CompanyType;
6
import com.reda.app.dao.CompanyDao;
7
8
import java.util.List;
9
import java.util.Map;
10
import java.util.HashMap;
11
12
public class CompanyServiceImpl implements CompanyService
{
13
14
private CompanyDao companyDao;
15
16
public void setCompanyDao(CompanyDao companyDao)
{
17
this.companyDao = companyDao;
18
}
19
20
public Map selectInput(String companyTypeId)
{
21
Company company = new Company();
22
CompanyType companyType = new CompanyType();
23
companyType.setTypeId(new Long(companyTypeId));
24
company.setCompanyType(companyType);
25
List list = companyDao.select(company);
26
27
Map<String, String> map = new HashMap<String, String>();
28
29
for (Object aList : list)
{
30
map.put(((Company) aList).getCompanyId().toString(), ((Company) aList).getCompanyName());
31
}
32
33
return map;
34
}
35
36
} 同时把上面的Service添加到Spring的配置文件里。
applicationContext.xml:
1
<bean id="companyService" class="com.reda.app.service.impl.CompanyServiceImpl">
2
<property name="companyDao" ref="companyDao"/>
3
</bean> DWR的Creators支持Spring,我们可以通过Spring的方式创建。
dwr.xml:
1
<create creator="spring" javascript="CompanyService">
2
<param name="class" value="com.reda.app.service.CompanyService"/>
3
<param name="beanName" value="companyService"/>
4
</create> 这样我们通过
http://localhost:8080/[ YOUR-WEBAPP ]/dwr,就可以看到生产的Javascript代码了。
我们在JSP里通过回调函数就可以实现级联下拉列表了。
JSP:
1
<script type='text/javascript' src='<%=request.getContextPath()%>
/dwr/interface/CompanyService.js'></script>
2
<script type='text/javascript' src='<%=request.getContextPath()%>
/dwr/engine.js'></script>
3
<script type='text/javascript' src='<%=request.getContextPath()%>
/dwr/util.js'></script>
4
5
<script type='text/javascript'>
6
function searchCompany(companyTypeId)
{
7
dwr.util.removeAllOptions("person.company.companyId");
8
CompanyService.selectInput(companyTypeId, function(data)
{
9
dwr.util.addOptions("person.company.companyId", data);
10
});
11
}
12
</script>
13
14
<s:label for="personForm_company_companyType" value="%{getText('companyType.typeName')}" cssClass="desc"/>
15
<s:select name="person.company.companyType.typeId" list="companyTypeList" listKey="typeId" listValue="typeName"
16
onchange="searchCompany(this.value)"></s:select>
17
<s:label for="personForm_company_companyName" value="%{getText('company.companyName')}" cssClass="desc"/>
18
<s:select name="person.company.companyId" list="companyList" listKey="companyId"
19
listValue="companyName"></s:select>
20
下面是通过HttpWatch扑获的数据。我们可以看到DWR是发出了什么样的请求,以及返回的数据结构。
HTTP Request:
POST Data:
callCount=1
page=/reda/persons.html;jsessionid=41C3CAEA0AEDFA7288EBFFBA0A5543BB
httpSessionId=1CBB46415786B48DC00EB91C0BA0BB23
scriptSessionId=658A71BBBEB17A34CB847C6A46EEA00581
c0-scriptName=CompanyService
c0-methodName=selectInput
c0-id=0
c0-param0=string:8
batchId=0
Content:
//#DWR-INSERT
//#DWR-REPLY
dwr.engine._remoteHandleCallback('0','0',{'74':"\u5B9C\u6625\u6E29\u548C\u5B9E\u4E1A\u6709\u9650\u516C\u53F8",'63':"\u682A\u6D32\u5E02\u660E\u65E5\u73BB\u7483\u94A2\u5382",'70':"\u6C38\u5DDE\u5E02\u7F8E\u96C5\u73BB\u7483\u94A2\u5236\u54C1\u5382",'75':"\u5B9C\u6625\u73A9\u5177\u5382",'58':"\u957F\u6C99\u66AE\u4E91\u4E9A\u592A\u6C7D\u8F66\u5185\u9970\u4EF6\u5382",'64':"\u682A\u6D32\u5E02\u752C\u7CA4\u4E0D\u9508\u94A2\u884C",'69':"\u91B4\u9675\u5E02\u65B0\u5EFA\u73BB\u7483\u94A2\u5382",'60':"\u682A\u6D32\u5F18\u71D5\u73BB\u7483\u94A2\u5382",'71':"\u53CC\u724C\u53BF\u73BB\u7483\u94A2\u6709\u9650\u516C\u53F8",'57':"\u6E56\u5357\u4E9A\u592A\u5B9E\u4E1A\u6709\u9650\u516C\u53F8",'65':"\u682A\u6D32\u5E02\u67F3\u9F99\u73BB\u7483\u94A2\u5236\u54C1\u6709\u9650\u8D23\u4EFB\u516C\u53F8",'76':"\u5B9C\u6625\u5E02\u8881\u5DDE\u946B\u6E90\u673A\u68B0\u6709\u9650\u516C\u53F8",'59':"\u957F\u6C99\u798F\u51EF\u6C7D\u8F66\u8F66\u8EAB\u6709\u9650\u516C\u53F8",'72':"\u840D\u4E61\u6C7D\u9A70\u5B9E\u4E1A\u516C\u53F8",'61':"\u682A\u6D32\u5E02\u5BCC\u4E3D\u6765\u73BB\u7483\u94A2\u6709\u9650\u516C\u53F8",'68':"\u91B4\u9675\u5E02\u6E58\u4E1C\u73BB\u7483\u94A2\u5382",'56':"\u6E56\u5357\u94F6\u6CB3\u73BB\u7483\u6750\u6599\u5F00\u53D1\u6709\u9650\u516C\u53F8",'77':"\u8D63\u897F\u5316\u5DE5\u5382",'62':"\u682A\u6D32\u5E02\u81EA\u6765\u6C34\u516C\u53F8\u73BB\u7483\u94A2\u5382",'73':"\u840D\u4E61\u5E02\u5317\u6865\u73BB\u7483\u94A2\u5236\u54C1\u5382",'66':"\u91B4\u9675\u5E02\u4E07\u901A\u516C\u53F8",'67':"\u91B4\u9675\u5E02\u798F\u661F\u73BB\u7483\u94A2\u5382"});
文章来源:
http://heyday.blogcn.com/diary,15807434.shtml