我的DWR之簡單實現(xiàn)
1、測試類:package mydwr.test;
import java.util.Date;
public class Single {
public String printMsg(String msg, boolean bool, int i, byte b, double d) {
String value = "msg:" + msg + ",bool:" + bool + ",int:" + i + ",byte:" + b + ",double:" + d
+ ",date:" + new Date();
return value;
}
}
import java.util.Date;
public class Single {
public String printMsg(String msg, boolean bool, int i, byte b, double d) {
String value = "msg:" + msg + ",bool:" + bool + ",int:" + i + ",byte:" + b + ",double:" + d
+ ",date:" + new Date();
return value;
}
}
2、運行效果如下:

3、核心Servlet類:
public class MyDWRServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Processor iface;
private Processor exec;
public void init(ServletConfig config) throws ServletException {
super.init(config);
Map<String, Class<?>> creators = new HashMap<String, Class<?>>();
try {
// 加載初始配置信息
ClassLoader loader = Thread.currentThread().getContextClassLoader();
creators.put("Single", loader.loadClass("mydwr.test.Single"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
iface = new InterfaceProcessor();
exec = new ExecProcessor();
iface.setCreators(creators);
exec.setCreators(creators);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException,
ServletException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException,
ServletException {
String pathInfo = req.getPathInfo();
if (pathInfo.startsWith("/interface/")) {
iface.handle(req, resp);
} else if (pathInfo.startsWith("/exec")) {
exec.handle(req, resp);
} else if (pathInfo.startsWith("/myengine.js")) {
String output = null;
StringBuffer buffer = new StringBuffer();
InputStream raw = getClass().getResourceAsStream("/mydwr/myengine.js");
BufferedReader in = new BufferedReader(new InputStreamReader(raw));
String line = null;
while ((line = in.readLine()) != null) {
buffer.append(line);
buffer.append('\n');
}
output = buffer.toString();
resp.setContentType("text/javascript");
PrintWriter out = resp.getWriter();
out.println(output);
out.flush();
}
}
}
private static final long serialVersionUID = 1L;
private Processor iface;
private Processor exec;
public void init(ServletConfig config) throws ServletException {
super.init(config);
Map<String, Class<?>> creators = new HashMap<String, Class<?>>();
try {
// 加載初始配置信息
ClassLoader loader = Thread.currentThread().getContextClassLoader();
creators.put("Single", loader.loadClass("mydwr.test.Single"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
iface = new InterfaceProcessor();
exec = new ExecProcessor();
iface.setCreators(creators);
exec.setCreators(creators);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException,
ServletException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException,
ServletException {
String pathInfo = req.getPathInfo();
if (pathInfo.startsWith("/interface/")) {
iface.handle(req, resp);
} else if (pathInfo.startsWith("/exec")) {
exec.handle(req, resp);
} else if (pathInfo.startsWith("/myengine.js")) {
String output = null;
StringBuffer buffer = new StringBuffer();
InputStream raw = getClass().getResourceAsStream("/mydwr/myengine.js");
BufferedReader in = new BufferedReader(new InputStreamReader(raw));
String line = null;
while ((line = in.readLine()) != null) {
buffer.append(line);
buffer.append('\n');
}
output = buffer.toString();
resp.setContentType("text/javascript");
PrintWriter out = resp.getWriter();
out.println(output);
out.flush();
}
}
}
4、處理基類:
public abstract class Processor {
public abstract void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException;
public void setCreators(Map<String, Class<?>> creators) {
this.creators = creators;
}
public Map<String, Class<?>> getCreators() {
return creators;
}
protected Map<String, Class<?>> creators;
}
public abstract void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException;
public void setCreators(Map<String, Class<?>> creators) {
this.creators = creators;
}
public Map<String, Class<?>> getCreators() {
return creators;
}
protected Map<String, Class<?>> creators;
}
5、接口處理類:
public class InterfaceProcessor extends Processor {
public void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pathInfo = req.getPathInfo();
String servletPath = req.getServletPath();
String script = pathInfo.replaceFirst("/interface/", "");
script = script.replaceFirst(".js", "");
Class<?> cls = creators.get(script);
String path = req.getContextPath() + servletPath;
// 輸出接口
PrintWriter out = resp.getWriter();
out.println();
out.println("function " + script + "() { }");
out.println(script + "._path = '" + path + "';");
Method[] methods = cls.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
String methodName = method.getName();
out.print('\n');
out.print(script + '.' + methodName + " = function(");
Class<?>[] paramTypes = method.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
out.print("p" + j + ", ");
}
out.println("callback) { DWREngine._execute(");
out.print(script + "._path, '" + script + "', '" + methodName + "\', ");
for (int j = 0; j < paramTypes.length; j++) {
out.print("p" + j + ", ");
}
out.println("callback);");
out.println('}');
}
out.flush();
}
}
public void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pathInfo = req.getPathInfo();
String servletPath = req.getServletPath();
String script = pathInfo.replaceFirst("/interface/", "");
script = script.replaceFirst(".js", "");
Class<?> cls = creators.get(script);
String path = req.getContextPath() + servletPath;
// 輸出接口
PrintWriter out = resp.getWriter();
out.println();
out.println("function " + script + "() { }");
out.println(script + "._path = '" + path + "';");
Method[] methods = cls.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
String methodName = method.getName();
out.print('\n');
out.print(script + '.' + methodName + " = function(");
Class<?>[] paramTypes = method.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
out.print("p" + j + ", ");
}
out.println("callback) { DWREngine._execute(");
out.print(script + "._path, '" + script + "', '" + methodName + "\', ");
for (int j = 0; j < paramTypes.length; j++) {
out.print("p" + j + ", ");
}
out.println("callback);");
out.println('}');
}
out.flush();
}
}
6、調(diào)用處理類:
public class ExecProcessor extends Processor {
private int varIndex = 0;
public void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
Call call = this.getCall(req.getMethod().equals("GET") ? parseGet(req) : parsePost(req));
Method m = findMethod(call);
Object[] params = new Object[m.getParameterTypes().length];
for (int j = 0; j < m.getParameterTypes().length; j++) {
Class<?> paramType = m.getParameterTypes()[j];
Variable var = call.variables.get("c-param" + j);
try {
params[j] = ConverterUtil.convertInbound(paramType, var);
} catch (Exception e) {
throw new ServletException("參數(shù)轉(zhuǎn)換出現(xiàn)異常", e);
}
}
Class<?> cls = creators.get(call.scriptName);
try {
Object reply = m.invoke(cls.newInstance(), params);
StringBuffer buffer = new StringBuffer();
String code = "s" + varIndex++;
buffer.append(ConverterUtil.convertOutbound(reply, code));
buffer.append('\n');
buffer.append("DWREngine._handleResponse('");
buffer.append(call.id);
buffer.append("', ");
buffer.append(code);
buffer.append(");\n");
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
out.print(buffer.toString());
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private Method findMethod(Call call) {
Class<?> cls = creators.get(call.scriptName);
for (Method m : cls.getMethods()) {
if (m.getName().equals(call.methodName)
&& m.getParameterTypes().length == call.variables.size()) {
return m;
}
}
return null;
}
private Call getCall(Map paramMap) {
Call call = new Call();
String prefix = "c-";
call.id = (String) paramMap.remove(prefix + "id");
call.scriptName = (String) paramMap.remove(prefix + "scriptName");
call.methodName = (String) paramMap.remove(prefix + "methodName");
for (Iterator it = paramMap.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
if (key.startsWith(prefix)) {
String data = (String) entry.getValue();
String[] split = data.split(":");
call.variables.put(key, new Variable(key, split[0], split[1]));
it.remove();
}
}
return call;
}
private Map parseGet(HttpServletRequest req) throws IOException {
Map paramMap = new HashMap();
Map reqMap = req.getParameterMap();
for (Iterator it = reqMap.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
String[] array = (String[]) reqMap.get(key);
if (array.length == 1) {
paramMap.put(key, array[0]);
}
}
return paramMap;
}
private Map parsePost(HttpServletRequest req) throws IOException {
Map paramMap = new HashMap();
BufferedReader in = new BufferedReader(new InputStreamReader(req.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
for (String part : line.split("&")) {
int sep = part.indexOf("=");
String key = part.substring(0, sep);
String value = part.substring(sep + 1);
paramMap.put(key, value);
}
}
return paramMap;
}
}
private int varIndex = 0;
public void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
Call call = this.getCall(req.getMethod().equals("GET") ? parseGet(req) : parsePost(req));
Method m = findMethod(call);
Object[] params = new Object[m.getParameterTypes().length];
for (int j = 0; j < m.getParameterTypes().length; j++) {
Class<?> paramType = m.getParameterTypes()[j];
Variable var = call.variables.get("c-param" + j);
try {
params[j] = ConverterUtil.convertInbound(paramType, var);
} catch (Exception e) {
throw new ServletException("參數(shù)轉(zhuǎn)換出現(xiàn)異常", e);
}
}
Class<?> cls = creators.get(call.scriptName);
try {
Object reply = m.invoke(cls.newInstance(), params);
StringBuffer buffer = new StringBuffer();
String code = "s" + varIndex++;
buffer.append(ConverterUtil.convertOutbound(reply, code));
buffer.append('\n');
buffer.append("DWREngine._handleResponse('");
buffer.append(call.id);
buffer.append("', ");
buffer.append(code);
buffer.append(");\n");
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
out.print(buffer.toString());
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private Method findMethod(Call call) {
Class<?> cls = creators.get(call.scriptName);
for (Method m : cls.getMethods()) {
if (m.getName().equals(call.methodName)
&& m.getParameterTypes().length == call.variables.size()) {
return m;
}
}
return null;
}
private Call getCall(Map paramMap) {
Call call = new Call();
String prefix = "c-";
call.id = (String) paramMap.remove(prefix + "id");
call.scriptName = (String) paramMap.remove(prefix + "scriptName");
call.methodName = (String) paramMap.remove(prefix + "methodName");
for (Iterator it = paramMap.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
if (key.startsWith(prefix)) {
String data = (String) entry.getValue();
String[] split = data.split(":");
call.variables.put(key, new Variable(key, split[0], split[1]));
it.remove();
}
}
return call;
}
private Map parseGet(HttpServletRequest req) throws IOException {
Map paramMap = new HashMap();
Map reqMap = req.getParameterMap();
for (Iterator it = reqMap.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
String[] array = (String[]) reqMap.get(key);
if (array.length == 1) {
paramMap.put(key, array[0]);
}
}
return paramMap;
}
private Map parsePost(HttpServletRequest req) throws IOException {
Map paramMap = new HashMap();
BufferedReader in = new BufferedReader(new InputStreamReader(req.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
for (String part : line.split("&")) {
int sep = part.indexOf("=");
String key = part.substring(0, sep);
String value = part.substring(sep + 1);
paramMap.put(key, value);
}
}
return paramMap;
}
}
7、類型轉(zhuǎn)換工具類:
package mydwr;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
public class ConverterUtil {
private static Map<String, Converter> converterMap = new HashMap<String, Converter>();
static {
Converter stringConv = new StringConverter();
Converter primConv = new PrimitiveConverter();
converterMap.put("boolean", primConv);
converterMap.put("byte", primConv);
converterMap.put("int", primConv);
converterMap.put("double", primConv);
converterMap.put("char", primConv);
converterMap.put("number", primConv);
converterMap.put("java.lang.Boolean", primConv);
converterMap.put("java.lang.Byte", primConv);
converterMap.put("java.lang.Integer", primConv);
converterMap.put("java.lang.Double", primConv);
converterMap.put("java.lang.Character", primConv);
converterMap.put("string", stringConv);
converterMap.put("java.lang.String", stringConv);
}
public static Object convertInbound(Class<?> paramType, Variable var) throws Exception {
Converter conv = converterMap.get(var.type);
return conv.convertInbound(paramType, var);
}
public static String convertOutbound(Object data, String varName) {
Converter conv = converterMap.get(data.getClass().getName());
return conv.convertOutbound(data, varName);
}
}
interface Converter {
Object convertInbound(Class<?> paramType, Variable var) throws Exception;
String convertOutbound(Object data, String varName);
}
class StringConverter implements Converter {
JSUtil jsUtil = JSUtil.getInstance();
public Object convertInbound(Class<?> paramType, Variable var) throws IOException {
return URLDecoder.decode(var.value, "UTF-8");
}
public String convertOutbound(Object data, String varName) {
return "var " + varName + "=\"" + jsUtil.escapeJavaScript(data.toString()) + "\";";
}
}
class PrimitiveConverter implements Converter {
JSUtil jsUtil = JSUtil.getInstance();
public Object convertInbound(Class<?> paramType, Variable var) throws Exception {
String value = var.value;
if (paramType == Boolean.TYPE || paramType == Boolean.class) {
return Boolean.valueOf(value.trim());
}
if (paramType == Byte.TYPE || paramType == Byte.class) {
if (value.length() == 0) {
byte b = 0;
return new Byte(b);
}
return new Byte(value.trim());
}
if (paramType == Short.TYPE || paramType == Short.class) {
if (value.length() == 0) {
short s = 0;
return new Short(s);
}
return new Short(value.trim());
}
if (paramType == Character.TYPE || paramType == Character.class) {
String decode = URLDecoder.decode(value.trim(), "UTF-8");
if (decode.length() == 1) {
return new Character(decode.charAt(0));
}
}
if (paramType == Integer.TYPE || paramType == Integer.class) {
if (value.length() == 0) {
return new Integer(0);
}
return new Integer(value.trim());
}
if (paramType == Long.TYPE || paramType == Long.class) {
if (value.length() == 0) {
return new Long(0);
}
return new Long(value.trim());
}
if (paramType == Float.TYPE || paramType == Float.class) {
if (value.length() == 0) {
return new Float(0);
}
return new Float(URLDecoder.decode(value.trim(), "UTF-8"));
}
if (paramType == Double.TYPE || paramType == Double.class) {
if (value.length() == 0) {
return new Double(0);
}
return new Double(URLDecoder.decode(value.trim(), "UTF-8"));
}
throw new Exception("找不到匹配的類型");
}
public String convertOutbound(Object data, String varName) {
Class<?> paramType = data.getClass();
if (data.equals(Boolean.TRUE)) {
return "var " + varName + "=true;";
} else if (data.equals(Boolean.FALSE)) {
return "var " + varName + "=false;";
} else if (paramType == Character.class) {
return "var " + varName + "=\"" + jsUtil.escapeJavaScript(data.toString()) + "\";";
} else {
return "var " + varName + '=' + data.toString() + ';';
}
}
}
import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
public class ConverterUtil {
private static Map<String, Converter> converterMap = new HashMap<String, Converter>();
static {
Converter stringConv = new StringConverter();
Converter primConv = new PrimitiveConverter();
converterMap.put("boolean", primConv);
converterMap.put("byte", primConv);
converterMap.put("int", primConv);
converterMap.put("double", primConv);
converterMap.put("char", primConv);
converterMap.put("number", primConv);
converterMap.put("java.lang.Boolean", primConv);
converterMap.put("java.lang.Byte", primConv);
converterMap.put("java.lang.Integer", primConv);
converterMap.put("java.lang.Double", primConv);
converterMap.put("java.lang.Character", primConv);
converterMap.put("string", stringConv);
converterMap.put("java.lang.String", stringConv);
}
public static Object convertInbound(Class<?> paramType, Variable var) throws Exception {
Converter conv = converterMap.get(var.type);
return conv.convertInbound(paramType, var);
}
public static String convertOutbound(Object data, String varName) {
Converter conv = converterMap.get(data.getClass().getName());
return conv.convertOutbound(data, varName);
}
}
interface Converter {
Object convertInbound(Class<?> paramType, Variable var) throws Exception;
String convertOutbound(Object data, String varName);
}
class StringConverter implements Converter {
JSUtil jsUtil = JSUtil.getInstance();
public Object convertInbound(Class<?> paramType, Variable var) throws IOException {
return URLDecoder.decode(var.value, "UTF-8");
}
public String convertOutbound(Object data, String varName) {
return "var " + varName + "=\"" + jsUtil.escapeJavaScript(data.toString()) + "\";";
}
}
class PrimitiveConverter implements Converter {
JSUtil jsUtil = JSUtil.getInstance();
public Object convertInbound(Class<?> paramType, Variable var) throws Exception {
String value = var.value;
if (paramType == Boolean.TYPE || paramType == Boolean.class) {
return Boolean.valueOf(value.trim());
}
if (paramType == Byte.TYPE || paramType == Byte.class) {
if (value.length() == 0) {
byte b = 0;
return new Byte(b);
}
return new Byte(value.trim());
}
if (paramType == Short.TYPE || paramType == Short.class) {
if (value.length() == 0) {
short s = 0;
return new Short(s);
}
return new Short(value.trim());
}
if (paramType == Character.TYPE || paramType == Character.class) {
String decode = URLDecoder.decode(value.trim(), "UTF-8");
if (decode.length() == 1) {
return new Character(decode.charAt(0));
}
}
if (paramType == Integer.TYPE || paramType == Integer.class) {
if (value.length() == 0) {
return new Integer(0);
}
return new Integer(value.trim());
}
if (paramType == Long.TYPE || paramType == Long.class) {
if (value.length() == 0) {
return new Long(0);
}
return new Long(value.trim());
}
if (paramType == Float.TYPE || paramType == Float.class) {
if (value.length() == 0) {
return new Float(0);
}
return new Float(URLDecoder.decode(value.trim(), "UTF-8"));
}
if (paramType == Double.TYPE || paramType == Double.class) {
if (value.length() == 0) {
return new Double(0);
}
return new Double(URLDecoder.decode(value.trim(), "UTF-8"));
}
throw new Exception("找不到匹配的類型");
}
public String convertOutbound(Object data, String varName) {
Class<?> paramType = data.getClass();
if (data.equals(Boolean.TRUE)) {
return "var " + varName + "=true;";
} else if (data.equals(Boolean.FALSE)) {
return "var " + varName + "=false;";
} else if (paramType == Character.class) {
return "var " + varName + "=\"" + jsUtil.escapeJavaScript(data.toString()) + "\";";
} else {
return "var " + varName + '=' + data.toString() + ';';
}
}
}
8、調(diào)用實體類:
package mydwr;
import java.util.HashMap;
import java.util.Map;
public class Call {
String id = null;
String scriptName = null;
String methodName = null;
Map<String, Variable> variables = new HashMap<String, Variable>();
}
class Variable {
String key;
String type;
String value;
public Variable(String key, String type, String value) {
this.key = key;
this.type = type;
this.value = value;
}
}
import java.util.HashMap;
import java.util.Map;
public class Call {
String id = null;
String scriptName = null;
String methodName = null;
Map<String, Variable> variables = new HashMap<String, Variable>();
}
class Variable {
String key;
String type;
String value;
public Variable(String key, String type, String value) {
this.key = key;
this.type = type;
this.value = value;
}
}
9、精簡之后的引擎JS:





















































































































































































































































10、點擊此處下載源代碼