posts - 59, comments - 244, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

客户端调用服务器端方法的简单例子

Posted on 2011-03-03 09:44 penngo 阅读(3525) 评论(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(){
    
var strFullPath=window.document.location.href;
    
var strPath=window.document.location.pathname;
    
var pos=strFullPath.indexOf(strPath);
    
var prePath=strFullPath.substring(0,pos);
    
var postPath=strPath.substring(0,strPath.substr(1).indexOf('/')+1);
    
return(prePath+postPath);
    }

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

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

    
this.invoke = function(){
        
var result;
        
var parames = "";
        
if(arguments.length > 0){
            
for(i = 0; i < arguments.length; i++){
                parames
=arguments[i];
            }

        }

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

        }
);
        
return result;
    }

}

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

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

    
public RemoteServlet() {
        
super();
    }


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


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

    
protected void remote(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name 
= request.getParameter("class");
        String method 
= request.getParameter("method");
        String args 
= request.getParameter("args");
        
if(name != null && method != null){
            
try{
                Class cls 
= Class.forName(name);
                Object[] parames 
= !args.equals(""? args.split(";") : null;
                Object obj 
= cls.newInstance();
                Method[] methods 
= cls.getMethods(); 
                
                
for(Method m:methods){
                    System.out.println(m.getName());
                    
if(m.getName().equals(method)){
                        Object result 
= parames != null ? m.invoke(obj,parames) : m.invoke(obj); 
                        response.setCharacterEncoding(
"UTF-8");
                        response.getWriter().println(result.toString());
                        
break;
                    }

                }
    
            }

            
catch(Exception e){
                e.printStackTrace();
            }

            
        }

    }

}

在web.xml中配置该servlet

  <servlet>
    
<description></description>
    
<display-name>RemoteServlet</display-name>
    
<servlet-name>RemoteServlet</servlet-name>
    
<servlet-class>com.pengo.init.RemoteServlet</servlet-class>
  
</servlet>
  
<servlet-mapping>
    
<servlet-name>RemoteServlet</servlet-name>
    
<url-pattern>/RemoteServlet</url-pattern>
  
</servlet-mapping>


3、RemoteServlet处理完,把数据以文本形式返回给客户端。
这样一个简单的客户端调用服务器端方法的框架就完成了。

下面开始试用该框架
先写需要被客户端调用的方法类。
HelloWorld.java

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

    
    
public String tell(String name){
        
return "hello," + name;
    }

}


DateUtil.java

import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
    
public String today(){
        SimpleDateFormat sdf 
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
        String str 
= sdf.format(new Date()); 
        
return str; 
    }

}


客户端调用这两个类
test.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<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>
</head>
<script type="text/javascript">
    
function hello(){
    
var se = new ScriptEngine();
    se.setClass(
"com.pengo.remote.HelloWorld");
    se.setMethod(
"say");
    
var re = se.invoke();
    alert(re);
}

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

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

</script>
<body>
<input type="button" onClick="hello();" value="无参数调用"/>
<input type="button" onClick="tell();" value="有参数调用"/>
<input type="button" onClick="today();" value="取服务器端日期"/>
</body>
</html>


运行效果:



本文还需要改进的地方:
1、se.setClass("com.pengo.remote.HelloWorld");不应该通过完整的包名来调用,可以考虑注解实现,
2、返回的数据可以考虑定义为json或xml格式。
3、......

源码:下载

评论

# re: 客户端调用服务器端方法的简单例子  回复  更多评论   

2011-03-03 10:55 by 窝窝影视
这个实用 ,不错。。。

# re: 客户端调用服务器端方法的简单例子[未登录]  回复  更多评论   

2012-11-05 11:25 by Luke
Method[] methods = cls.getMethods();

for(Method m:methods){
System.out.println(m.getName());
if(m.getName().equals(method)){
Object result = parames != null ? m.invoke(obj,parames) : m.invoke(obj);
response.setCharacterEncoding("UTF-8");
response.getWriter().println(result.toString());
break;
}
不需要这样写,直接用getDeclaredMethod(arg0, arg1)即可

# re: 客户端调用服务器端方法的简单例子  回复  更多评论   

2012-12-10 18:25 by 路人甲
非常感谢!

只有注册用户登录后才能发表评论。


网站导航: