DWR的簡單實現

前段時間給一個同學做一個畢業設計,由於要求只能用jsp/servlet實現。用慣了dwr框架,於是自己模仿了下DWR的實現:

簡單的模仿了下DWR框架的實現:

這是MyDwrServlet.java源碼:

package com.xcy.core.web.dwr;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


/**
 * @author Siuon
 *
 */
@SuppressWarnings("all")
public class MyDWRServlet extends HttpServlet{
	/**
	 * serialVersionUID
	 */
	private final long serialVersionUID = 1L;
	private final String RT = "\r\n"; 
	private final String TAB = "\t"; 
	private String CONTEXT_PATH = null;
	private HashMap<String,JSClassMapping> jsAndClassMapping = new HashMap<String,JSClassMapping>();
	private StringBuffer engineFileContent;
	
	public MyDWRServlet(){
		//System.out.println("MyDWRServlet Constructor");
	}
	
	@Override
	public void init() throws ServletException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = null;
		try {
			builder = factory.newDocumentBuilder();
			Document document = builder.parse(new File(this.getServletContext().getRealPath("/WEB-INF/mydwr.xml")));
			Element root = document.getDocumentElement();
			Element allow = (Element)root.getElementsByTagName("allow").item(0);
			NodeList creates = allow.getElementsByTagName("create");
			for (int i = 0; i < creates.getLength(); i++) {
				Element create = (Element)creates.item(i);
				String javascript = create.getAttribute("javascript");
				String clazz = create.getAttribute("class");
				Class c = Class.forName(clazz);
				jsAndClassMapping.put(javascript, new JSClassMapping(javascript, c, c.newInstance()));
			}
			
			BufferedReader reader = new BufferedReader(new InputStreamReader(MyDWRServlet.class.getResourceAsStream("engine.js")));
			String line = null;
			engineFileContent = new StringBuffer();
			while((line=reader.readLine())!=null){
				engineFileContent.append(line+RT);
			}
			reader.close();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		CONTEXT_PATH = req.getContextPath()+"/mydwr/interface/";
		String requestURI = req.getRequestURI();
		if(!requestURI.endsWith(".js")) return;
		String jsName = requestURI.substring(CONTEXT_PATH.length(), requestURI.length()-3);
		if("engine".equals(jsName)){
			write(resp, engineFileContent.toString());
			return;
		}
		
		JSClassMapping jsClassMapping = jsAndClassMapping.get(jsName);
		if(jsClassMapping==null) return;
		
		try {
			if(jsClassMapping.getJsFileContent()==null){
				Class c = jsClassMapping.getClazz();
				Type[] types = c.getGenericInterfaces();
				if(types.length==0){
					throw new RuntimeException(c.getClass()+"必須實現一個接口!");
				}
				Class intface = (Class)types[0];
				Method[] methods = intface.getDeclaredMethods();
				
				StringBuffer jsFileContent = new StringBuffer("var mydwr = null;"+RT); 
				jsFileContent.append("if(mydwr==null){mydwr=new MyDWR();};"+RT);
				jsFileContent.append("var "+jsName+" = null;"+RT);
				jsFileContent.append("if(null=="+jsName+"){"+jsName+"={};};"+RT);
				StringBuffer functionBody = new StringBuffer();
				for (int i = 0; i < methods.length; i++) {
					functionBody.setLength(0);
					Method method = methods[i];
					functionBody.append(jsName+"."+methods[i].getName()+"=function(");
					Class[] params = method.getParameterTypes();
					StringBuffer paramArrayStr = new StringBuffer("[");
					for (int j = 0; j < params.length; j++) {
						if(j==0){
							functionBody.append("p"+j);
							paramArrayStr.append("p"+j);
						}else{
							functionBody.append(",p"+j);
							paramArrayStr.append(",p"+j);
						}
					}
					paramArrayStr.append("];");
					if(params.length!=0){
						functionBody.append(",");
					}
					functionBody.append("callback){"+RT);
					functionBody.append(TAB+"var params = "+paramArrayStr+RT);
					functionBody.append(TAB+"mydwr.request('"+CONTEXT_PATH+"','"+jsName+"','"+method.getName()+"',params,callback);"+RT);
					functionBody.append("}"+RT);
					jsFileContent.append(functionBody);
				}
				jsClassMapping.setJsFileContent(jsFileContent);
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		}finally{
			if(jsClassMapping.getJsFileContent()!=null){
				write(resp,jsClassMapping.getJsFileContent().toString());
			}
		}
	}
	
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		Map<String,Object> params = (Map<String,Object>)req.getParameterMap();
		List<String> paramValues = new ArrayList<String>();
		for (int i = 0; i < params.size(); i++) {
			paramValues.add(req.getParameter("p"+i));
		} 
		String clazzAndMethod = req.getRequestURI().substring(CONTEXT_PATH.length());
		String className = clazzAndMethod.split("!")[0];
		String methodName = clazzAndMethod.split("!")[1];
		JSClassMapping jsClassMapping = jsAndClassMapping.get(className);
		Method[] methods = jsClassMapping.getClazz().getDeclaredMethods();
		Method method = null;
		for (int i = 0; i < methods.length; i++) {
			if(methods[i].getName().equals(methodName)){
				method = methods[i];
				break;
			}
		}
		Class[] types = method.getParameterTypes();
		Object[] values = new Object[paramValues.size()]; 
		for (int i = 0; i < types.length; i++) {
			if("Integer".equals(types[i].getSimpleName())){
				values[i] = Integer.parseInt(paramValues.get(i));
			}else if("Double".equals(types[i].getSimpleName())){
				values[i] = Double.parseDouble(paramValues.get(i));
			}else{
				values[i] = paramValues.get(i);
				//其它類型當String處理.
			}
		}
		Object result = null;
		try {
			result = method.invoke(jsClassMapping.getObjct(), values);
		} catch (Exception e) {
			result = e.getMessage();
			e.printStackTrace();
		}
		processResult(resp,result);
	}

	/**
	 * 處理調用方法後的結果,針對不同類型返回值,分別處理。
	 * @param resp
	 * @param result
	 * @throws IOException
	 */
	private void processResult(HttpServletResponse resp,Object result) throws IOException {
		StringBuffer temp = new StringBuffer("[");
		if(result instanceof Object[]){
			Object[] objs = (Object[])result;
			for (int i = 0; i < objs.length; i++) {
				temp.append("'"+objs[i]+"'");
				if(i!=objs.length-1){
					temp.append(",");
				}
			}
			temp.append("]");
			result = temp.toString();
		}else if(result instanceof List){
			List list = (List)result;
			for (int i = 0; i < list.size(); i++) {
				Object el = list.get(i);
				if(el instanceof Map){
					temp.append("{");
					Map map = (Map)el;
					Set<Map.Entry<Object,Object>> sets = map.entrySet();
					for(Map.Entry<Object,Object> entry : sets){
						Object value = entry.getValue()==null?"":entry.getValue();
						temp.append("'"+entry.getKey()+"':'" + value +"',");
					}
					temp.replace(temp.length()-1, temp.length(), "}");;
				}else{
					temp.append("'"+list.get(i)+"'");
				}
				if(i!=list.size()-1){
					temp.append(",");
				}
			}
			result = temp.append("]");
		}else if(result instanceof Map){
			temp = new StringBuffer("{");
			Map map = (Map)result;
			Set<Map.Entry<Object,Object>> sets = map.entrySet();
			for(Map.Entry<Object,Object> entry : sets){
				Object value = entry.getValue()==null?"":entry.getValue();
				temp.append("'"+entry.getKey()+"':'" + value +"',");
			}
			temp.replace(temp.length()-1, temp.length(), "}");;
			result = temp.toString();
		}else{
			//其它類型一律作爲String
			result = "'"+result+"'";
		}
		write(resp,result.toString());
	}

	private void write(HttpServletResponse resp,String content) throws IOException{
		OutputStream os = resp.getOutputStream();
		os.write(content.getBytes("UTF-8"));
		os.flush();
		os.close();
	}
	
}
engine.js

function MyDWR(){}
MyDWR.prototype.request = function(context,className,methodName,params,callback){
	var queryContent = "";
	if(params.length){
		for(var i=0;i<params.length;i++){
			if(i==0){
				queryContent+="p"+i+"="+params[i];
			}else{
				queryContent+="&p"+i+"="+params[i];
			}
		}
	}
	var xmlHttpRequest;
	// 生成ajax引擎
	if (window.XMLHttpRequest) { // Mozilla 瀏覽器
		xmlHttpRequest = new XMLHttpRequest();
	} else if (window.ActiveXObject) { // IE瀏覽器
		try {
			xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {
			}
		}
	}
	xmlHttpRequest.open("POST",context+className+"!"+methodName,true);
	xmlHttpRequest.onreadystatechange = function(){
		if (xmlHttpRequest.readyState == 4) { // 判斷對象狀態
			if (xmlHttpRequest.status == 200) { // 信息已經成功返回,開始處理信息
				//prompt("DWR Return:",xmlHttpRequest.responseText);
				var datas = undefined;
				try{
					eval("datas = "+xmlHttpRequest.responseText+";");
				}catch(e){
					alert("DWR Error:"+e.message);
					datas = {};
				}
				callback.success(datas);
			} else { // 頁面不正常
				eval("var datas = "+xmlHttpRequest.responseText+";");
				callback.errorHandler(datas);
			}
		}
	};
	xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	xmlHttpRequest.send(queryContent);
}
MyDWR.prototype.hello=function(){
	alert("Hello MyDWR");
}


源碼下載地址:

MyDwr源碼下載

發佈了35 篇原創文章 · 獲贊 38 · 訪問量 55萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章