Posted on 2011-03-03 09:44 
penngo 阅读(3573) 
评论(3)  编辑  收藏  所属分类: 
Java 
			 
			
		 
		昨天网友问了下DWR的问题,DWR是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,不过自己并未在项目中用过,只是之前在网上看过它的一些介绍,大概的了解它的调用原理。
如果要在客户端调用服务器端的java方法,一种是基于TCP协议,如RMI;另一种是基于HTTP协议,如web service、ajax。DWR就是基于ajax方式调用WEB服务器上的JAVA方法的一种。
如果是基于HTTP协议来调用,按个人理解,只需把3步做好就行了,
1、定义好访问规则,如怎样把需要调用的类名、方法名、参数提交到服务器端。
2、服务器端怎样按收客户端传类名、方法名、参数;接收到数据后,怎样实例化该类和执行指定的方法。
3、服务器把处理结果以什么形式返回给客户端。
和网友说着来了兴趣,回家顺便写了个实现尝试下。
下面开始按上面的原理步骤写一个简单的实现例子
1、类名、方法名、参数通过ajax方式pose到服务器端RemoteServlet,本文直接使用jquery的ajax
ScriptEngine.js,

 function getRootPath()
function getRootPath() {
{
 var strFullPath=window.document.location.href;
    var strFullPath=window.document.location.href;
 var strPath=window.document.location.pathname;
    var strPath=window.document.location.pathname;
 var pos=strFullPath.indexOf(strPath);
    var pos=strFullPath.indexOf(strPath);
 var prePath=strFullPath.substring(0,pos);
    var prePath=strFullPath.substring(0,pos);
 var postPath=strPath.substring(0,strPath.substr(1).indexOf('/')+1);
    var postPath=strPath.substring(0,strPath.substr(1).indexOf('/')+1);
 return(prePath+postPath);
    return(prePath+postPath);
 }
    }

 function ScriptEngine()
function ScriptEngine() {
{
 this.name = "";
    this.name = "";
 this.method = "";
    this.method = "";

 this.setClass = function(n)
    this.setClass = function(n) {
{
 name = "class=" + n;
        name = "class=" + n;
 }
    }

 this.setMethod = function(m)
    this.setMethod = function(m) {
{
 method = "method=" + m;
        method = "method=" + m;
 }
    }

 this.invoke = function()
    this.invoke = function() {
{
 var result;
        var result;
 var parames = "";
        var parames = "";

 if(arguments.length > 0)
        if(arguments.length > 0) {
{

 for(i = 0; i < arguments.length; i++)
            for(i = 0; i < arguments.length; i++) {
{
 parames=arguments[i];
                parames=arguments[i];
 }
            }
 }
        }

 $.ajax(
        $.ajax(  {
{
 type : "POST",
            type : "POST",
 url : getRootPath() + "/RemoteServlet",
            url : getRootPath() + "/RemoteServlet",
 cache : false,
            cache : false,
 async : false,
            async : false,
 data : name + "&" + method + "&args=" + parames,
            data : name + "&" + method + "&args=" + parames,

 success : function(data)
            success : function(data)  {
{
 result = data;
                result = data;
 },
            },

 error :function(data)
            error :function(data) {
{
 result= data;
                result= data;
 }
            }
 });
        });
 return result;
        return result;
 }
    }
 }
}
2、服务器端RemoteServlet接收客户端传来类名、方法名、参数,并通过反射的方式,实例化该类和执行相应的方法。
RemoteServlet.java
 import java.io.IOException;
import java.io.IOException;
 import java.lang.reflect.Method;
import java.lang.reflect.Method;
 import javax.servlet.ServletException;
import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponse;


 public class RemoteServlet extends HttpServlet
public class RemoteServlet extends HttpServlet  {
{
 private static final long serialVersionUID = 1L;
    private static final long serialVersionUID = 1L;


 public RemoteServlet()
    public RemoteServlet()  {
{
 super();
        super();
 }
    }


 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  {
{
 remote(request, response);
        remote(request, response);
 }
    }


 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  {
{
 remote(request, response);
        remote(request, response);
 }
    }

 protected void remote(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    protected void remote(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  {
{
 String name = request.getParameter("class");
        String name = request.getParameter("class");
 String method = request.getParameter("method");
        String method = request.getParameter("method");
 String args = request.getParameter("args");
        String args = request.getParameter("args");

 if(name != null && method != null)
        if(name != null && method != null) {
{

 try
            try {
{
 Class cls = Class.forName(name);
                Class cls = Class.forName(name);
 Object[] parames = !args.equals("") ? args.split(";") : null;
                Object[] parames = !args.equals("") ? args.split(";") : null;
 Object obj = cls.newInstance();
                Object obj = cls.newInstance();
 Method[] methods = cls.getMethods();
                Method[] methods = cls.getMethods(); 
 
                

 for(Method m:methods)
                for(Method m:methods) {
{
 System.out.println(m.getName());
                    System.out.println(m.getName());

 if(m.getName().equals(method))
                    if(m.getName().equals(method)) {
{
 Object result = parames != null ? m.invoke(obj,parames) : m.invoke(obj);
                        Object result = parames != null ? m.invoke(obj,parames) : m.invoke(obj); 
 response.setCharacterEncoding("UTF-8");
                        response.setCharacterEncoding("UTF-8");
 response.getWriter().println(result.toString());
                        response.getWriter().println(result.toString());
 break;
                        break;
 }
                    }
 }
                }    
 }
            }

 catch(Exception e)
            catch(Exception e) {
{
 e.printStackTrace();
                e.printStackTrace();
 }
            }
 
            
 }
        }
 }
    }
 }
}在web.xml中配置该servlet
 <servlet>
  <servlet>
 <description></description>
    <description></description>
 <display-name>RemoteServlet</display-name>
    <display-name>RemoteServlet</display-name>
 <servlet-name>RemoteServlet</servlet-name>
    <servlet-name>RemoteServlet</servlet-name>
 <servlet-class>com.pengo.init.RemoteServlet</servlet-class>
    <servlet-class>com.pengo.init.RemoteServlet</servlet-class>
 </servlet>
  </servlet>
 <servlet-mapping>
  <servlet-mapping>
 <servlet-name>RemoteServlet</servlet-name>
    <servlet-name>RemoteServlet</servlet-name>
 <url-pattern>/RemoteServlet</url-pattern>
    <url-pattern>/RemoteServlet</url-pattern>
 </servlet-mapping>
  </servlet-mapping>
3、RemoteServlet处理完,把数据以文本形式返回给客户端。
这样一个简单的客户端调用服务器端方法的框架就完成了。
下面开始试用该框架
先写需要被客户端调用的方法类。
HelloWorld.java

 public class HelloWorld
public class HelloWorld  {
{

 public String say()
    public String say() {
{
 return "hello,pengo!";
        return "hello,pengo!";
 }
    }
 
    

 public String tell(String name)
    public String tell(String name) {
{
 return "hello," + name;
        return "hello," + name;
 }
    }
 }
}
DateUtil.java
 import java.text.SimpleDateFormat;
import java.text.SimpleDateFormat;
 import java.util.Date;
import java.util.Date;

 public class DateUtil
public class DateUtil  {
{

 public String today()
    public String today() {
{
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
 String str = sdf.format(new Date());
        String str = sdf.format(new Date()); 
 return str;
        return str; 
 }
    }
 }
}
客户端调用这两个类
test.html
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <html>
<html>
 <head>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Insert title here</title>
<title>Insert title here</title>
 <script type="text/javascript" src="js/jquery-1.4.2.min.js" ></script>
<script type="text/javascript" src="js/jquery-1.4.2.min.js" ></script>
 <script type="text/javascript" charset=UTF-8" src="js/ScriptEngine.js" ></script>
<script type="text/javascript" charset=UTF-8" src="js/ScriptEngine.js" ></script>
 </head>
</head>

 <script type="text/javascript">
<script type="text/javascript">
 
    

 function hello()
function hello() {
{
 var se = new ScriptEngine();
    var se = new ScriptEngine();
 se.setClass("com.pengo.remote.HelloWorld");
    se.setClass("com.pengo.remote.HelloWorld");
 se.setMethod("say");
    se.setMethod("say");
 var re = se.invoke();
    var re = se.invoke();
 alert(re);
    alert(re);
 }
}

 function tell()
function tell() {
{
 var se = new ScriptEngine();
    var se = new ScriptEngine();
 se.setClass("com.pengo.remote.HelloWorld");
    se.setClass("com.pengo.remote.HelloWorld");
 se.setMethod("tell");
    se.setMethod("tell");
 var re = se.invoke("测试");
    var re = se.invoke("测试");
 alert(re);
    alert(re);
 }
}

 function today()
function today() {
{
 var se = new ScriptEngine();
    var se = new ScriptEngine();
 se.setClass("com.pengo.remote.DateUtil");
    se.setClass("com.pengo.remote.DateUtil");
 se.setMethod("today");
    se.setMethod("today");
 var re = se.invoke();
    var re = se.invoke();
 alert(re);
    alert(re);
 }
}
 </script>
</script>
 <body>
<body>
 <input type="button" onClick="hello();" value="无参数调用"/>
<input type="button" onClick="hello();" value="无参数调用"/>
 <input type="button" onClick="tell();" value="有参数调用"/>
<input type="button" onClick="tell();" value="有参数调用"/>
 <input type="button" onClick="today();" value="取服务器端日期"/>
<input type="button" onClick="today();" value="取服务器端日期"/>
 </body>
</body>
 </html>
</html>
运行效果:
 
本文还需要改进的地方:
1、se.setClass("com.pengo.remote.HelloWorld");不应该通过完整的包名来调用,可以考虑注解实现,
2、返回的数据可以考虑定义为json或xml格式。 
3、......
源码:
下载