Apache对象池插件common-pool学习小结
2015-12-22 14:42
525 查看
一、背景
对于使用面向对象语言开发软件的童鞋们都知道,对象是一个十分重要的概念,用Thinking in Java绪论里面的话说:一切皆是对象。
因为对象的重要性,所以在某些大型的应用系统中,对象会被频繁的创建并使用,这就会导致开发人员需要对系统的性能进行调优,特别是在系统耗时方法更是需要着重优化。幸好,有Apache这样一个组织,给奋斗在第一线的广大IT民工提供了这样一个好使的工具:common-pool。
Commons-pool是一个apache开源组织下的众多项目的一个,其原理很简单:创建一个对象池,将一定数量的对象缓存到这个对象池中,需要使用时直接从对象池中取出对象,使用完后将对象扔回到对象池中即可。下面介绍咱们今天的主角——common-pool。
二、common-pool组件简单说明
common-pool提供的对象池主要有两种:一种是带Key的对象池,这种带Key的对象池是把相同的池对象放在同一个池中,也就是说有多少个key就有多少个池;另一种是不带Key的对象池,这种对象池是把生产完全一致的对象放在同一个池中,但是有时候,单用对池内所有对象一视同仁的对象池,并不能解决的问题,例如:对于一组某些参数设置不同的同类对象——比如一堆指向不同地址的 java.net.URL对象或者一批代表不同语句的java.sql.PreparedStatement对象,用这样的方法池化,就有可能取出不合用的对象。
common-pool给带Key的对象池提供了三类对象:KeyedObjectPool、KeyedPoolableObjectFactory、KeyedObjectPoolFactory;给不带Key的对象池同样提供了三个接口:ObjectPool、PoolableObjectFactory、ObjectPoolFactory。这两组接口中的每个接口的功能都是相同的,即PoolableObjectFactory或KeyedPoolableObjectFactory用于管理被池化对象的产生,激活,挂起,检验和销毁;ObjectPool或KeyedObjectPool用于管理要被池化的对象的接触和归还,并通过PoolableObjectFactory完成相应的操作;ObjectPoolFactory或KeyedObjectPoolFactory作为对应ObjectPool或KeyedObjectPool的工厂,里边有createPool()方法,用于大量生成相同类型和设置的池。
三、common-pool实例
下面通过一个例子具体说明不带Key和带Key这两种对象池的区别:
1. 实体类
/**
* 实体对象类
*/
public class MyBaseObject {
private int NumOfGetObjectFormPool ; //记录从池中取出的对象
private boolean activeFlag = false;//对象激活状态,默认不激活
public MyBaseObject(){
activeFlag = true ;
System.out.println("Object is activited....");
}
public int getNumOfGetObjectFormPool() {
return NumOfGetObjectFormPool;
}
public void setNumOfGetObjectFormPool(int numOfGetObjectFormPool) {
NumOfGetObjectFormPool = numOfGetObjectFormPool;
}
public boolean isActiveFlag() {
return activeFlag;
}
public void setActiveFlag(boolean activeFlag) {
this.activeFlag = activeFlag;
}
}
2. 不带Key的工厂类
import org.apache.commons.pool.PoolableObjectFactory;
import com.zh.exception.MyException;
/**
* 管理池里对象的产生,激活,挂起,检验和销毁的工厂类
* 不带Key的池工厂
*/
@SuppressWarnings("rawtypes")
public class PoolableFactoryWithoutKey implements PoolableObjectFactory{
//激活对象
public void activateObject(Object obj) throws MyException{
((MyBaseObject)obj).setActiveFlag(true);
}
//销毁被破坏的对象
public void destroyObject(Object obj) throws MyException{
obj = null ;
}
//创建对象
public Object makeObject() throws MyException{
return new MyBaseObject();
}
//挂起对象
public void passivateObject(Object obj) throws MyException{
((MyBaseObject)obj).setActiveFlag(false);
}
//验证该对象是否安全
public boolean validateObject(Object obj){
if(((MyBaseObject)obj).isActiveFlag()){
return true ;
}
return false;
}
}
3. 带Key的工厂类
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import com.zh.exception.MyException;
/**
* 管理池里对象的产生,激活,挂起,检验和销毁的工厂类
* 带Key的池工厂
*/
public class PoolableFactoryWithKey implements KeyedPoolableObjectFactory<String,MyBaseObject>{
//激活对象
public void activateObject(String str,MyBaseObject my_obj) throws MyException{
my_obj.setActiveFlag(true);
}
//销毁对象
public void destroyObject(String str,MyBaseObject my_obj) throws MyException{
my_obj = null ;
}
//创建对象
public MyBaseObject makeObject(String str) throws MyException{
MyBaseObject my_obj = new MyBaseObject();
my_obj.setNumOfGetObjectFormPool(0);
return my_obj;
}
//挂起对象
public void passivateObject(String str,MyBaseObject my_obj) throws MyException{
my_obj.setActiveFlag(false);
}
//验证对象是否安全
public boolean validateObject(String str ,MyBaseObject my_obj){
if(my_obj.isActiveFlag()){
return true ;
}
return false ;
}
}
4.测试类
<span style="font-size:18px;">import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import com.zh.exception.MyException;
public class CommonPoolTest {
public static void main(String[] args) throws Exception{
testCommonPoolWithoutKey();
System.out.println("不带Key的CommonPool执行结束");
System.out.println("----------------------");
testCommonPoolWithKey();
System.out.println("带Key的CommonPool执行结束");
System.out.println("----------------------");
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static void testCommonPoolWithoutKey() throws Exception{
MyBaseObject my_obj = null ;
PoolableObjectFactory factoryWithoutKey = new PoolableFactoryWithoutKey();
ObjectPool pool = new GenericObjectPool(factoryWithoutKey);
try{
for(int i=0;i<5;i++){
System.out.println("\n>>>>>>" + i + "<<<<<<");
System.out.println("对象池中处于闲置状态的对象:" + pool.getNumIdle());
//将对象池中闲置的对象取出一个
my_obj = (MyBaseObject)pool.borrowObject();
System.out.println("取出的对象:" + my_obj);
System.out.println("对象池中所有在用对象的数量:" + pool.getNumActive());
if(i % 2 == 0){//用完之后归还对象
pool.returnObject(my_obj);
System.out.println("归还的对象:" + my_obj);
}
}
}catch(MyException e){
System.out.println(e.getErrorMessage());
throw e ;
}catch(Exception e){
e.printStackTrace();
}finally{
pool.close();
}
}
private static void testCommonPoolWithKey() throws Exception{
MyBaseObject my_obj1,my_obj2,my_obj3 = null ;
KeyedPoolableObjectFactory<String, MyBaseObject> factoryWithKey =
new PoolableFactoryWithKey();
KeyedObjectPool<String, MyBaseObject> pool =
new GenericKeyedObjectPool<String,MyBaseObject>(factoryWithKey);
try{
//这里添加池对象,只需要传入key就会默认调用makeObject()方法创建一个对象
pool.addObject("A");
pool.addObject("B");
System.out.println("对象池中处于闲置状态的对象:" + pool.getNumIdle());
for(int i=0;i<5;i++){
my_obj1 = pool.borrowObject("A");//从对象池中取Key=A的对象
my_obj1.setNumOfGetObjectFormPool(my_obj1.getNumOfGetObjectFormPool() + 1);
System.out.println("A" + i + ">>>>" + my_obj1 + "<<<<" + my_obj1.getNumOfGetObjectFormPool());
my_obj2 = pool.borrowObject("B"); //从对象池中取Key=B的对象
my_obj2.setNumOfGetObjectFormPool(my_obj2.getNumOfGetObjectFormPool() + 1);
System.out.println("B" + i + ">>>>" + my_obj2 + "<<<<" + my_obj2.getNumOfGetObjectFormPool());
//如果对象池中有Key=C的闲置对象,则也会默认创建一个Key=C的池对象
my_obj3 = pool.borrowObject("C");
my_obj3.setNumOfGetObjectFormPool(my_obj3.getNumOfGetObjectFormPool() + 1);
System.out.println("C" + i + ">>>>" + my_obj3 + "<<<<" + my_obj3.getNumOfGetObjectFormPool());
if(i < 3){//用完归还对象
pool.returnObject("A", my_obj1);
pool.returnObject("B", my_obj2);
pool.returnObject("C", my_obj3);
System.out.println("归还的对象:" + my_obj1 + "," + "my_obj2" + "," + "my_obj3");
}
}
System.out.println("当前对象池中的所有对象:" + pool.getNumActive());
System.out.println("当前对象池中处于闲置状态的对象:" + pool.getNumIdle());
}catch(MyException e){
System.out.println(e.getErrorMessage());
throw e ;
}catch(Exception e){
e.printStackTrace();
}finally{
pool.close();
}
}
}</span>
5.测试结果
>>>>>>0<<<<<<
对象池中处于闲置状态的对象:0
Object is activited....
取出的对象:com.zh.learn.common.pool.MyBaseObject@73a2335d
对象池中所有在用对象的数量:1
归还的对象:com.zh.learn.common.pool.MyBaseObject@73a2335d
>>>>>>1<<<<<<
对象池中处于闲置状态的对象:1
取出的对象:com.zh.learn.common.pool.MyBaseObject@73a2335d
对象池中所有在用对象的数量:1
>>>>>>2<<<<<<
对象池中处于闲置状态的对象:0
Object is activited....
取出的对象:com.zh.learn.common.pool.MyBaseObject@717da562
对象池中所有在用对象的数量:2
归还的对象:com.zh.learn.common.pool.MyBaseObject@717da562
>>>>>>3<<<<<<
对象池中处于闲置状态的对象:1
取出的对象:com.zh.learn.common.pool.MyBaseObject@717da562
对象池中所有在用对象的数量:2
>>>>>>4<<<<<<
对象池中处于闲置状态的对象:0
Object is activited....
取出的对象:com.zh.learn.common.pool.MyBaseObject@6ff4ff23
对象池中所有在用对象的数量:3
归还的对象:com.zh.learn.common.pool.MyBaseObject@6ff4ff23
不带Key的CommonPool执行结束
----------------------
Object is activited....
Object is activited....
对象池中处于闲置状态的对象:2
A0>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<1
B0>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<1
Object is activited....
C0>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<1
归还的对象:com.zh.learn.common.pool.MyBaseObject@2b49959a,my_obj2,my_obj3
A1>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<2
B1>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<2
C1>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<2
归还的对象:com.zh.learn.common.pool.MyBaseObject@2b49959a,my_obj2,my_obj3
A2>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<3
B2>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<3
C2>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<3
归还的对象:com.zh.learn.common.pool.MyBaseObject@2b49959a,my_obj2,my_obj3
A3>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<4
B3>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<4
C3>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<4
Object is activited....
A4>>>>com.zh.learn.common.pool.MyBaseObject@73ae9565<<<<1
Object is activited....
B4>>>>com.zh.learn.common.pool.MyBaseObject@4ad25538<<<<1
Object is activited....
C4>>>>com.zh.learn.common.pool.MyBaseObject@36d8f5e8<<<<1
当前对象池中的所有对象:6
当前对象池中处于闲置状态的对象:0
带Key的CommonPool执行结束
----------------------
对于使用面向对象语言开发软件的童鞋们都知道,对象是一个十分重要的概念,用Thinking in Java绪论里面的话说:一切皆是对象。
因为对象的重要性,所以在某些大型的应用系统中,对象会被频繁的创建并使用,这就会导致开发人员需要对系统的性能进行调优,特别是在系统耗时方法更是需要着重优化。幸好,有Apache这样一个组织,给奋斗在第一线的广大IT民工提供了这样一个好使的工具:common-pool。
Commons-pool是一个apache开源组织下的众多项目的一个,其原理很简单:创建一个对象池,将一定数量的对象缓存到这个对象池中,需要使用时直接从对象池中取出对象,使用完后将对象扔回到对象池中即可。下面介绍咱们今天的主角——common-pool。
二、common-pool组件简单说明
common-pool提供的对象池主要有两种:一种是带Key的对象池,这种带Key的对象池是把相同的池对象放在同一个池中,也就是说有多少个key就有多少个池;另一种是不带Key的对象池,这种对象池是把生产完全一致的对象放在同一个池中,但是有时候,单用对池内所有对象一视同仁的对象池,并不能解决的问题,例如:对于一组某些参数设置不同的同类对象——比如一堆指向不同地址的 java.net.URL对象或者一批代表不同语句的java.sql.PreparedStatement对象,用这样的方法池化,就有可能取出不合用的对象。
common-pool给带Key的对象池提供了三类对象:KeyedObjectPool、KeyedPoolableObjectFactory、KeyedObjectPoolFactory;给不带Key的对象池同样提供了三个接口:ObjectPool、PoolableObjectFactory、ObjectPoolFactory。这两组接口中的每个接口的功能都是相同的,即PoolableObjectFactory或KeyedPoolableObjectFactory用于管理被池化对象的产生,激活,挂起,检验和销毁;ObjectPool或KeyedObjectPool用于管理要被池化的对象的接触和归还,并通过PoolableObjectFactory完成相应的操作;ObjectPoolFactory或KeyedObjectPoolFactory作为对应ObjectPool或KeyedObjectPool的工厂,里边有createPool()方法,用于大量生成相同类型和设置的池。
三、common-pool实例
下面通过一个例子具体说明不带Key和带Key这两种对象池的区别:
1. 实体类
/**
* 实体对象类
*/
public class MyBaseObject {
private int NumOfGetObjectFormPool ; //记录从池中取出的对象
private boolean activeFlag = false;//对象激活状态,默认不激活
public MyBaseObject(){
activeFlag = true ;
System.out.println("Object is activited....");
}
public int getNumOfGetObjectFormPool() {
return NumOfGetObjectFormPool;
}
public void setNumOfGetObjectFormPool(int numOfGetObjectFormPool) {
NumOfGetObjectFormPool = numOfGetObjectFormPool;
}
public boolean isActiveFlag() {
return activeFlag;
}
public void setActiveFlag(boolean activeFlag) {
this.activeFlag = activeFlag;
}
}
2. 不带Key的工厂类
import org.apache.commons.pool.PoolableObjectFactory;
import com.zh.exception.MyException;
/**
* 管理池里对象的产生,激活,挂起,检验和销毁的工厂类
* 不带Key的池工厂
*/
@SuppressWarnings("rawtypes")
public class PoolableFactoryWithoutKey implements PoolableObjectFactory{
//激活对象
public void activateObject(Object obj) throws MyException{
((MyBaseObject)obj).setActiveFlag(true);
}
//销毁被破坏的对象
public void destroyObject(Object obj) throws MyException{
obj = null ;
}
//创建对象
public Object makeObject() throws MyException{
return new MyBaseObject();
}
//挂起对象
public void passivateObject(Object obj) throws MyException{
((MyBaseObject)obj).setActiveFlag(false);
}
//验证该对象是否安全
public boolean validateObject(Object obj){
if(((MyBaseObject)obj).isActiveFlag()){
return true ;
}
return false;
}
}
3. 带Key的工厂类
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import com.zh.exception.MyException;
/**
* 管理池里对象的产生,激活,挂起,检验和销毁的工厂类
* 带Key的池工厂
*/
public class PoolableFactoryWithKey implements KeyedPoolableObjectFactory<String,MyBaseObject>{
//激活对象
public void activateObject(String str,MyBaseObject my_obj) throws MyException{
my_obj.setActiveFlag(true);
}
//销毁对象
public void destroyObject(String str,MyBaseObject my_obj) throws MyException{
my_obj = null ;
}
//创建对象
public MyBaseObject makeObject(String str) throws MyException{
MyBaseObject my_obj = new MyBaseObject();
my_obj.setNumOfGetObjectFormPool(0);
return my_obj;
}
//挂起对象
public void passivateObject(String str,MyBaseObject my_obj) throws MyException{
my_obj.setActiveFlag(false);
}
//验证对象是否安全
public boolean validateObject(String str ,MyBaseObject my_obj){
if(my_obj.isActiveFlag()){
return true ;
}
return false ;
}
}
4.测试类
<span style="font-size:18px;">import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import com.zh.exception.MyException;
public class CommonPoolTest {
public static void main(String[] args) throws Exception{
testCommonPoolWithoutKey();
System.out.println("不带Key的CommonPool执行结束");
System.out.println("----------------------");
testCommonPoolWithKey();
System.out.println("带Key的CommonPool执行结束");
System.out.println("----------------------");
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static void testCommonPoolWithoutKey() throws Exception{
MyBaseObject my_obj = null ;
PoolableObjectFactory factoryWithoutKey = new PoolableFactoryWithoutKey();
ObjectPool pool = new GenericObjectPool(factoryWithoutKey);
try{
for(int i=0;i<5;i++){
System.out.println("\n>>>>>>" + i + "<<<<<<");
System.out.println("对象池中处于闲置状态的对象:" + pool.getNumIdle());
//将对象池中闲置的对象取出一个
my_obj = (MyBaseObject)pool.borrowObject();
System.out.println("取出的对象:" + my_obj);
System.out.println("对象池中所有在用对象的数量:" + pool.getNumActive());
if(i % 2 == 0){//用完之后归还对象
pool.returnObject(my_obj);
System.out.println("归还的对象:" + my_obj);
}
}
}catch(MyException e){
System.out.println(e.getErrorMessage());
throw e ;
}catch(Exception e){
e.printStackTrace();
}finally{
pool.close();
}
}
private static void testCommonPoolWithKey() throws Exception{
MyBaseObject my_obj1,my_obj2,my_obj3 = null ;
KeyedPoolableObjectFactory<String, MyBaseObject> factoryWithKey =
new PoolableFactoryWithKey();
KeyedObjectPool<String, MyBaseObject> pool =
new GenericKeyedObjectPool<String,MyBaseObject>(factoryWithKey);
try{
//这里添加池对象,只需要传入key就会默认调用makeObject()方法创建一个对象
pool.addObject("A");
pool.addObject("B");
System.out.println("对象池中处于闲置状态的对象:" + pool.getNumIdle());
for(int i=0;i<5;i++){
my_obj1 = pool.borrowObject("A");//从对象池中取Key=A的对象
my_obj1.setNumOfGetObjectFormPool(my_obj1.getNumOfGetObjectFormPool() + 1);
System.out.println("A" + i + ">>>>" + my_obj1 + "<<<<" + my_obj1.getNumOfGetObjectFormPool());
my_obj2 = pool.borrowObject("B"); //从对象池中取Key=B的对象
my_obj2.setNumOfGetObjectFormPool(my_obj2.getNumOfGetObjectFormPool() + 1);
System.out.println("B" + i + ">>>>" + my_obj2 + "<<<<" + my_obj2.getNumOfGetObjectFormPool());
//如果对象池中有Key=C的闲置对象,则也会默认创建一个Key=C的池对象
my_obj3 = pool.borrowObject("C");
my_obj3.setNumOfGetObjectFormPool(my_obj3.getNumOfGetObjectFormPool() + 1);
System.out.println("C" + i + ">>>>" + my_obj3 + "<<<<" + my_obj3.getNumOfGetObjectFormPool());
if(i < 3){//用完归还对象
pool.returnObject("A", my_obj1);
pool.returnObject("B", my_obj2);
pool.returnObject("C", my_obj3);
System.out.println("归还的对象:" + my_obj1 + "," + "my_obj2" + "," + "my_obj3");
}
}
System.out.println("当前对象池中的所有对象:" + pool.getNumActive());
System.out.println("当前对象池中处于闲置状态的对象:" + pool.getNumIdle());
}catch(MyException e){
System.out.println(e.getErrorMessage());
throw e ;
}catch(Exception e){
e.printStackTrace();
}finally{
pool.close();
}
}
}</span>
5.测试结果
>>>>>>0<<<<<<
对象池中处于闲置状态的对象:0
Object is activited....
取出的对象:com.zh.learn.common.pool.MyBaseObject@73a2335d
对象池中所有在用对象的数量:1
归还的对象:com.zh.learn.common.pool.MyBaseObject@73a2335d
>>>>>>1<<<<<<
对象池中处于闲置状态的对象:1
取出的对象:com.zh.learn.common.pool.MyBaseObject@73a2335d
对象池中所有在用对象的数量:1
>>>>>>2<<<<<<
对象池中处于闲置状态的对象:0
Object is activited....
取出的对象:com.zh.learn.common.pool.MyBaseObject@717da562
对象池中所有在用对象的数量:2
归还的对象:com.zh.learn.common.pool.MyBaseObject@717da562
>>>>>>3<<<<<<
对象池中处于闲置状态的对象:1
取出的对象:com.zh.learn.common.pool.MyBaseObject@717da562
对象池中所有在用对象的数量:2
>>>>>>4<<<<<<
对象池中处于闲置状态的对象:0
Object is activited....
取出的对象:com.zh.learn.common.pool.MyBaseObject@6ff4ff23
对象池中所有在用对象的数量:3
归还的对象:com.zh.learn.common.pool.MyBaseObject@6ff4ff23
不带Key的CommonPool执行结束
----------------------
Object is activited....
Object is activited....
对象池中处于闲置状态的对象:2
A0>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<1
B0>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<1
Object is activited....
C0>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<1
归还的对象:com.zh.learn.common.pool.MyBaseObject@2b49959a,my_obj2,my_obj3
A1>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<2
B1>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<2
C1>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<2
归还的对象:com.zh.learn.common.pool.MyBaseObject@2b49959a,my_obj2,my_obj3
A2>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<3
B2>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<3
C2>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<3
归还的对象:com.zh.learn.common.pool.MyBaseObject@2b49959a,my_obj2,my_obj3
A3>>>>com.zh.learn.common.pool.MyBaseObject@2b49959a<<<<4
B3>>>>com.zh.learn.common.pool.MyBaseObject@6bfcc7a9<<<<4
C3>>>>com.zh.learn.common.pool.MyBaseObject@20985fa2<<<<4
Object is activited....
A4>>>>com.zh.learn.common.pool.MyBaseObject@73ae9565<<<<1
Object is activited....
B4>>>>com.zh.learn.common.pool.MyBaseObject@4ad25538<<<<1
Object is activited....
C4>>>>com.zh.learn.common.pool.MyBaseObject@36d8f5e8<<<<1
当前对象池中的所有对象:6
当前对象池中处于闲置状态的对象:0
带Key的CommonPool执行结束
----------------------
相关文章推荐
- linux下安装apache与php;Apache+PHP+MySQL配置攻略
- libexpat.a(libexpat.so.0) is needed by apache
- apahce2执行外部命令
- Apache同一台主机配置多个站点
- Apache日志分析代码大全
- 源码手动安装Apache以及配置
- Java中apache下面FTPClient主动模式和被动模式
- Linux环境下安装apache服务实例
- SVN提交代码提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir解决办法
- PHP 7 Apache 2.4 fastcgi mod_fcgid配置方法
- Apache中配置SSI
- Server——如何修改Apache默认的80端口
- CentOS Apache安装与配置
- Linux系统apache2.4环境下php7.0.0的源码安装
- java cxf org.apache.cxf.interceptor.Fault: Unmarshalling Error: null
- Apache Lucene初探
- Ubuntu下配置Apache SVN并使用SSL
- apache-phoenix F.A.Q翻译
- Ubuntu下配置Apache SSL
- Apache的压力测试以及web性能优化的常用知识总结