当柳上原的风吹向天际的时候...

真正的快乐来源于创造

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks

#

任务:数据库中有六千余条目录(id,pid,name)数据组成一棵目录树,需要通过WebService服务提供给客户端显示出来(Swing中的JTree)。

实现功能的第一步:在客户端的树显示时通过网络得到顶层目录,再根据用户的点击逐级展开下级目录。此方案优点:实现简单;缺点:点击多次容易使人厌烦,速度不行。

客户端实现改善的第二步:启动一个线程从服务器加载数据逐渐生成一个节点树,再交给界面上的JTree命其更新。此举对操作友好型有改进,速度上也有所提高。

客户端实现改善的第三步:先起线程从服务器端一次性下载完全部数据,而后置入内存,再以此为基础构建树。此举对速度也有明显提高。

客户端实现改善的第四步:将已经加载的节点从内存中删除,使查找时间逐渐减小。此举对速度有一定提高。

服务器端实现改善的第四步:不使用Hibernate的对象映射而单独遴选字段组建成一个包装类,此举对速度有一定提高。

服务器端实现改善的第五步:直接采用优化的存储过程将表中必要行集的数据在数据库段形成大文本,一次性传出,WS服务器端只负责传输,此举对速度有明显提高。

通过以上措施,完成包括六千个节点的树显示速度数量级的提高,综合评价一下,以上逐步中,第三步:在客户端另起线程从内存加载数据形成一棵完整的节点树再通知界面更新 和 第五步:通过存储过程直接取得行集合并结果对提高速度帮助最大。


posted @ 2010-01-08 22:20 何杨| 编辑 收藏

编程中Java应用常需要访问Tomcat,Weblogic等中间件,如果因为远程机器没有开机或是中间件服务未启动而导致服务不可用,则程序会抛出异常。如果事先对这些端口进行检测会更有利与我们诊断错误,下面就是一个诊断远程端口的类:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.alpha.model.TPClientModel;
import com.alpha.util.DlgUtil;

/**
 * 这个类仅本类使用
 * 
@author 何杨
 * @date 2009-11-5
 * @time 下午03:15:20
 
*/
class IpPort{
    String ip;
    
int    port;
}

/**
 * 远程端口探测器,判断远程端口是否打开
 * 
 * 
@author 何杨
 * @date 2009-11-5
 * @time 下午02:48:56
 
*/
public class RemotePortTestor{    
    
public static Logger logger = Logger.getLogger(TPClientModel.class);
    
    
// 测试项目集合
    private List<IpPort> testItems;
    
    
    
/**
     * 构造函数
     * 
     * 
@param fileName
     * 
@param keys
     
*/
    
public RemotePortTestor(String fileName,List<String> keys){
        Properties prop
=new Properties();
        
try {
            prop.load(
new FileInputStream(fileName));
            
            testItems
=new ArrayList<IpPort>();
            
for(String key:keys){
                String value
=prop.getProperty(key);
                testItems.add(getIpPortAddr(value));
            }            
        } 
catch (FileNotFoundException e) {
            logger.error(e);
            e.printStackTrace();
        } 
catch (IOException e) {
            logger.error(e);
            e.printStackTrace();
        }
    }
    
    
/**
     * 检测远端端口,全部通过返回真
     * 
     * 
@return
     * 创建人:何杨
     * 创建日期:2009-11-5
     * 创建时间:下午03:32:34
     
*/
    
public boolean testRemotePorts(){
        
for(IpPort ipPort:testItems){
            
if(testRemotePort(ipPort.ip,ipPort.port)==false){
                
return false;
            }            
        }
        
        
return true;
    }
    
    
/**
     * 从URL中得到IP地址和端口
     * 
     * 
@param url
     * 
@return
     * 创建人:何杨
     * 创建日期:2009-11-5
     * 创建时间:下午03:32:55
     
*/
    
private IpPort getIpPortAddr(String url){
        IpPort ipPort
=new IpPort();
        
        String ip
=getMatchedString("(//)(.*)(:)",url);
        ipPort.ip
=ip;
        
        String port
=getMatchedString("(:)(\\d+)",url);
        ipPort.port
=Integer.parseInt(port);
        
        
return ipPort;
    }
    
    
/**
     * 检测端口是否能连接上
     * 
     * 
@param ip
     * 
@param port
     * 
@return
     * 创建人:何杨
     * 创建日期:2009-11-5
     * 创建时间:下午03:33:20
     
*/
    
public static boolean testRemotePort(String ip,int port){        
        
try {
            Socket s
=new Socket(ip,port);
            System.out.println(s.getLocalAddress()
+"可以访问"+ip+"上的端口"+port+"的服务.");
            s
=null;
            
return true;
        } 
catch (Exception e) {
            System.out.println(
"无法取得"+ip+"上的端口"+port+"的服务.");
            DlgUtil.popupErrorDialog(
"无法取得"+ip+"上的端口"+port+"的服务!\r\n,请确认服务可用后再执行本程序!");
                        
            e.printStackTrace();
            logger.error(e);
            
return false;
        }    
    }
    
    
/**
     * 从target找到regex能代表的文字
     * 
     * 
@param regex
     * 
@param target
     * 
@return
     * 创建人:何杨
     * 创建日期:2009-11-5
     * 创建时间:下午03:33:41
     
*/
    
public static String getMatchedString(String regex,String target){
        Pattern pattern
=Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        
        Matcher matcher
=pattern.matcher(target);
        
        
while(matcher.find()){
            
return matcher.group(2);
        }
        
        
return null;
    }
    
    
/**
     * 测试入口
     * 
     * 
@param args
     * 创建人:何杨
     * 创建日期:2009-11-5
     * 创建时间:下午03:34:06
     
*/    
    
public static void main(String[] args){
        List
<String> ls=new ArrayList<String>();
        ls.add(
"webservice.url");
        ls.add(
"jmsbroker.url");
        
        String properitesFile
=TPClientModel.class.getResource("/remoteservice.properites").getFile().toString();
        RemotePortTestor rt
=new RemotePortTestor(properitesFile,ls);
        System.out.println(rt.testRemotePorts());
    }
}

remoteservice.properites的内容如下:
webservice.url=http://localhost:8080/SampleWebService/services/service
jmsbroker.url=tcp://192.168.0.110:61616

以上程序会自动从上述URL中找出IP地址和端口,然后用Socket连接过去看是否能联通,主要使用了正则表达式和Socket,比较简单,大家可自行阅读理解。


posted @ 2009-11-05 16:29 何杨| 编辑 收藏


代码如下:
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

/**
 * 此类用于取出本机的IP地址
 * 
 * 
@author 何杨
 * @date 2009-11-5
 * @time 上午10:41:13
 
*/
public class IPAddrFetcher{
    
public String getIPInfo(){
        StringBuilder sb
=new StringBuilder();
        
        
try{
            Enumeration
<NetworkInterface> interfaces=NetworkInterface.getNetworkInterfaces();
            
            
while(interfaces.hasMoreElements()){
                NetworkInterface ni
=interfaces.nextElement();
                
                sb.append(
"Interface "+ni.getName()+":\r\n");
                
                
                Enumeration
<InetAddress> inetAddresses=ni.getInetAddresses();
                
                
while(inetAddresses.hasMoreElements()){
                    InetAddress address
=inetAddresses.nextElement();
                    
                    sb.append(
"Address");
                    
                    
if(address instanceof Inet4Address){
                        sb.append(
"(v4)");
                    }
                    
else{
                        sb.append(
"(v6)");
                    }
                    
                    sb.append(
":address="+address.getHostAddress()+" name="+address.getHostName()+"\r\n");
                }
            }
        }
catch(Exception ex){
            ex.printStackTrace();
        }
                
        
return sb.toString();
    }
    
    
public static void main(String[] args){
        IPAddrFetcher iPAddrFetcher
=new IPAddrFetcher();
        System.out.println(iPAddrFetcher.getIPInfo());
    }
}


posted @ 2009-11-05 16:21 何杨| 编辑 收藏

JMS消息传递是一种异步过程,如果没有接受者JMS Provider应该选择将消息持久化,策略主要有文件持久化和基于数据库的持久化两种,下文是关于将未消费的消息持久化到MySql数据库的。

首先,我们要做的是将MySql数据库的驱动包放置到ActiveMQ的安装目录下的lib里。

其次,我们需要改写activemq.xml文件,它在ActiveMQ的conf目录中。具体修改部分请见下文中粗体部分:

<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You 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.
-->
<beans
  
xmlns="http://www.springframework.org/schema/beans"
  xmlns:amq
="http://activemq.apache.org/schema/core"
  xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"
>

    
<!-- Allows us to use system properties as variables in this configuration file -->
    
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        
<property name="locations">
            
<value>file:${activemq.base}/conf/credentials.properties</value>
        
</property>      
    
</bean>

    
<!-- 
        The <broker> element is used to configure the ActiveMQ broker. 
    
-->
    
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.base}/data">
        
        
<!-- 
            The managementContext is used to configure how ActiveMQ is exposed in 
            JMX. By default, ActiveMQ uses the MBean server that is started by 
            the JVM. For more information, see: 
            
            http://activemq.apache.org/jmx.html 
        
-->
        
<managementContext>
            
<managementContext createConnector="false"/>
        
</managementContext>

        
<!-- 
            Configure message persistence for the broker. The default persistence
            mechanism is the KahaDB store (identified by the kahaDB tag). 
            For more information, see: 
            
            http://activemq.apache.org/persistence.html 
        
-->
        
<persistenceAdapter>
            
<jdbcPersistenceAdapter dataSource="#mysqlDataSource"/>
        
</persistenceAdapter>        
        
<!--
            For better performances use VM cursor and small memory limit.
            For more information, see:
            
            http://activemq.apache.org/message-cursors.html
            
            Also, if your producer is "hanging", it's probably due to producer flow control.
            For more information, see:
            http://activemq.apache.org/producer-flow-control.html
        
-->
              
        
<destinationPolicy>
            
<policyMap>
              
<policyEntries>
                
<policyEntry topic=">" producerFlowControl="true" memoryLimit="1mb">
                  
<pendingSubscriberPolicy>
                    
<vmCursor />
                  
</pendingSubscriberPolicy>
                
</policyEntry>
                
<policyEntry queue=">" producerFlowControl="true" memoryLimit="1mb">
                  
<!-- Use VM cursor for better latency
                       For more information, see:
                       
                       http://activemq.apache.org/message-cursors.html
                       
                  <pendingQueuePolicy>
                    <vmQueueCursor/>
                  </pendingQueuePolicy>
                  
-->
                
</policyEntry>
              
</policyEntries>
            
</policyMap>
        
</destinationPolicy> 
 
         
<!--
            The systemUsage controls the maximum amount of space the broker will 
            use before slowing down producers. For more information, see:
            
            http://activemq.apache.org/producer-flow-control.html
             
        <systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage limit="20 mb"/>
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="1 gb" name="foo"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="100 mb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>
        
-->
          
        
<!-- 
            The transport connectors expose ActiveMQ over a given protocol to
            clients and other brokers. For more information, see: 
            
            http://activemq.apache.org/configuring-transports.html 
        
-->
        
<transportConnectors>
            
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
        
</transportConnectors>

    
</broker>

    
<!-- MySql dataSource -->
    
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        
<property name="url" value="jdbc:mysql://localhost/test?relaxAutoCommit=true"/>
        
<property name="username" value="root"/>
        
<property name="password" value="hy"/>
        
<property name="poolPreparedStatements" value="true"/>
    
</bean>

    
<!-- 
        Uncomment to enable Camel
        Take a look at activemq-camel.xml for more details
         
    <import resource="camel.xml"/>
    
-->

    
<!-- 
        Enable web consoles, REST and Ajax APIs and demos
        Take a look at activemq-jetty.xml for more details 
    
-->
    
<import resource="jetty.xml"/>
    
</beans>


如上,在persistenceAdapter节点中指定mySql数据源,在broker节点外配置了bean:

    <!-- MySql dataSource -->
    
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        
<property name="url" value="jdbc:mysql://localhost/test?relaxAutoCommit=true"/>
        
<property name="username" value="root"/>
        
<property name="password" value="hy"/>
        
<property name="poolPreparedStatements" value="true"/>
    
</bean>

上面加粗的一句指明了消息存储在mysql的test数据库中,当然你可以指定成任何你想要的数据库,注意在启动ActiveMq之前这个数据库是要存在的,否则报错。另外需要赘述的一点是activemq.xml中不要有中文,看来白狗子对非英语的抵触真是无处不在,我们所有中国人应该奋发图强恢复汉唐明荣光,让异族不得不仰视我们,当然这是后话。

下面就可以启动ActiveMQ了,向队列发送几条消息后,我们可以看看数据库里发生了什么变化,如下:


上图是ActiveMQ为了持久化消息而设立的三张表。


上图是持久化到数据库的未被消费掉的消息。

如果这些待消费消息被接收后,这张表就会空空如也,如下:


你可以使用这个程序(注意包要自己导入一下)来测试一下。

以上就是将ActiveMQ中未消费的消息持久化到MySql数据库的过程,但愿对你有所帮助。
posted @ 2009-10-27 11:23 何杨| 编辑 收藏

     摘要: 如果需要将表数据转化为XML形式数据的话,如果我们使用Spring的JDBC Template,那么常需要做的工作是创建一个RowMapper匿名类,在其中将字段与领域对象的某个属性匹配上,然后得到领域对象链表形式的结果,此后展开这个集合,再将字段转化为XML数据,其中进行了两次名称和值之间的匹配,硬编码较多,比较费时间。如果我们利用Metadata(Metadata是解释数据的数据,如果我们的研...  阅读全文
posted @ 2009-10-27 10:13 何杨| 编辑 收藏

     摘要: 相对于Weblogic这种大家伙来说,在ActiveMQ5.3.0上建立队列和主题还是相对容易的,当然如果路没走对也要费一番周折,本人在此写出小文,希望能对ActiveMQ初学者有所裨益,顺便感谢网络上那些辛勤的有共享精神的ActiveMQ研究者和鄙视一下那些懒惰的有剽窃习惯的转载者。 一.下载安装ActiveMQ。 在http://activemq.apache.org/ 你可...  阅读全文
posted @ 2009-10-27 09:00 何杨| 编辑 收藏

TimesTen是一种内存数据库,与其它内存数据库不同的是它依然使用SQL作为数据库存取的手段,估计是考虑到对Oracle数据库的兼顾和对象进出方式的不成熟。它既可以作为Oracle的前端缓存使用,也可以独立使用。下面是将它作为独立数据库并使用java程序对其进行访问的情况:

一.安装TimesTen数据库
到页面“http://www.oracle.com/technology/global/cn/software/products/timesten/index.html”下载适合你的环境的安装程序,并进行安装。(注意需要注册一个账号)

二.设置TimesTen环境变量
在你机器上的[TimesTen的安装目录]\tt70_32\bin下找到ttenv。双击即可。如果要手工设置可以参见其帮助文档,这里略过。

三.建立一个TimesTen数据源
1.打开“控制面板”->“管理工具”->“数据源”
2.点击“系统DSN”选项卡,点击“添加”按钮。
3.找到“TimesTen Data Manager 7.0”一项,再点击“完成”按钮。
4.在“Data Source  Name”一项中,填入数据源名;给 “Data Store Path”指定一个目录,给“Log  Directory”指定另一个目录;指定“DataBase Character Set”为UTF-8;指定“Type Mode”为“1-TimesTen”,这是不依赖Oracle数据库的方式。具体设置请参考下图:


四.通过ttIsql建表
ttIsql是TimesTen的管理控制台,作用相当于MySql数据库的“MySQL Command Line Client”或Oracle数据库的“Sql Plus”,通过它我们可以连接到数据库并执行Sql语句。
在开始菜单中我们可以找到“ttIsql (Interactive SQL)”,点击即打开管理控制台窗口。
窗口打开后,我们可以输入命令“connect myTstDs”连接到刚才建立的数据源,之后可以输入如下语句建立一张表:
create table employee(
   id 
CHAR(4primary key not null ,
   name 
VARCHAR(200)
)

五.通过程序在employee表中建立一条记录
通过程序访问一数据库的库我们需要找到种数据库的驱动包,访问TimesTen数据库的驱动包是ttjdbc14.jar,你可以在[TimesTenan安装目录]"tt70_32"lib下找到它。

以下是程序代码,它能打开TimesTen数据库,并向刚才创建的employee表中插入一条记录:
package com.heyang;

import java.sql.Connection;
import java.sql.PreparedStatement;

import com.timesten.jdbc.TimesTenDataSource;

/**
 * 程序入口点
 * 
@author 何杨(heyang78@gmail.com)
 *
 * 
@since 2009-10-17 下午07:17:11
 * 
@version 1.00
 
*/
public class Main {
  
public static void main(String[] args) {
    
try {
      Class.forName(
"com.timesten.jdbc.TimesTenDriver");

      String url 
= "jdbc:timesten:direct:dsn=myTstDs";

      TimesTenDataSource ds 
= new TimesTenDataSource();
      ds.setUrl(url);
      Connection conn 
= ds.getConnection();
      conn.setAutoCommit(
false);
      String sql 
= "insert into employee ( id, name ) values ( ?, ?);";

      PreparedStatement pstmt 
= conn.prepareStatement(sql);
      pstmt.setString(
1"002");
      pstmt.setString(
2"heyang@gmail.com");
      pstmt.executeUpdate();
      conn.commit();

      conn.close();

    } 
catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}



posted @ 2009-10-18 07:50 何杨| 编辑 收藏

1.Oracle官方的介绍网页。

2.Oralce TimeStan的安装及体验配置,可惜是Linux上的。

3.Oracle官方TimeStan下载页面

4.一个简单的访问TimesTen数据库的例程

5.tst安装指南。
posted @ 2009-10-16 14:28 何杨| 编辑 收藏

WebService的原始API直接书写在代码中有诸多不便,如果我们把其调用过程归纳成一个类,再用Spring把URI和方法名注入到实例中去,这样就好些了。

归纳出来的WebService调用类:
package com.heyang;

import java.net.MalformedURLException;
import java.rmi.RemoteException;

import javax.xml.rpc.ServiceException;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

/**
 * WebService统一调用类
 * 
@author: 何杨(heyang78@gmail.com)
 * @date: 2009-10-10-下午11:47:56
 
*/
public class WebService{
    
private String endpoint;
    
    
private String operationName;
    
    
/**
     * 取得WebService调用的结果
     * 
@param args
     * 
@return
     * 
@throws ServiceException
     * 
@throws MalformedURLException
     * 
@throws RemoteException
     
*/
    
public Object getCallResult(Object[] args)throws ServiceException, MalformedURLException, RemoteException{
        
// 创建 Service实例
        Service service = new Service();
        
        
// 通过Service实例创建Call的实例
        Call call = (Call) service.createCall();
        
        
// 将Web Service的服务路径加入到call实例之中.
        call.setTargetEndpointAddress(new java.net.URL(endpoint));// 为Call设置服务的位置
        
        
// 调用Web Service的方法
        call.setOperationName(operationName);
        
        
// 调用Web Service,传入参数
        return call.invoke(args);
    }

    
public String getEndpoint() {
        
return endpoint;
    }

    
public void setEndpoint(String endpoint) {
        
this.endpoint = endpoint;
    }

    
public String getOperationName() {
        
return operationName;
    }

    
public void setOperationName(String operationName) {
        
this.operationName = operationName;
    }
}

再在上下文中配置三个bean,这样WebService的相关信息就变成可配置方式了:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
<bean id="method_isExist" class="com.heyang.WebService" >    
        
<property name="endpoint">
            
<value>http://localhost:8080/UserLoginService/services/login</value>
        
</property>
        
<property name="operationName">
            
<value>isExist</value>
        
</property>
    
</bean>
    
    
<bean id="method_getUserRole" class="com.heyang.WebService" >    
        
<property name="endpoint">
            
<value>http://localhost:8080/UserLoginService/services/login</value>
        
</property>
        
<property name="operationName">
            
<value>getUserRole</value>
        
</property>
    
</bean>
    
    
<bean id="method_getUserTrade" class="com.heyang.WebService" >    
        
<property name="endpoint">
            
<value>http://localhost:8080/UserLoginService/services/login</value>
        
</property>
        
<property name="operationName">
            
<value>getUserTrade</value>
        
</property>
    
</bean>
 
</beans>

调用因此也变得相对简单:
package com.heyang;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 使用Spring的简约式调用WebService
 * 
@author: 何杨(heyang78@gmail.com)
 * @date: 2009-10-10-下午11:40:49
 
*/
public class SpringTest{
    
public static void main(String[] args){
        
try{
            ApplicationContext appContext 
= new ClassPathXmlApplicationContext("bean.xml");
            Object[] params
=new Object[] { "MT001","123" };
            
            WebService ws1
=(WebService)appContext.getBean("method_isExist");
            WebService ws2
=(WebService)appContext.getBean("method_getUserRole");
            WebService ws3
=(WebService)appContext.getBean("method_getUserTrade");
            
            System.out.println(ws1.getCallResult(params));
            System.out.println(ws2.getCallResult(params));
            System.out.println(ws3.getCallResult(params));
        }
        
catch(Exception ex){
            ex.printStackTrace();
        }
    }
}

代码下载(jar请从前面的程序里找,WebService即用上一篇文章中的UserLoginService):
http://www.blogjava.net/Files/heyang/UserLoginServiceTest20091011082831.rar
posted @ 2009-10-11 00:10 何杨 阅读(4261) | 评论 (1)编辑 收藏

参考文章一:
使用Axis开发Web Service程序
它对初学者有所帮助

参考文章二:
在axis中通过wsdd文件发布和卸载webservice
这篇文章披露了一些wsdd文件的细节,有一定参考价值。

下面是一个Axis的Web Service程序实例及测试程序:
http://www.blogjava.net/Files/heyang/userloginWebService20091010232908.rar
注意为了减少体积lib目录中的jar都被删除了,你可以从http://www.blogjava.net/Files/heyang/SerialNumber20090929130453.rar 这个工程的lib目录中找到所需要的所有jar包。

希望能对大家有所帮助。

posted @ 2009-10-10 23:34 何杨| 编辑 收藏

仅列出标题
共28页: First 上一页 17 18 19 20 21 22 23 24 25 下一页 Last