SpringMVC 攔截class,method註解可替換方法

@Controller
@RequestMapping(value="/document")
public class DocumentController{
    private final Logger logger = LoggerFactory.getLobber(DocumentController.class);
    
    @Autowired
    private JsonUtils jsonUtils;
    
    @Value("${onlinedoc.scan.package}")
    String packageName;
    
    @RequestMapping(value="{class}/{method}",method=Request.GET)
    public String action(@PathVariable String clazz,@PathVariable String method,Model model,HttpServletRequest req) throws ClassNotFoundException{
        Class<?> cl = null;
        try{
            cl = Class.forName(packageName + clazz);
        } catch (ClassNotFoundException e){
            logger.error("找不到指定的類:" + clazz,e);
        }
        
        String mainPath = "";
        if (null != cl){
            RequestMapping requestMapping = cl.getAnnotation(RequestMapping.class);
            mainPath = requestMapping.value()[0];
        }
        
        Method[] methods = cl.getMethods[];
        Description description = null;
        Method thisMethod = null;
        RequestMapping methodMapping = null;
        for (Method m : methods){
            if (m.getName().equals(method)){
                thisMethod = m;
                description = m.getAnnotation(Description.class);
                methodMapping = m.getAnnotation(RequestMapping.class);
            }
        }
        
        if (null == thisMethod){
            return "action";
        }
        
        String genericClassName = null;
        Type[] types = thisMethod.getGenericParameterTypes();
        for (Type type : types){
            if (type instanceof ParameterizedType){
                ParameterizedType paramType = (ParameterizedType)type;
                Type genericType = paramType.getActualTypeArguments{}[0];
                genericClassname = genericType.toString().subString(6);
            }
        }
        
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        if (null != genericClassName){
            Field[] fields = Class.forName(genericClassName).getDeclaredFields();
            for (Field param : fields){
                Map<String,Obejct> map = new HashMap<String,Obejct>();
                map.put("type",param.getType().getName());
                if (map.get("type").equals("java.util.Date")){
                    map.put("value","2015-04-25 12:00:00");
                } else {
                    map.put("value","");
                }
                
                map.put("name",param.getName());
                Description.Name name = param.getAnnotation(Description.Name.class);
                if (null == name){
                    logger.warn("Field missing Annotation @Description.Name");
                }
                map.put("description",name == null ? "":name.value());
                NotNull notNull = param.getAnnotation(NotNull.class);
                NotBlank notBlank = param.getAnnotation(NotBlank.class);
                Length length = param.getAnnotation(Length.class);
                String limit = "";
                if (null != length){
                    limit = "最小" + length.min() + "位,最大" + length.max() + "位";            
                }                    
                map.put("limit",limit);
                map.put("notNull",notNull != null || notBlank != null);
                list.add(map);                 
            }
        }
        
        ChangeLog changeLog = thisMethod.getAnnotation(ChangeLog.class);
        Map<String,String> sortedLogs = new LinkedHashMap<String,String>();
        if (null != changeLog){
            Map<String,String> logs = new HashMap<String,String>();
            String[] values = changeLog.value();
            if (null != values && values.length > 0){
                for (String v : values){
                    Matcher m = CHANGE_LOG_PATTERN.matcher(v);
                    if (m.matches()){
                        logs.put(m.group(1),m.group(4));                        
                    }
                }                
            }
            
            if (logs.size() > 0){
                List<String> versions = new ArrayList<String>(logs.keySet());
                Collections.sort(versions,new Comparator<String>(){
                    public int compare(String o1,String o2){
                        return o2.compareTo(o1);
                    }
                }); 
                for (String v : versions){
                    sortedLogs.put(v,logs.get(v));                    
                }                 
            }  
        }        
        model.addAttribute("title",Description.value());
        model.addAttribute("params", list);
        model.addAttribute("name", mainPath + methodMapping.value()[0]);
        model.addAttribute("description", description.description());
        model.addAttribute("token", req.getParameter("token"));
        model.addAttribute("changelogs", sortedLogs);
        return "action";          
    }

    @RequestMapping(value = "{clazz}/{method}", method = RequestMethod.POST)
    @ResponseBody
    public JsonNode result(@PathVariable String clazz, @PathVariable String method, Model model        ) throws ClassNotFoundException {
        Class<?> cl = null;
        try {
            cl = Class.forName(packageName + clazz);
        } catch (ClassNotFoundException e) {
            logger.error("找不到指定的類:" + clazz, e);
        }

        Method[] methods = cl.getMethods();
        Method thisMethod = null;
        for (Method m : methods) {
            if (m.getName().equals(method)) {
                thisMethod = m;
            }
        }
        if (thisMethod == null) return null;
        Map<String, Object> mapData = new HashMap<String, Object>();
        Class<?> requestType = thisMethod.getParameterTypes()[0];
		Type requestGenericType = thisMethod.getGenericParameterTypes()[0];
        String requestStructJson;
        try {
        	Object resultStruct = describeClass(requestType, (requestGenericType instanceof                     ParameterizedType) ? (ParameterizedType)requestGenericType : null);
        	requestStructJson = jsonUtils.toJsonString(resultStruct);
        } catch (Exception e) {
        	requestStructJson = "{\"error\":\"" + e.getMessage() + "\"}";
        }
        mapData.put("request", jsonUtils.getJsonNode(requestStructJson));
        
        Class<?> returnType = thisMethod.getReturnType();
		Type returnGenericType = thisMethod.getGenericReturnType();
        String resultStructJson;
        try {
        	Object resultStruct = describeClass(returnType, (returnGenericType instanceof P                        arameterizedType) ? (ParameterizedType)returnGenericType : null);
        	resultStructJson = jsonUtils.toJsonString(resultStruct);
        } catch (Exception e) {
        	resultStructJson = "{\"error\":\"" + e.getMessage() + "\"}";
        }
        mapData.put("result", jsonUtils.getJsonNode(resultStructJson));
        return jsonUtils.getJsonNode(jsonUtils.toJsonString(mapData));
    }
    
    private Object describeClass(Class<?> clazz, ParameterizedType type) throws Exception {
	PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(clazz);
	if (pds != null && pds.length > 0) {
	Map<String, Object> map = new HashMap<String, Object>();
	for (PropertyDescriptor pd : pds) {
	    if ("class".equals(pd.getName())) {
		continue;
	    }
				
	    String description = "";
	    try {
		Field field = getFieldFromClass(clazz, pd.getName(), pd.getPropertyType());
		Description.Name name = field.getAnnotation(Description.Name.class);
		description = (name != null) ? name.value() : "";
	    } catch (NoSuchFieldException e) {
		//logger.error("NoSuchFieldException class:\"" + clazz.getName() + "\" field:\"                    " + pd.getName() + "\"");
		map.put(pd.getName(), "【沒法識別" + clazz.getName() + "】");
		continue;
	    }
	
	    if (clazz == pd.getPropertyType()) {
		map.put(pd.getName(), "【同外層結構同樣】" + description);
		continue;
	    }
				
	    if ((clazz == JsonOverHttpResponse.class || clazz == JsonOverHttpRequest.class) &&                     "body".equals(pd.getName())) {
		if (type != null) {
		    Type actualType = type.getActualTypeArguments()[0];
		    if (actualType instanceof Class) {
			Class<?> actual = (Class<?>)actualType;
			    if (actual.isPrimitive() || actual == String.class) {
		                map.put(pd.getName(), "[" + actual.getSimpleName() + "]" + desc                                        ription);
			    } else {
				map.put(pd.getName(), describeClass(actual, null));
			    }
		    } else if (actualType instanceof ParameterizedType) {
			    ParameterizedType actualType2 = (ParameterizedType)actualType;
			    Class<?> actualType2Raw = (Class<?>)actualType2.getRawType();
			    if (Pagination.class.isAssignableFrom(actualType2Raw) 
			        || List.class.isAssignableFrom(actualType2Raw)) {
				Class<?> actualType3 = (Class<?>)actualType2
				                    .getActualTypeArguments()[0];
				List<Object> list = new ArrayList<Object>(1);
				list.add(describeClass(actualType3, null));
				map.put(pd.getName(), list);
			    } else if (Map.class.isAssignableFrom(actualType2Raw)) {
				map.put(pd.getName(), "[Map]【沒法解析Map類型】" + description);
			    } else {
				map.put(pd.getName(), "【沒法識別" + clazz.getName() + "】" + de                                    scription);
			    }
			} else {
			    map.put(pd.getName(), "【沒法識別" + clazz.getName() + "】" + descri                                    ption);
			}
		    } else {
			map.put(pd.getName(), "[" + pd.getPropertyType().getSimpleName() + "]"                             + description);
		    }
		} else if ((clazz == JsonOverHttpResponseHeader.class 
		        || clazz == JsonOverHttpRequestHeader.class) 
		        && "parameters".equals(pd.getName())) {
		    Map<String, String> parameters = new HashMap<String, String>();
		    parameters.put("token", "[String]" + description);
		    map.put(pd.getName(), parameters);
		} else if (pd.getPropertyType().isPrimitive() 
		    || pd.getPropertyType().isEnum() 
		    || pd.getPropertyType() == String.class 
		    || pd.getPropertyType() == Date.class) {
		    map.put(pd.getName(), "[" + pd.getPropertyType().getSimpleName() + "]" + de                        scription);
		} else if (List.class.isAssignableFrom(pd.getPropertyType())) {
		    Type returnType = pd.getReadMethod().getGenericReturnType();
		    if (returnType instanceof ParameterizedType) {
			Class<?> actual = (Class<?>)((ParameterizedType) returnType)
			        .getActualTypeArguments()[0];
			if (clazz == actual) {
			    map.put(pd.getName(), "[List]【同外層結構同樣的列表】" + description);
			} else {
			    List<Object> list = new ArrayList<Object>(1);
			    list.add(describeClass(actual, null));
			    map.put(pd.getName(), list);
			}
		    } else {
			    map.put(pd.getName(), "[" + pd.getPropertyType().getSimpleName() +                                 "]" + description);
		    }
		} else if (Map.class.isAssignableFrom(pd.getPropertyType())) {
			map.put(pd.getName(), "[" + pd.getPropertyType().getSimpleName() + "]"                                 + "【沒法解析Map類型】"+ description);
		} else if (Number.class.isAssignableFrom(pd.getPropertyType())) {
			map.put(pd.getName(), "[" + pd.getPropertyType().getSimpleName() + "]"                                 + description);
		} else if (Object.class.isAssignableFrom(pd.getPropertyType())) {
			map.put(pd.getName(), describeClass(pd.getPropertyType(), null));
		} else {
			map.put(pd.getName(), "[" + pd.getPropertyType().getSimpleName() + "]"                                + description);
		}
	    }
    	    if (map.size() > 0) {
    	        List<String> keys = new ArrayList<String>(map.keySet());
    	        Collections.sort(keys);
    	        LinkedHashMap<String, Object> hmap = new LinkedHashMap<String, Object>(keys.size());
    	        for (String key : keys) {
    	            hmap.put(key, map.get(key));
                }
    	        map = hmap;
	    }	
	    return map;
        } 	
	return null;
    }
}