zoukankan      html  css  js  c++  java
  • 导入导出Excel工具类ExcelUtil

    前言

     

    前段时间做的分布式集成平台项目中,许多模块都用到了导入导出Excel的功能,于是决定封装一个ExcelUtil类,专门用来处理Excel的导入和导出

     

    本项目的持久化层用的是JPA(底层用hibernate实现),所以导入和导出也都是基于实体类的。

     

    在编写ExcelUtil之前,在网上查了一些资料。Java中用来处理Excel的第三方开源项目主要就是POIJXLpoi功能强大,但是比较耗资源,对于大数据量的导入导出性能不是太好;jxl功能简单,但是性能比较好。

     

    由于本项目的导入导出更多关注性能问题,而且jxl提供的功能基本也都够用了,于是选择了jxl作为支持。

     



    实战

     

    导出就是将List转化为ExcellistToExcel

    导入就是将Excel转化为ListexcelToList

     

    导入导出中会出现各种各样的问题,比如:数据源为空、有重复行等,我自定义了一个ExcelException异常类,用来处理这些问题。

     

    ExcelException

     

    1. package common.tool.excel;  
    2.   
    3. public class ExcelException extends Exception {  
    4.   
    5.     public ExcelException() {  
    6.         // TODO Auto-generated constructor stub  
    7.     }  
    8.   
    9.     public ExcelException(String message) {  
    10.         super(message);  
    11.         // TODO Auto-generated constructor stub  
    12.     }  
    13.   
    14.     public ExcelException(Throwable cause) {  
    15.         super(cause);  
    16.         // TODO Auto-generated constructor stub  
    17.     }  
    18.   
    19.     public ExcelException(String message, Throwable cause) {  
    20.         super(message, cause);  
    21.         // TODO Auto-generated constructor stub  
    22.     }  
    23.   
    24.   
    25. }  


    下面就是该文的主角ExcelUtil登场了,作为一个工具类,其内的所有方法都是静态的,方便使用。


    ExcelUitl类

     

    1. /** 
    2.  * @author     : WH 
    3.  * @group      : tgb8 
    4.  * @Date       : 2014-1-2 下午9:13:21 
    5.  * @Comments   : 导入导出Excel工具类 
    6.  * @Version    : 1.0.0 
    7.  */  
    8.   
    9. public class ExcelUtil  {  
    10.       
    11.     /** 
    12.      * @MethodName  : listToExcel 
    13.      * @Description : 导出Excel(可以导出到本地文件系统,也可以导出到浏览器,可自定义工作表大小) 
    14.      * @param list      数据源 
    15.      * @param fieldMap      类的英文属性和Excel中的中文列名的对应关系 
    16.      * 如果需要的是引用对象的属性,则英文属性使用类似于EL表达式的格式 
    17.      * 如:list中存放的都是student,student中又有college属性,而我们需要学院名称,则可以这样写 
    18.      * fieldMap.put("college.collegeName","学院名称") 
    19.      * @param sheetName 工作表的名称 
    20.      * @param sheetSize 每个工作表中记录的最大个数 
    21.      * @param out       导出流 
    22.      * @throws ExcelException 
    23.      */  
    24.     public static <T>  void   listToExcel (  
    25.             List<T> list ,  
    26.             LinkedHashMap<String,String> fieldMap,  
    27.             String sheetName,  
    28.             int sheetSize,  
    29.             OutputStream out  
    30.             ) throws ExcelException{  
    31.           
    32.           
    33.         if(list.size()==0 || list==null){  
    34.             throw new ExcelException("数据源中没有任何数据");  
    35.         }  
    36.           
    37.         if(sheetSize>65535 || sheetSize<1){  
    38.             sheetSize=65535;  
    39.         }  
    40.           
    41.         //创建工作簿并发送到OutputStream指定的地方  
    42.         WritableWorkbook wwb;  
    43.         try {  
    44.             wwb = Workbook.createWorkbook(out);  
    45.               
    46.             //因为2003的Excel一个工作表最多可以有65536条记录,除去列头剩下65535条  
    47.             //所以如果记录太多,需要放到多个工作表中,其实就是个分页的过程  
    48.             //1.计算一共有多少个工作表  
    49.             double sheetNum=Math.ceil(list.size()/new Integer(sheetSize).doubleValue());  
    50.               
    51.             //2.创建相应的工作表,并向其中填充数据  
    52.             for(int i=0; i<sheetNum; i++){  
    53.                 //如果只有一个工作表的情况  
    54.                 if(1==sheetNum){  
    55.                     WritableSheet sheet=wwb.createSheet(sheetName, i);  
    56.                     fillSheet(sheet, list, fieldMap, 0, list.size()-1);  
    57.                   
    58.                 //有多个工作表的情况  
    59.                 }else{  
    60.                     WritableSheet sheet=wwb.createSheet(sheetName+(i+1), i);  
    61.                       
    62.                     //获取开始索引和结束索引  
    63.                     int firstIndex=i*sheetSize;  
    64.                     int lastIndex=(i+1)*sheetSize-1>list.size()-1 ? list.size()-1 : (i+1)*sheetSize-1;  
    65.                     //填充工作表  
    66.                     fillSheet(sheet, list, fieldMap, firstIndex, lastIndex);  
    67.                 }  
    68.             }  
    69.               
    70.             wwb.write();  
    71.             wwb.close();  
    72.           
    73.         }catch (Exception e) {  
    74.             e.printStackTrace();  
    75.             //如果是ExcelException,则直接抛出  
    76.             if(e instanceof ExcelException){  
    77.                 throw (ExcelException)e;  
    78.               
    79.             //否则将其它异常包装成ExcelException再抛出  
    80.             }else{  
    81.                 throw new ExcelException("导出Excel失败");  
    82.             }  
    83.         }  
    84.               
    85.     }  
    86.       
    87.     /** 
    88.      * @MethodName  : listToExcel 
    89.      * @Description : 导出Excel(可以导出到本地文件系统,也可以导出到浏览器,工作表大小为2003支持的最大值) 
    90.      * @param list      数据源 
    91.      * @param fieldMap      类的英文属性和Excel中的中文列名的对应关系 
    92.      * @param out       导出流 
    93.      * @throws ExcelException 
    94.      */  
    95.     public static  <T>  void   listToExcel (  
    96.             List<T> list ,  
    97.             LinkedHashMap<String,String> fieldMap,  
    98.             String sheetName,  
    99.             OutputStream out  
    100.             ) throws ExcelException{  
    101.           
    102.         listToExcel(list, fieldMap, sheetName, 65535, out);  
    103.           
    104.     }  
    105.       
    106.       
    107.     /** 
    108.      * @MethodName  : listToExcel 
    109.      * @Description : 导出Excel(导出到浏览器,可以自定义工作表的大小) 
    110.      * @param list      数据源 
    111.      * @param fieldMap      类的英文属性和Excel中的中文列名的对应关系 
    112.      * @param sheetSize    每个工作表中记录的最大个数 
    113.      * @param response  使用response可以导出到浏览器 
    114.      * @throws ExcelException 
    115.      */  
    116.     public static  <T>  void   listToExcel (  
    117.             List<T> list ,  
    118.             LinkedHashMap<String,String> fieldMap,  
    119.             String sheetName,  
    120.             int sheetSize,  
    121.             HttpServletResponse response   
    122.             ) throws ExcelException{  
    123.           
    124.         //设置默认文件名为当前时间:年月日时分秒  
    125.         String fileName=new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()).toString();  
    126.           
    127.         //设置response头信息  
    128.         response.reset();            
    129.         response.setContentType("application/vnd.ms-excel");        //改成输出excel文件  
    130.         response.setHeader("Content-disposition","attachment; filename="+fileName+".xls" );  
    131.   
    132.         //创建工作簿并发送到浏览器  
    133.         try {  
    134.               
    135.             OutputStream out=response.getOutputStream();  
    136.             listToExcel(list, fieldMap, sheetName, sheetSize,out );  
    137.               
    138.         } catch (Exception e) {  
    139.             e.printStackTrace();  
    140.               
    141.             //如果是ExcelException,则直接抛出  
    142.             if(e instanceof ExcelException){  
    143.                 throw (ExcelException)e;  
    144.               
    145.             //否则将其它异常包装成ExcelException再抛出  
    146.             }else{  
    147.                 throw new ExcelException("导出Excel失败");  
    148.             }  
    149.         }  
    150.     }  
    151.       
    152.       
    153.     /** 
    154.      * @MethodName  : listToExcel 
    155.      * @Description : 导出Excel(导出到浏览器,工作表的大小是2003支持的最大值) 
    156.      * @param list      数据源 
    157.      * @param fieldMap      类的英文属性和Excel中的中文列名的对应关系 
    158.      * @param response  使用response可以导出到浏览器 
    159.      * @throws ExcelException 
    160.      */  
    161.     public static <T>  void   listToExcel (  
    162.             List<T> list ,  
    163.             LinkedHashMap<String,String> fieldMap,  
    164.             String sheetName,  
    165.             HttpServletResponse response   
    166.             ) throws ExcelException{  
    167.           
    168.         listToExcel(list, fieldMap, sheetName, 65535, response);  
    169.     }  
    170.       
    171.     /** 
    172.      * @MethodName          : excelToList 
    173.      * @Description             : 将Excel转化为List 
    174.      * @param in                    :承载着Excel的输入流 
    175.      * @param sheetIndex        :要导入的工作表序号 
    176.      * @param entityClass       :List中对象的类型(Excel中的每一行都要转化为该类型的对象) 
    177.      * @param fieldMap          :Excel中的中文列头和类的英文属性的对应关系Map 
    178.      * @param uniqueFields  :指定业务主键组合(即复合主键),这些列的组合不能重复 
    179.      * @return                      :List 
    180.      * @throws ExcelException 
    181.      */  
    182.     public static <T>  List<T>  excelToList(  
    183.             InputStream in,  
    184.             String sheetName,  
    185.             Class<T> entityClass,  
    186.             LinkedHashMap<String, String> fieldMap,  
    187.             String[] uniqueFields  
    188.             ) throws ExcelException{  
    189.           
    190.         //定义要返回的list  
    191.         List<T> resultList=new ArrayList<T>();  
    192.           
    193.         try {  
    194.               
    195.             //根据Excel数据源创建WorkBook  
    196.             Workbook wb=Workbook.getWorkbook(in);  
    197.             //获取工作表  
    198.             Sheet sheet=wb.getSheet(sheetName);  
    199.               
    200.             //获取工作表的有效行数  
    201.             int realRows=0;  
    202.             for(int i=0;i<sheet.getRows();i++){  
    203.                   
    204.                 int nullCols=0;  
    205.                 for(int j=0;j<sheet.getColumns();j++){  
    206.                     Cell currentCell=sheet.getCell(j,i);  
    207.                     if(currentCell==null || "".equals(currentCell.getContents().toString())){  
    208.                         nullCols++;  
    209.                     }  
    210.                 }  
    211.                   
    212.                 if(nullCols==sheet.getColumns()){  
    213.                     break;  
    214.                 }else{  
    215.                     realRows++;  
    216.                 }  
    217.             }  
    218.               
    219.               
    220.             //如果Excel中没有数据则提示错误  
    221.             if(realRows<=1){  
    222.                 throw new ExcelException("Excel文件中没有任何数据");  
    223.             }  
    224.               
    225.               
    226.             Cell[] firstRow=sheet.getRow(0);  
    227.   
    228.             String[] excelFieldNames=new String[firstRow.length];  
    229.               
    230.             //获取Excel中的列名  
    231.             for(int i=0;i<firstRow.length;i++){  
    232.                 excelFieldNames[i]=firstRow[i].getContents().toString().trim();  
    233.             }  
    234.               
    235.             //判断需要的字段在Excel中是否都存在  
    236.             boolean isExist=true;  
    237.             List<String> excelFieldList=Arrays.asList(excelFieldNames);  
    238.             for(String cnName : fieldMap.keySet()){  
    239.                 if(!excelFieldList.contains(cnName)){  
    240.                     isExist=false;  
    241.                     break;  
    242.                 }  
    243.             }  
    244.               
    245.             //如果有列名不存在,则抛出异常,提示错误  
    246.             if(!isExist){  
    247.                 throw new ExcelException("Excel中缺少必要的字段,或字段名称有误");  
    248.             }  
    249.               
    250.               
    251.             //将列名和列号放入Map中,这样通过列名就可以拿到列号  
    252.             LinkedHashMap<String, Integer> colMap=new LinkedHashMap<String, Integer>();  
    253.             for(int i=0;i<excelFieldNames.length;i++){  
    254.                 colMap.put(excelFieldNames[i], firstRow[i].getColumn());  
    255.             }   
    256.               
    257.               
    258.               
    259.             //判断是否有重复行  
    260.             //1.获取uniqueFields指定的列  
    261.             Cell[][] uniqueCells=new Cell[uniqueFields.length][];  
    262.             for(int i=0;i<uniqueFields.length;i++){  
    263.                 int col=colMap.get(uniqueFields[i]);  
    264.                 uniqueCells[i]=sheet.getColumn(col);  
    265.             }  
    266.               
    267.             //2.从指定列中寻找重复行  
    268.             for(int i=1;i<realRows;i++){  
    269.                 int nullCols=0;  
    270.                 for(int j=0;j<uniqueFields.length;j++){  
    271.                     String currentContent=uniqueCells[j][i].getContents();  
    272.                     Cell sameCell=sheet.findCell(currentContent,   
    273.                             uniqueCells[j][i].getColumn(),  
    274.                             uniqueCells[j][i].getRow()+1,   
    275.                             uniqueCells[j][i].getColumn(),   
    276.                             uniqueCells[j][realRows-1].getRow(),   
    277.                             true);  
    278.                     if(sameCell!=null){  
    279.                         nullCols++;  
    280.                     }  
    281.                 }  
    282.                   
    283.                 if(nullCols==uniqueFields.length){  
    284.                     throw new ExcelException("Excel中有重复行,请检查");  
    285.                 }  
    286.             }  
    287.   
    288.             //将sheet转换为list  
    289.             for(int i=1;i<realRows;i++){  
    290.                 //新建要转换的对象  
    291.                 T entity=entityClass.newInstance();  
    292.                   
    293.                 //给对象中的字段赋值  
    294.                 for(Entry<String, String> entry : fieldMap.entrySet()){  
    295.                     //获取中文字段名  
    296.                     String cnNormalName=entry.getKey();  
    297.                     //获取英文字段名  
    298.                     String enNormalName=entry.getValue();  
    299.                     //根据中文字段名获取列号  
    300.                     int col=colMap.get(cnNormalName);  
    301.                       
    302.                     //获取当前单元格中的内容  
    303.                     String content=sheet.getCell(col, i).getContents().toString().trim();  
    304.                       
    305.                     //给对象赋值  
    306.                     setFieldValueByName(enNormalName, content, entity);  
    307.                 }  
    308.                   
    309.                 resultList.add(entity);  
    310.             }  
    311.         } catch(Exception e){  
    312.             e.printStackTrace();  
    313.             //如果是ExcelException,则直接抛出  
    314.             if(e instanceof ExcelException){  
    315.                 throw (ExcelException)e;  
    316.               
    317.             //否则将其它异常包装成ExcelException再抛出  
    318.             }else{  
    319.                 e.printStackTrace();  
    320.                 throw new ExcelException("导入Excel失败");  
    321.             }  
    322.         }  
    323.         return resultList;  
    324.     }  
    325.       
    326.       
    327.       
    328.       
    329.       
    330.     /*<-------------------------辅助的私有方法----------------------------------------------->*/  
    331.     /** 
    332.      * @MethodName  : getFieldValueByName 
    333.      * @Description : 根据字段名获取字段值 
    334.      * @param fieldName 字段名 
    335.      * @param o 对象 
    336.      * @return  字段值 
    337.      */  
    338.     private static  Object getFieldValueByName(String fieldName, Object o) throws Exception{  
    339.           
    340.         Object value=null;  
    341.         Field field=getFieldByName(fieldName, o.getClass());  
    342.           
    343.         if(field !=null){  
    344.             field.setAccessible(true);  
    345.             value=field.get(o);  
    346.         }else{  
    347.             throw new ExcelException(o.getClass().getSimpleName() + "类不存在字段名 "+fieldName);  
    348.         }  
    349.           
    350.         return value;  
    351.     }  
    352.       
    353.     /** 
    354.      * @MethodName  : getFieldByName 
    355.      * @Description : 根据字段名获取字段 
    356.      * @param fieldName 字段名 
    357.      * @param clazz 包含该字段的类 
    358.      * @return 字段 
    359.      */  
    360.     private static Field getFieldByName(String fieldName, Class<?>  clazz){  
    361.         //拿到本类的所有字段  
    362.         Field[] selfFields=clazz.getDeclaredFields();  
    363.           
    364.         //如果本类中存在该字段,则返回  
    365.         for(Field field : selfFields){  
    366.             if(field.getName().equals(fieldName)){  
    367.                 return field;  
    368.             }  
    369.         }  
    370.           
    371.         //否则,查看父类中是否存在此字段,如果有则返回  
    372.         Class<?> superClazz=clazz.getSuperclass();  
    373.         if(superClazz!=null  &&  superClazz !=Object.class){  
    374.             return getFieldByName(fieldName, superClazz);  
    375.         }  
    376.           
    377.         //如果本类和父类都没有,则返回空  
    378.         return null;  
    379.     }  
    380.       
    381.       
    382.       
    383.     /** 
    384.      * @MethodName  : getFieldValueByNameSequence 
    385.      * @Description :  
    386.      * 根据带路径或不带路径的属性名获取属性值 
    387.      * 即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等 
    388.      *  
    389.      * @param fieldNameSequence  带路径的属性名或简单属性名 
    390.      * @param o 对象 
    391.      * @return  属性值 
    392.      * @throws Exception 
    393.      */  
    394.     private static  Object getFieldValueByNameSequence(String fieldNameSequence, Object o) throws Exception{  
    395.           
    396.         Object value=null;  
    397.           
    398.         //将fieldNameSequence进行拆分  
    399.         String[] attributes=fieldNameSequence.split("\.");  
    400.         if(attributes.length==1){  
    401.             value=getFieldValueByName(fieldNameSequence, o);  
    402.         }else{  
    403.             //根据属性名获取属性对象  
    404.             Object fieldObj=getFieldValueByName(attributes[0], o);  
    405.             String subFieldNameSequence=fieldNameSequence.substring(fieldNameSequence.indexOf(".")+1);  
    406.             value=getFieldValueByNameSequence(subFieldNameSequence, fieldObj);  
    407.         }  
    408.         return value;   
    409.           
    410.     }   
    411.       
    412.       
    413.     /** 
    414.      * @MethodName  : setFieldValueByName 
    415.      * @Description : 根据字段名给对象的字段赋值 
    416.      * @param fieldName  字段名 
    417.      * @param fieldValue    字段值 
    418.      * @param o 对象 
    419.      */  
    420.     private static void setFieldValueByName(String fieldName,Object fieldValue,Object o) throws Exception{  
    421.           
    422.             Field field=getFieldByName(fieldName, o.getClass());  
    423.             if(field!=null){  
    424.                 field.setAccessible(true);  
    425.                 //获取字段类型  
    426.                 Class<?> fieldType = field.getType();    
    427.                   
    428.                 //根据字段类型给字段赋值  
    429.                 if (String.class == fieldType) {    
    430.                     field.set(o, String.valueOf(fieldValue));    
    431.                 } else if ((Integer.TYPE == fieldType)    
    432.                         || (Integer.class == fieldType)) {    
    433.                     field.set(o, Integer.parseInt(fieldValue.toString()));    
    434.                 } else if ((Long.TYPE == fieldType)    
    435.                         || (Long.class == fieldType)) {    
    436.                     field.set(o, Long.valueOf(fieldValue.toString()));    
    437.                 } else if ((Float.TYPE == fieldType)    
    438.                         || (Float.class == fieldType)) {    
    439.                     field.set(o, Float.valueOf(fieldValue.toString()));    
    440.                 } else if ((Short.TYPE == fieldType)    
    441.                         || (Short.class == fieldType)) {    
    442.                     field.set(o, Short.valueOf(fieldValue.toString()));    
    443.                 } else if ((Double.TYPE == fieldType)    
    444.                         || (Double.class == fieldType)) {    
    445.                     field.set(o, Double.valueOf(fieldValue.toString()));    
    446.                 } else if (Character.TYPE == fieldType) {    
    447.                     if ((fieldValue!= null) && (fieldValue.toString().length() > 0)) {    
    448.                         field.set(o, Character    
    449.                                 .valueOf(fieldValue.toString().charAt(0)));    
    450.                     }    
    451.                 }else if(Date.class==fieldType){  
    452.                     field.set(o, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(fieldValue.toString()));  
    453.                 }else{  
    454.                     field.set(o, fieldValue);  
    455.                 }  
    456.             }else{  
    457.                 throw new ExcelException(o.getClass().getSimpleName() + "类不存在字段名 "+fieldName);  
    458.             }  
    459.     }  
    460.       
    461.       
    462.     /** 
    463.      * @MethodName  : setColumnAutoSize 
    464.      * @Description : 设置工作表自动列宽和首行加粗 
    465.      * @param ws 
    466.      */  
    467.     private static void setColumnAutoSize(WritableSheet ws,int extraWith){  
    468.         //获取本列的最宽单元格的宽度  
    469.         for(int i=0;i<ws.getColumns();i++){  
    470.             int colWith=0;  
    471.             for(int j=0;j<ws.getRows();j++){  
    472.                 String content=ws.getCell(i,j).getContents().toString();  
    473.                 int cellWith=content.length();  
    474.                 if(colWith<cellWith){  
    475.                     colWith=cellWith;  
    476.                 }  
    477.             }  
    478.             //设置单元格的宽度为最宽宽度+额外宽度  
    479.             ws.setColumnView(i, colWith+extraWith);  
    480.         }  
    481.           
    482.     }  
    483.       
    484.     /** 
    485.      * @MethodName  : fillSheet 
    486.      * @Description : 向工作表中填充数据 
    487.      * @param sheet     工作表  
    488.      * @param list  数据源 
    489.      * @param fieldMap 中英文字段对应关系的Map 
    490.      * @param firstIndex    开始索引 
    491.      * @param lastIndex 结束索引 
    492.      */  
    493.     private static <T> void fillSheet(  
    494.             WritableSheet sheet,  
    495.             List<T> list,  
    496.             LinkedHashMap<String,String> fieldMap,  
    497.             int firstIndex,  
    498.             int lastIndex  
    499.             )throws Exception{  
    500.           
    501.         //定义存放英文字段名和中文字段名的数组  
    502.         String[] enFields=new String[fieldMap.size()];  
    503.         String[] cnFields=new String[fieldMap.size()];  
    504.           
    505.         //填充数组  
    506.         int count=0;  
    507.         for(Entry<String,String> entry:fieldMap.entrySet()){  
    508.             enFields[count]=entry.getKey();  
    509.             cnFields[count]=entry.getValue();  
    510.             count++;  
    511.         }  
    512.         //填充表头  
    513.         for(int i=0;i<cnFields.length;i++){  
    514.             Label label=new Label(i,0,cnFields[i]);  
    515.             sheet.addCell(label);  
    516.         }  
    517.           
    518.         //填充内容  
    519.         int rowNo=1;  
    520.         for(int index=firstIndex;index<=lastIndex;index++){  
    521.             //获取单个对象  
    522.             T item=list.get(index);  
    523.             for(int i=0;i<enFields.length;i++){  
    524.                 Object objValue=getFieldValueByNameSequence(enFields[i], item);  
    525.                 String fieldValue=objValue==null ? "" : objValue.toString();  
    526.                 Label label =new Label(i,rowNo,fieldValue);  
    527.                 sheet.addCell(label);  
    528.             }  
    529.               
    530.             rowNo++;  
    531.         }  
    532.           
    533.         //设置自动列宽  
    534.         setColumnAutoSize(sheet, 5);  
    535.     }  
    536.       
    537. }  


    该工具类有4个重载的导出方法和1个导入方法,大家可以根据实际情况进行选择。

     

    总结

    导入和导出方法都是通过传一个fieldMap参数(类的英文属性和Excel的中文列头的对应关系)来连接实体类和Excel

    导出的时候可以选择导出到本地文件系统或导出到浏览器,也可以自定义每个工作表的大小

    导入的时候可以自定义业务主键组合uniqueFields,这样就可以检测Excel中是否有重复行了

     

    转自他人!!!!

  • 相关阅读:
    PHP对URL传递的参数值进行编码和解码
    PHP 获取表单【2/2】
    PHP 获取表单【1/2】
    utf8 和 utf-8区别
    PHP 乘法口诀表
    PHP 插入和获取后台数据
    点击复制
    php网盘
    memcached-session-manager配置
    Apache Http Server与Tomcat6 的负载均衡(二)
  • 原文地址:https://www.cnblogs.com/zhoushihui/p/6020176.html
Copyright © 2011-2022 走看看