在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