java递归查看对象构造的小工具

java递归查看对象结构的小工具
问题描述:
分布式集群,同步session问题,引发查看session中序列化对象结构查看问题

初步解决方案:code说明,如有可改进部分请给予帮助,谢谢
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpSession;

/**
* Detect the complex object structure
* Note: this is just a test, it should enhance in the future or you  give assistance
* @version  beta
* @author ScottXu
*
*/
public class SessionUtilWriteLogInFile {
//recursive max level, ensure not out of memory
private static int LEVEL = 30;

private static SessionUtilWriteLogInFile util = new SessionUtilWriteLogInFile();

public static SessionUtilWriteLogInFile getInstance(){
return util;
}

/**
* detect the session attribute structure
* @param session destination session
* @param logFilePath log file path  like c:/
* @throws IOException
*/
@SuppressWarnings("unchecked")
public void literaSession(HttpSession session, String logFilePath) throws IOException{
File file = new File(logFilePath+session.getId()+"_"+System.currentTimeMillis()+".txt");
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);

Enumeration<String> sessionKeys=session.getAttributeNames();
fos.write("==========Begin session simple structure============================================\r\n".getBytes());
while(sessionKeys.hasMoreElements()){
String nextElement = sessionKeys.nextElement();
recusiveObj(session.getAttribute(nextElement), 0, fos);
}
fos.write("==========End session simple structure==============================================\r\n".getBytes());
fos.close();
}

/**
* detect the complex object structure
* @param obj destination complex object
* @param count format the style
* @param pFileOutputStream
* @throws IOException
*/
@SuppressWarnings("unchecked")
protected void recusiveObj(Object obj, int count, FileOutputStream pFileOutputStream) throws IOException{
if(count>LEVEL){
pFileOutputStream.write("too long, not recusive to the end[force return]\r\n".getBytes());
return;
}
String blank = "";
for(int i=0; i<count; i++){
blank+="\t";
}
if(isAPrimitiveType(obj.getClass())){
pFileOutputStream.write((blank+obj.toString()+"\r\n").getBytes());
return;
}

if(isSerializable(obj.getClass())){
pFileOutputStream.write((blank +obj.getClass().getName()+" is a Serializable class\r\n").getBytes());
}

if(obj instanceof Collection){
Iterator<?> iterator = ((Collection<?>)obj).iterator();
pFileOutputStream.write((blank+"{\r\n").getBytes());
while(iterator.hasNext()){
Object next = iterator.next();
recusiveObj(next, count+1,  pFileOutputStream);
}
pFileOutputStream.write((blank+"}\r\n").getBytes());
return;
}

if(obj instanceof Map){
Iterator<?> iter = ((Map<?,?>)obj).entrySet().iterator();
pFileOutputStream.write((blank+"{\r\n").getBytes());
while (iter.hasNext()) {
    Map.Entry<?, ?> entry = (Map.Entry<?, ?>) iter.next();
    Object key = entry.getKey();
    Object val = entry.getValue();
    pFileOutputStream.write((blank+"  "+"[key ("+key+"): value (\r\n").getBytes());
    recusiveObj(val, count+1, pFileOutputStream);
    pFileOutputStream.write((blank+"  )]\r\n").getBytes());
}
pFileOutputStream.write((blank+"}\r\n").getBytes());
return;
}

if(obj instanceof Dictionary){
Dictionary d = (Dictionary)obj;
Enumeration<?> elements = d.elements();
pFileOutputStream.write((blank+"{\r\n").getBytes());
while(elements.hasMoreElements()){
recusiveObj(elements.nextElement(), count+1, pFileOutputStream);
}
pFileOutputStream.write((blank+"}\r\n").getBytes());
return;
}

pFileOutputStream.write((blank+obj.getClass().getName()+"\r\n").getBytes());
Field[] fields = obj.getClass().getDeclaredFields();
try {
for(Field f : fields){
f.setAccessible(true);
recusiveObj(f.get(obj), count+1, pFileOutputStream);
}
} catch (Exception e){
e.printStackTrace();
}

}

/**
* adjust the clazz is primitive type, if primitive type, we should end the recursive and do what we want to do, may be print or log
* @param clazz
* @return
*/
private  boolean isAPrimitiveType(Class<?> clazz)
  {
    if (clazz == Boolean.TYPE) {
      return true;
    }
    if (clazz == Character.TYPE) {
      return true;
    }
    if (clazz == Byte.TYPE) {
      return true;
    }
    if (clazz == Short.TYPE) {
      return true;
    }
    if (clazz == Integer.TYPE) {
      return true;
    }
    if (clazz == Long.TYPE) {
      return true;
    }
    if (clazz == Float.TYPE) {
      return true;
    }
    if (clazz == Double.TYPE) {
      return true;
    }
   
    if(clazz == String.class){
    return true;
    }

    return clazz == Void.TYPE;
  }
/**
* adjust if the object is implements the Serializable interface for network
* @param clazz
* @return
*/
private  boolean isSerializable(Class<?> clazz){
Class<?>[] interfaces = clazz.getInterfaces();
for(Class<?> c : interfaces){
if(c.getClass().isInstance(Serializable.class)){
return true;
}
}
return false;
}

private SessionUtilWriteLogInFile(){}

public static void main(String[] args) throws IOException {
//for instance :< the core method recusiveObj(), you could make the complex object to test>
/*Map m = new java.util.HashMap();
ComplexObject cop = new ComplexObject();
AnotherComplextOjbect a1 = new AnotherComplextOjbect("a1", "a2", "a3");
AnotherComplextOjbect b1 = new AnotherComplextOjbect("b1", "b2", "b3");
AnotherComplextOjbect c1 = new AnotherComplextOjbect("c1", "c2", "c3");
cop.setAnother(a1);
m.put("1", cop);
m.put("2", "abc");

File file = new File("c:/aaa111_"+System.currentTimeMillis()+".txt");
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
fos.write("==========Begin session simple structure============================================\r\n".getBytes());
SessionUtilWriteLogInFile.getInstance().recusiveObj(m, 0, fos);
fos.write("==========End session simple structure==============================================\r\n".getBytes());
fos.close();*/

}
}