在JavaScript程序中整合Java函数

2016-02-19 19:02 12 1 收藏

今天天气好晴朗处处好风光,好天气好开始,图老师又来和大家分享啦。下面给大家推荐在JavaScript程序中整合Java函数,希望大家看完后也有个好心情,快快行动吧!

【 tulaoshi.com - 编程语言 】

  
  问题的提出:   假定我们的Html 页中有一些表单需要处理,并且我们需要初始化数据库中的字段,我们该怎么办?标准的解决办法就是使用CGI脚本或是使用Java Servlet等服务器端程序,但是你有没有想过,还可以编写一个脚本程序使你可以用javascript直接调用服务器端Java程序进行任何计算的结果,就像下面代码中列的那样:

  <html>
  我们的表单<br>
  <form>
  <input type="text" name="textField"><br>
  <input type="button" value="Click" onClick="updateField();">
  </form>
  <script>
  function updateField()
  {
  document.forms[0].textField.value=java.dbConnection.getData('SQL_eXPr');
  }
  </script>
  </html>

  所以,当用户点击按钮,该程序就会调用Java的dbConnection类,然后就可以在JavaScript应用程序中使用Java返回的结果了。上面的程序只是更新了textField的值,我们不必刷新整个页面。由于这个程序也不是jsp文件,所以不必把你的页面编译成Java Servlet。

  你还可以使用调用某些Java函数返回的结果替代段落中的文字;在一个非常大的HTML表中,你可以使用同样的方法,只要更新一行信息:

  
  <script language="JavaScript">
  function changeCol()
  {
  document.all.quote.rows[0].cells[1].innerText=java.Stock.getQuote('Wayne');
  }
  </script>

  <table id="quote" border=1>
  <tr><td>Wayne</td><td>123</td></tr>
  <tr><td>Another one</td><td>34</td></tr>
  </table>

  
  怎么样,能够直接在JavaScript中嵌入Java对象的调用,而且可以保证你的页面的其它部分不会被改变,你一定对这个问题比较感爱好吧。好吧,现在就让我们用Java Servlet来实现它吧。

  工作原理

  我的构思是使用Java Servlet编写一个JinJ(Java in JavaScript)程序,能够让 HTML 页面内整合 Java 类和 JavaScript脚本,将所有使用JavaScript调用Java函数的HTML页面都传送到这个Servlet中处理,JinJ将即时产生带有Java applet的隐藏帧,

  这个applet起着桥梁的作用,用来和Java通讯,它的大小还不到2KB,为了调用对象,Applet使用HTTP连接同一个JinJ Servlet。JinJ用相应的JavaScript结构来替换所有的Java调用(其实每一个调用前都有前缀java),并且保持页面的其它部分不变。所以,为了能够让JinJ正确识别,你的JavaScript代码中的任何Java调用,都要使用如下的结构: java.object_name.function_name(list_of_parameters) 其中:

  java:是一个标准的前缀:

  object_name:是一个变量名,保存某些Java类的实例(在后面,我们会具体的探讨如何创建/定义这样的变量),比如说它可以是一个类名。

   function_name:是一个Java类的函数名。

   list_of_parameters:是调用的函数的参数列表(可以为空)。

  下面也将会探讨如何把参数传给Java,每个参数显然是某个JavaScript表达式。你也可以使用预编译页,换句话说就是在使用HTML页面之前编译它。

  服务器实现

  在谈编程之前我还想说一说JinJ的服务器实现。在你的服务器中需要两个组成部分:JINJ servlet和bridge applet.。你所有需要被整合的HTML页面都是被JinJ servlet预处理,你可以通过以下方法实现:

  a)把你的页面当作一个参数传递给JinJ servlet

  所以你可以把你HTML页中如下的超链接<a href="mypage.html">我的页面</a>改为:<a href="http://myhost/servlet/JinJ?mypage.html" target="_top">我的页面</a>

  JinJ servlet 随即把所有的Java调用转化成JavaScript,然后产生页面并输出出来。

  b)定义某种映射。举例来说,这里我们设置Servlet调用扩展名为.JinJ的文件 (这里介绍的方法针对运行于NT上的JSWDK,你所使用的Servelt系统的具体定义映射的方法请参看你的用户指南)

  JinJ.code=JinJ

  JinJ.initparams=servlet=http://myhost/servlet/JinJ,
  root=c:jswdkwebpages,
  objects=c:jswdkobj.txt,
  codebase=http://myhost/
  设置了以后,你就可以使用http://myhost/some_file.JinJ然后JinJ servlet将会自动被调用了

  Servlet参数

  为了让JinJ正常运行,还应当能够为JinJ servlet设置一些全局参数,这也是我们在编程是应当注重到的问题。对于JSWDK, Servlet属性是参数'initparams'的一部分;对于Tomcat,则应当编辑系统中的web.XML

  
  1)需要设置JinJ servlet的路径,参数名是servlet,就像这样:

  http://your_host:port/servlet/JINJ

  2) 需要设置存放HTML页的根目录,参数名是root,其值就像这样: /home/webpages (或c:webpages) (默认值是一个空的字符串)。 例如,假如你的根目录是:/home/webpages,并且你使用http://host/servlet/JINJ?myfile.htm 的话,那你的真实的文件名是/home/webpages/myfile.htm

  3) 需要设置你定义的Java对象的文件的完全目录,参数名是objects,其值只是一个存放在你的服务器中的一个文件的文件名。

  4) 需要设置用于java applet的codebase,参数名是codebase,定义了存放applet的类的路径,比如http://your_host/ 。

  以下为Tomcat中web.xml 中的相应设置:

   

  <servlet>
  <servlet-name>JinJ</servlet-name>
  <servlet-class>JinJ</servlet-class>
  <init-param>
  <param-name>servlet</param-name>
  <param-value>http://your_host/servlet/JinJ</param-value>
  </init-param>
  <init-param>
  <param-name>root</param-name>
  <param-value>path_to_the_root_Directory</param-value>
  </init-param>
  <init-param>
  <param-name>objects</param-name>
  <param-value>path_to_your_objects_file</param-value>
  </init-param>
  <init-param>
  <param-name>codebaset</param-name>
  <param-value>http://your_host/</param-value>
  </init-param>
  </servlet>

  
  在编程时还应当注重实现读取对象文件中所包含的对象,或创建新的Java对象

  1. 在初始化JinJ Servlet时将创建一些Java对象,因此你必须在某个文本文件中定义这些对象,并且在参数objects中设置这个文件的路径,这是一个文本文件,每一行描述了一个元素(空行和以#或//开头的行将被忽略),使用下面的格式来描述参数:

   object_name=new class_name(list_of_parameters);

  换句话说,它很象每次调用类构造器的new操作符,object_name 是就是某个你将在JavaScript中使用到的标识符,例如:

  file://数据池

  A=new dbPool(5);

  file://哈希表

  B=new java.util.Hashtable();

  或者使用你自己定义的包和类:c=new myPackage.myClass(true);

  然后在JavaScript中,你就可以使用它们了,如A.connect(),其中connect() 是类dbPool的一个函数,或者使用B.put('key',value)

  注重:

  1)你的类应当放在你的CLASSPATH指定的目录下面。

  2)你可以使用类名作为对象名 (不过这必须在没有重名的情况下,因为对象名必须是唯一的),如:dbPool=new dbPool();

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  2. 为了更优化程序,应当在编程的时候就预建一些对象组成标准化库,通过标准化库,你可以在运行中创建/删除对象的实例,查看存在的对象等。

  下面就是我们需要实现的标准化库(预定义的对象) ,对象名是JinJ,所以服务器端名为JinJ的实例将会被自动创建,这给类中有下面几个函数:

   

  public boolean create(String object_name,String class_name,list_of_constrUCtors_parameters);
  public void delete(String object_name);
  public boolean exists(String object_name);
  public String id();
  public int random(int n1, int n2);

  public String rewriteURL(document,String id_name);
  public String rewriteURL(document,String id_name,String id_value);

  
  create(创建):能够让你在运行时创建某个对象的实例:

  参数为:

   - 新的对象名
   - 类名
   - 参数列表 (假如你使用默认构造函数的时候,可以为空)。

  返回值:

   - 根据创建的接过返回true 或 false

  例如:

  
  <script language="JavaScript">
  <!--创建myHash 作为一个新的哈希表Hashtable -->
  java.JinJ.create("myHash","java.util.Hashtable");

  <!-- 使用myHash -->
  java.myHash.put('key1','shop1');
  </script>

  delete:让你删除任何对象的实例。
  参数为:
  - 对象名

  例如:
  <script language="JavaScript">
  <!-- 删除myHash -->
  java.JinJ.delete("myHash");
  </script>

  exists:查看对象的实例是否存在。
  参数为:
  - 对象名
  返回值:
  true 或 false

  例如:
  <script language="JavaScript">
  if (java.JinJ.exists("myHash")=='false')
  {
  <!--创建myHash 作为一个新的哈希表Hashtable -->
  java.JinJ.create(myHash,"java.util.Hashtable");

  <!--使用myHash -->
  java.myHash.put('key1','shop1');
  }
  </script>

  id: 返回唯一的标示符,比如你可以在支持session的程序中使用这个函数。
  Random: 从给定的数域中返回随机值:
  例如:
  <script language="JavaScript">
  var sessionId=java.JinJ.id();

  <!-- 从1到10中的随机数 -->
  var randValue=java.JinJ.random(1,10);
  </script>

  rewriteURL:能够让你使用session。你可以用<a href="some_url? id_name=id_value">你的链接</a>来替代<a href="some_url">你的链接</a>这同样适用于任何形式的动作。你可以只设置一个参数名,参数值将自动生成,也可以同时设置参数名和参数值:
  例如:
  <script language="JavaScript">

  <!--添加sessionId=某个值到这个链接 -->
  java.JinJ.rewriteURL(document,'sessionId');

  <!-- 添加 id=12345 到这个链接-->
  java.JinJ.rewriteURL(document,'id',12345);

  </script>

  我们还要能够分析读入Java函数的参数,对于一个参数我们必须知道它的数据类型,为了简单起见,我们就认为有四种数据类型整型,浮点型,布尔型其余的全归于字符串型,你可以看到,这在程序中都有相应的解释。

  例如:

   

  <!-- 我们假定A(int,float,String,boolean) -->
   java.myClass.myFunc(2, 5.6, a123, true);

  
  为了保证你传递的参数是一个字符串型的值的话,请你使用"或者',如:

   

  <!--总是作为字符串型数据传递-->
  java.myClass.myFunc("256");

   

  函数返回的结果问题

  假如Java函数的类型为void的话,那么将返回给JavaScript一个空字符串,在别的情况下(假如不是数组),将返回Java对象的字符型返回值。假如你的Java函数返回数组或者向量(Vector)或枚举(Enumeration),结果将被表示为JavaScript中的数组。例如:在类dbpool中,你假如有某个函数performQuery(some_sql_string)来通过JDBC来调用SQL查询,将转换ResultSet成为数组(或向量)然后把这个数组返回给JavaScript。

   

  res=java.dbpool.performQuery("select * from emp");
  first=res[0];
  second=res[1];

  
  程序还应该实现控制台(JINJ控制台),这样你就可以直接从浏览器中运行这个Servlet,并且可以创建/删除对象,相应的命令是: http://your_host/servlet/JINJ?your_password

  或者,假如你使用扩展名映射JinJ的话,则::

  http://your_host/your_file.JinJ?your_password ,这些都应当在程序中体现,你可以在servlet的初始化参数中设置口令,参数名是admin. 如:

  
  JINJ.code=JINJ
  JINJ.initparams=admin=secret,
  servlet=http://myhost/servlet/JINJ,
  root=/home/www/pub,
   objects=/home/load/obj.txt,
   codebase=http://myhost/
  默认的密码值是abcd,所以使用JINJ?abcd 将运行治理员界面,通过这一页,你可以删除或者创建新的对象的实例。

  下面,然我们来看看具体在Java代码上如何实现我们的构思:

  JinJ.java

  import java.io.*;
  import java.lang.reflect.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;

  public class JinJ extends HttpServlet
  { public JinJ()
  {
  }

  
  public void init(ServletConfig servletconfig)//初始化
  throws ServletException
  {
  super.init(servletconfig);
  inst = new Hashtable();
  cls = new Hashtable();
  NEWLINE = System.getProperty("line.separator"); file://获取行分割符在本系统中的属性值,例如在UNIX下为
  separator = System.getProperty("file.separator");//获取文件分割符在本系统中的属性值,例如在UNIX下为/

  if((THIS_SERVLET = getInitParameter("servlet")) == null)
  file://getInitParameter方法,返回一个字符串,包含命名的初始化参数的值,假如参数不存在则为空。
  THIS_SERVLET = "";
  if((admin = getInitParameter("admin")) == null)
  admin = "abcd";
  if((DOCUMENT_ROOT = getInitParameter("root")) == null)
  DOCUMENT_ROOT = "";
  if(DOCUMENT_ROOT.length() > 0 && !DOCUMENT_ROOT.endsWith(separator))
  file://假如DOCUMENT_ROOT的长度为正值,并且不以文件分割符结尾则
  DOCUMENT_ROOT = DOCUMENT_ROOT + separator;
  if((CODEBASE = getInitParameter("codebase")) == null)
  CODEBASE = "";
  JAVA_FILE = getInitParameter("objects");
  if(JAVA_FILE != null && inst != null)
  loadJava(JAVA_FILE);
  }

  private void loadJava(String s)
  {
  System.out.println("从" + s +"调用Java对象 ");
  try
  {
  BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream(s)));
  file://创建一个文件输入流缓冲区
  String s1;
  file://开始分析文件
  while((s1 = bufferedreader.readLine()) != null)//每次读入一行
  {
  s1 = s1.trim(); file://把字符串两端的空格去掉
  /*********************************************************
  * 假如以";"结尾则去掉";"
  **********************************************************/
  if(s1.endsWith(";"))
  s1 = s1.substring(0, s1.length() - 1).trim();
  /*****************************************************************************
  * 假如s1的长度大于零,并且第一个字符不为#和//,则调用processLine处理这一行参数
  ******************************************************************************/
  if(s1.length() > 0 && s1.charAt(0) != '#' && !s1.startsWith("//"))
  processLine(s1);
  }

  bufferedreader.close();
  return;
  }
  catch(Exception _ex)
  {
  return;
  }
  }

  private void processLine(String s)
  {
  /**************************************************************************
  *取得这一行中第一次出现等号的下标值,假如没出现等号则返回-1
  *假如没有等号,则输出错误信息
  **************************************************************************/
  int i = s.indexOf("=");
  if(i <= 0 i == s.length() - 1)
  {
  System.out.println("不能处理此行信息: " + s);
  return;
  }
  String s1 = s.substring(0, i).trim();//s1为s中等号前的字符串
  String s2 = s.substring(i + 1).trim();//s2为s中等号后的字符串
  if(s2.startsWith("new "))//判定s2是否以new开头,如new class_name(list_of_parameters);
  s2 = s2.substring("new".length()).trim();
  if(s1.length() == 0 s2.length() == 0)
  {
  System.out.println("不能处理此行信息: " + s);
  return;
  }
  if(inst.get(s1) != null) file://为了防止重复定义类名
  {
  System.out.println("重复命名 " + s1);
  return;
  }
  i = s2.indexOf("(");
  if(i <= 0 && !s2.endsWith(")"))
  {
  System.out.println("不能处理此行信息:" + s);
  return;
  }
  String s3 = s2.substring(0, i).trim();//s3为新定义的类名
  s2 = s2.substring(i + 1, s2.length() - 1).trim();//s2为参数列表
  if(inst.size() < 5)
  processLine1(s1, s3, s2, s);
  }

   

  
  private String prepareString(String s)
  {
  if(s == null)
  return null;
  if(s.length() < 2)
  return s;
  if(s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') file://假如字符串s以"开头,又以"结尾,则把两头的"去掉
  return s.substring(1, s.length() - 1);
  if(s.startsWith("'") && s.endsWith("'"))//假如字符串s以'开头,又以'结尾,则把两头的"去掉
  return s.substring(1, s.length() - 1);
  else
  return s;
  }

  private boolean processLine1(String s, String s1, String s2, String s3)
  { file://创建一个Object类的实例
  Object obj[] = {
  null, null
  };
  Class class1;
  if((class1 = (Class)cls.get(s1)) == null)
  try
  {
  class1 = Class.forName(s1);//返回具有s1指定的类名的类的Class描述符
  cls.put(s1, class1); file://放回哈西表
  }
  catch(Exception _ex)
  {
  System.out.println("不能装载类 " + s1);
  return false;
  }
  obj[0] = class1;
  if(s2.length() == 0)
  {
  try
  {
  obj[1] = class1.newInstance();// 创建类的新实例
  }
  catch(NoSuchMethodError _ex)
  {
  System.out.println("不能创建对象的实例 " + s3);
  return false;
  }
  catch(Exception _ex)
  {
  System.out.println("不能创建对象的实例 " + s3);
  return false;
  }
  inst.put(s, ((Object) (obj)));
  }
  else
  {
  Object obj1[] = getParamArray(s2, 0); file://取得参数列表
  if(obj1 == null)
  {
  System.out.println("不能处理这行参数: " + s3);
  return false;
  }
  try
  {
  Constructor cons = class1.getConstructor((Class[])obj1[0]);//使用参数列表构建类构建器
  if(class1 == null)
  {
  System.out.println("不能创建对象的实例 " + s3);
  return false;
  }
  obj[1] = cons.newInstance((Object[])obj1[1]);
  inst.put(s, ((Object) (obj)));
  }
  catch(Exception _ex)
  {
  System.out.println("不能创建对象的实例 " + s3);
  return false;
  }
  }
  return true;
  }

   

  private Object[] getParamArray(String s, int i) file://取得s中所包含的参数列表,存入一个Object数组中
  {
  String s1 = s.trim(); file://去除末尾的空格
  String s6 = ",";
  Vector vector = new Vector();
  if(s1.length() > 0)
  {
  if(s1.charAt(0) == '(')//去掉(
  s1 = s1.substring(1);
  if(s1.endsWith(")"))//去掉)
  s1 = s1.substring(0, s1.length() - 1);
  String s2 = s1.trim(); file://去掉字符串后的空格
  if(s2.length() == 0 && i == 0) file://假如s2长度为零,说明没有参数
  return null;
  String s4;
  if(s2.length() > 0)
  {
  if(s2.charAt(0) == '"')//假如s2以"开头,则用"代替
  s6 = """;
  else
  if(s2.charAt(0) == ''')//假如s2以'开头,则用'代替
  s6 = "'";
  else
  s6 = ",";
  s4 = s2.substring(0, 1); file://取得s2的第一个字符
  s2 = s2.substring(1);//取得s2的第二个字符往后的字符
  }
  else
  {
  s4 = "";
  }
  for(; s2.length() > 0; s2 = s2.substring(1))//这些语句是为了把参数表中的参数分离出来
  {
  String s5 = s2.substring(0, 1);//取得s2的第一个字符
  if(s5.equals(s6)) file://假如s5和s6相等,即判定s5是否为两个参数的分隔符
  {
  if(s6.equals(""") s6.equals("'"))//假如s6为"或',则
  s4 = s4 + s6;
  vector.addElement(s4); file://把s4(即一个参数值)加入vector中
  s2 = s2.substring(1).trim();
  s4 = "";
  if(s2.length() == 0)
  break;
  s4 = s2.substring(0, 1);
  if(s4.charAt(0) == ',')
  file://假如s4以","开头,则判定s4是否以分隔符开头
  {
  s2 = s2.substring(1).trim();
  s4 = "";
  if(s2.length() == 0)
  break;
  s4 = s2.substring(0, 1);
  }
  if(s4.charAt(0) == '"')
  s6 = """;
  else
  if(s4.charAt(0) == ''')
  s6 = "'";
  else
  s6 = ",";
  }
  else
  {
  s4 = s4 + s5;
  }
  }

  if(s4.length() > 0)
  vector.addElement(s4);
  }
  int j = vector.size(); file://取得向量变量vector的大小,vector中保存的都是参数值
  if(j == 0 && i == 0)
  return null; file://没有参数
  Object aobj[] = new Object[3];
  Class class1[] = new Class[j + i];
  Object aobj1[] = new Object[j + i];
  aobj[0] = class1;
  aobj[1] = ((Object) (aobj1));
  aobj[2] = new Integer(j + i);
  for(int k = i; k < j + i; k++)
  {
  String s3 = (String)vector.elementAt(k - i);
  try
  file://以下的代码是为了判定,每个参数到底是什么数据类型
  { file://判定是否为整型
  Integer integer = Integer.valueOf(s3);
  class1[k] = Integer.TYPE;
  aobj1[k] = integer;
  }
  catch(Exception _ex)
  {
  try
  { file://判定是否为浮点型
  Float float1 = Float.valueOf(s3);
  class1[k] = Float.TYPE;
  aobj1[k] = float1;
  }
  catch(Exception _ex2)
  { file://判定是否为布尔类型
  s3 = prepareString(s3);
  if(s3.equals("true")) file://判定是否为真
  {
  class1[k] = Boolean.TYPE;
  aobj1[k] = new Boolean(true);
  }
  else
  if(s3.equals("false")) file://判定是否为假
  {
  class1[k] = Boolean.TYPE;
  aobj1[k] = new Boolean(false);
  }
  else
  {
  class1[k] = class$java$lang$String == null ? (class$java$lang$String = class$("java.lang.String")) : class$java$lang$String;
  aobj1[k] = s3;
  }
  }
  }
  }

  vector = null;
  return aobj;
  }

   

  
  public void doPost(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
  throws ServletException, IOException
  {
  doGet(httpservletrequest, httpservletresponse);
  }

  public void doGet(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
  throws ServletException, IOException
  {
  String s = "";
  String s1 = "";
  s = HttpUtils.getRequestURL(httpservletrequest).toString();
  file://返回一个字符串,包含请求字符串中包含的协议名,主机名,端口号以及路径,但是不包含请求的内容
  int i;
  if((i = s.indexOf("?")) > 0)//去掉s结尾的问号
  s = s.substring(0, i);
  s1 = httpservletrequest.getQueryString();//取的请求字符串的请求内容
  if(s1 == null)
  {
  parseFile(s1, httpservletrequest, httpservletresponse);
  return;
  }
  if(s1.equals(admin)) file://假如请求串等于admin
  {
  adminPage(httpservletrequest, httpservletresponse, s); file://进入治理员界面
  return;
  }
  if(s1.equals("namiotde")) file://假如请求串为namiotde,则执行相应的执行命令
  {
  executeRequest(httpservletrequest, httpservletresponse);
  return;
  }
  String s2 = getFromQuery(s1, "what="); file://取的动作的属性值
  if(s2.equals("hframe"))
  {
  getHiddenFrame(httpservletrequest, httpservletresponse);//转到隐藏帧
  return;
  }
  if(s2.equals("mframe"))
  {
  getMainFrame(s1, httpservletrequest, httpservletresponse); file://转到主帧
  return;
  }
  else
  {
  parseFile(s1, httpservletrequest, httpservletresponse);
  return;
  }
  }
  file://治理员界面,执行添加删除对象的操作
  private void adminPage(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, String s)
  throws IOException
  {
  PrintWriter printwriter = httpservletresponse.getWriter();
  String s1 = "";
  String s4 = httpservletrequest.getParameter("what"); file://返回请求串中what,即动作的属性值
  if(s4 != null)
  if(s4.equals("delete")) file://假如what的值为delete,则执行相应的操作
  {
  for(Enumeration enumeration = httpservletrequest.getParameterNames(); enumeration.hasMoreElements();)
  {
  String s2 = (String)enumeration.nextElement();
  if(s2.startsWith("_"))
  {
  inst.remove(s2.substring(1));
  s1 = s1 + " " + s2.substring(1);
  }
  }

  if(s1.length() > 0)
  s1 = "删除: " + s1;
  }
  else
  if(s4.equals("add")) file://假如what的值为add,则执行相应的操作
  {
  String s5 = httpservletrequest.getParameter("oname");//取的对象名
  String s6 = httpservletrequest.getParameter("JinJ"); file://取得类名
  String s7 = httpservletrequest.getParameter("params"); file://取得参数
  if(s5 == null)
  s5 = "";
  else
  s5 = s5.trim();
  if(s6 == null)
  s6 = "";
  else
  s6 = s6.trim();
  if(s7 == null)
  s7 = "";
  else
  s7 = s7.trim();
  if(s7.length() > 0 && !s7.startsWith("("))
  s7 = "(" + s7 + ")";
  if(s5.length() > 0 && s6.length() > 0 && inst.size() < 5)
  {
  String s3 = s5 + "=new " + s6 + s7;//写成标准的对象实例化形式
  if(processLine1(s5, s6, s7, s3))
  s1 = s5 + " 被载入...";
  else
  s1 = "不能载入" + s3;
  }
  }
  httpservletresponse.setContentType("text/html");
  printwriter.println("<html>");
  printwriter.println("<head>");
  printwriter.println("<title>JinJ 控制台</title>");
  printwriter.println("</head>");
  printwriter.println("<body bgcolor="#FFFFFF">");
  printwriter.println(setScript());
  if(s1.length() > 0)
  printwriter.println("<br><i>" + s1 + "</i><br>");
  printwriter.println("<h2><center>对象</center></h2>");
  printwriter.println("<br>");
  printwriter.println(objectsTable(s));
  printwriter.println("</body>");
  printwriter.println("</html>");
  }

   

  private String setScript()
  {
  StringBuffer stringbuffer = new StringBuffer();
  stringbuffer.append("<script language="JavaScript">" + NEWLINE);
  stringbuffer.append("function fun(what)" + NEWLINE);
  stringbuffer.append("{ document.mf.what.value=what; document.mf.submit(); }" + NEWLINE);
  stringbuffer.append("</script>" + NEWLINE);
  return stringbuffer.toString();
  }

  private String objectsTable(String s)
  {
  StringBuffer stringbuffer = new StringBuffer();
  String s2 = "#D5E6E1";
  stringbuffer.append("<form name="mf" method=post action="" + s + "?" + admin + "">" + NEWLINE);
  stringbuffer.append("<input type=hidden name="what">" + NEWLINE);
  stringbuffer.append("<table width=98% border=0>");
  stringbuffer.append("<tr bgcolor=#CCCCFF><td nowrap> </td><td nowrap>对象名</td><td nowrap>类名</td></tr>" + NEWLINE);
  for(Enumeration enumeration = inst.keys(); enumeration.hasMoreElements();)
  {
  String s1 = (String)enumeration.nextElement();
  Object aobj[] = (Object[])inst.get(s1);
  stringbuffer.append("<tr bgcolor="" + s2 + "">");
  stringbuffer.append("<td width=5 nowrap>");
  stringbuffer.append("<input type=checkbox name="_" + s1 + "">");
  stringbuffer.append("</td>");
  stringbuffer.append("<td nowrap>" + s1 + "</td><td nowrap>" + aobj[0] + "</td></tr>" + NEWLINE);
  if(s2.equals("#D5E6E1"))
  s2 = "#F7F7F7";
  else
  s2 = "#D5E6E1";
  }

  stringbuffer.append("</table>" + NEWLINE);
  stringbuffer.append("<br><br>");
  stringbuffer.append("<table>" + NEWLINE);
  stringbuffer.append("<tr>");
  if(inst.size() > 0)
  stringbuffer.append("<td align=left nowrap><input type=button value=Delete onClick="fun('delete');"></td>");
  else
  stringbuffer.append("<td nowrap> </td>");
  stringbuffer.append("<td nowrap> </td>");
  stringbuffer.append("<td align=right nowrap>对象名 <input type=text size=10 name="oname"> 类名 <input type=text size=18 name="JinJ"> 参数 <input type=text name="params"> ");
  stringbuffer.append("<input type=button value=Add onClick="fun('add');"></td></tr>");
  stringbuffer.append("</table>" + NEWLINE);
  stringbuffer.append("</form>");
  return stringbuffer.toString();
  }
  file://分析文件
  private void parseFile(String s, HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
  throws IOException
  {
  String s1 = getUrl(httpservletrequest);
  String s2 = getFile(s, httpservletrequest);
  httpservletresponse.setContentType("text/html");
  PrintWriter printwriter = httpservletresponse.getWriter();
  printwriter.println("<html>");
  if(s1 == null)
  {
  printwriter.println("<br>找不到servlet名.请检查初始参数");
  }
  else
  {
  printwriter.println("<frameset rows="*,100%" border=0>");
  printwriter.println("<frame name="hframe" src="" + s1 + "?" + "what" + "=" + "hframe" + "">");
  printwriter.println("<frame name="mframe" src="" + s1 + "?" + "what" + "=" + "mframe" + "&" + "df" + "=" + s2 + "">");
  printwriter.println("</frameset>");
  }
  printwriter.println("</html>");
  printwriter.flush();
  printwriter.close();
  }

   

  
  private String getId()//取ID命令,使用当前的时间配合随机数产生的是唯一值
  {
  String s = "";
  synchronized(SessionIdLock)
  {
  long l = System.currentTimeMillis();
  Random random = new Random();
  s = String.valueOf(l);
  for(int i = 1; i <= 6; i++)
  s = s + (int)(1.0D + 6D * random.nextDouble());

  }
  return s;
  }

  private String randomValue(String s, String s1)//取随机数
  {
  Random random = new Random();
  int i;
  int j;
  try
  {
  i = Integer.parseInt(s);
  j = Integer.parseInt(s1);
  }
  catch(Exception _ex)
  {
  return "对于random()无效的参数值";
  }
  return String.valueOf((int)((double)i + (double)j * random.nextDouble()));
  }

  private void executeRequest(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse) file://执行请求
  throws IOException
  {
  String s = httpservletrequest.getParameter("params"); file://返回参数params的值
  String s2 = "";
  String s3 = "";
  String s4 = "";
  Object aobj[] = {
  null, null
  };
  int i = s.indexOf("@#$");
  String s1 = s.substring(0, i); file://取出"@#$"前的字符串
  if(s.length() <= i + "@#$".length()) file://假如大于的话,说明@#$后还有其他的字符
  s2 = "";
  else
  for(s = s.substring(i + "@#$".length()).trim(); s.length() > 0;)
  {
  i = s.indexOf("@#$");
  if(i < 0)
  {
  if(s2.length() > 0)
  s2 = s2 + ",";
  s2 = s2 + s;
  s = "";
  }
  else
  {
  if(s2.length() > 0)
  s2 = s2 + ",";
  s2 = s2 + s.substring(0, i);
  if(s.length() <= i + "@#$".length())
  s = "";
  else
  s = s.substring(i + "@#$".length()).trim();
  }
  }

  i = s1.indexOf(".");
  if(i > 0 && i < s1.length() - 1)
  {
  s3 = s1.substring(0, i);
  s1 = s1.substring(i + 1);
  }
  if(s3.equals("j2j"))
  {
  if(s1.equals("exists")) file://exists命令
  {
  if(s2.length() == 0) file://参数为零显然是错误的
  {
  s4 = "错误的标准函数调用";
  }
  else
  {
  if((i = s2.indexOf(",")) > 0)
  s2 = s2.substring(0, i);
  s4 = String.valueOf(inst.get(s2) != null);//判定是否存在s2对象
  }
  }
  else
  if(s1.equals("delete")) file://delete函数
  {
  if(s2.length() == 0)
  {
  s4 = "错误的标准函数调用";
  }
  else
  {
  if((i = s2.indexOf(",")) > 0)
  s2 = s2.substring(0, i);
  inst.remove(s2); file://删除s2对象
  s4 = "";
  }
  }
  else
  if(s1.equals("create")) file://create函数,创建新的对象的实例
  {
  if(s2.length() == 0 (i = s2.indexOf(",")) < 0)
  {
  s4 = "错误的标准函数调用";
  }
  else
  {
  String s8 = s2.substring(0, i); file://s8为对象名
  s2 = s2.substring(i + 1);
  String s9;
  if((i = s2.indexOf(",")) < 0)
  {
  s9 = s2; file://假如没有构造参数列表则s9(类名)就等于s2
  s2 = "";
  }
  else
  {
  s9 = s2.substring(0, i); file://否则,s9(类名)为两个逗号之间的字符串
  s2 = s2.substring(i + 1); file://s2是构造参数列表
  }
  if((aobj = (Object[])inst.get(s8)) != null)
  {
  s4 = "false";
  }
  else
  {
  String s5 = s8 + "=new " + s9 + "(" + s2 + ")"; file://s5为一标准java对象实例化形式,送入processLine1处理
  s4 = String.valueOf(processLine1(s8, s9, s2, s5));
  }
  }
  }
  else
  if(s1.equals("id"))//id命令
  s4 = getId();
  else
  if(s1.equals("random")) file://random命令
  {
  if((i = s2.indexOf(",")) < 0) file://假如没有两个参数的话,出错
  s4 = "错误的标准函数调用";
  else
  s4 = randomValue(s2.substring(0, i), s2.substring(i + 1)); file://取随机值
  }
  else
  {
  s4 = "错误的标准函数调用";
  }
  }
  else
  if((aobj = (Object[])inst.get(s3)) == null)
  {
  s4 = "不能发现" + s3+ "的实例";
  }
  else
  {
  Class class1 = (Class)aobj[0];
  Object obj = aobj[1];
  try
  {
  if(s2.length() > 0)
  {
  Object aobj1[] = getParamArray(s2, 0); file://从s2中取出参数列表
  Method method = class1.getMethod(s1, (Class[])aobj1[0]);
  Object obj2 = method.invoke(obj, (Object[])aobj1[1]);
  if(method.getReturnType().getComponentType() == null)
  {
  String s6 = method.getReturnType().toString();
  if(s6.indexOf("java.util.Vector") > 0)//判定s6中是否有java.util.Vector
  {
  if(obj2 == null)
  {
  s4 = "";
  }
  else
  {
  Vector vector = (Vector)obj2;
  if(vector.size() == 0)
  {
  s4 = "";
  }
  else
  {
  for(int j = 0; j < vector.size(); j++)
  {
  s4 = s4 + "@#$";
  s4 = s4 + (String)vector.elementAt(j);
  }

  }
  }
  }
  else
  if(s6.indexOf("java.util.Enumeration") > 0)
  {
  if(obj2 == null)
  {
  s4 = "";
  }
  else
  {
  Enumeration enumeration = (Enumeration)obj2;
  if(!enumeration.hasMoreElements())
  s4 = "";
  else
  while(enumeration.hasMoreElements())
  {
  s4 = s4 + "@#$";
  s4 = s4 + (String)enumeration.nextElement();
  }

  }
  }
  else
  if(obj2 == null)
  s4 = "";
  else
  s4 = String.valueOf(obj2);
  }
  else
  {
  for(int k = 0; k < Array.getLength(obj2); k++)
  {
  s4 = s4 + "@#$";
  if((obj = Array.get(obj2, k)) != null)
  s4 = s4 + obj;
  }

  }
  }
  else
  {
  Method method1 = class1.getMethod(s1, null);
  Object obj3 = method1.invoke(obj, null);
  if(method1.getReturnType().getComponentType() == null)
  {
  String s7 = method1.getReturnType().toString();
  if(s7.indexOf("java.util.Vector") > 0)
  {
  if(obj3 == null)
  {
  s4 = "";
  }
  else
  {
  Vector vector1 = (Vector)obj3;
  if(vector1.size() == 0)
  {
  s4 = "";
  }
  else
  {
  for(int l = 0; l < vector1.size(); l++)
  {
  s4 = s4 + "@#$";
  s4 = s4 + (String)vector1.elementAt(l);
  }

  }
  }
  }
  else
  if(s7.indexOf("java.util.Enumeration") > 0)
  {
  if(obj3 == null)
  {
  s4 = "";
  }
  else
  {
  Enumeration enumeration1 = (Enumeration)obj3;
  if(!enumeration1.hasMoreElements())
  s4 = "";
  else
  while(enumeration1.hasMoreElements())
  {
  s4 = s4 + "@#$";
  s4 = s4 + (String)enumeration1.nextElement();
  }

  }
  }
  else
  if(obj3 == null)
  s4 = "";
  else
  s4 = String.valueOf(obj3);
  }
  else
  {
  for(int i1 = 0; i1 < Array.getLength(obj3); i1++)
  {
  s4 = s4 + "@#$";
  Object obj1;
  if((obj1 = Array.get(obj3, i1)) != null)
  s4 = s4 + obj1;
  }

  }
  }
  }
  catch(Exception _ex)
  {
  s4 = "不能从类 "+ class1.getName()+ "中调用"+ s1;
  }
  if(s4 == null)
  s4 = "";
  }
  PrintWriter printwriter = httpservletresponse.getWriter();
  httpservletresponse.setContentType("text/html");
  printwriter.println(s4);
  printwriter.flush();
  printwriter.close();
  }

  private void getMainFrame(String s, HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
  throws IOException
  {
  PrintWriter printwriter = httpservletresponse.getWriter();
  String s1 = getFromQuery(s, "df="); file://取得数据文件所在的路径和文件名
  httpservletresponse.setContentType("text/html");
  if(s1.length() == 0)
  printwriter.println("<html><br>不能打开数据文件</html>");
  else
  try
  { file://打开数据文件
  BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream(s1)));
  String s2;
  while((s2 = bufferedreader.readLine()) != null)
  {
  int i;
  while((i = s2.indexOf("java.")) > 0)
  {
  String s3 = s2.substring(0, i) + "parent." + "hframe" + ".javabridge('";
  String s4;
  for(s4 = s2.substring(i + "java.".length()); s4.length() > 0; s4 = s4.substring(1))
  {
  if(s4.charAt(0) == '(')
  {
  s3 = s3 + "'";
  s4 = s4.substring(1);
  break;
  }
  s3 = s3 + s4.substring(0, 1);
  }

  if(needComma(s4))
  s3 = s3 + ",";
  s2 = s3 + s4;
  }

  printwriter.println(s2);
  }

  bufferedreader.close();
  }
  catch(Exception _ex)
  {
  printwriter.println("不能读取数据文件" + s1);
  }
  printwriter.flush();
  printwriter.close();
  }
  file://取得隐藏帧
  private void getHiddenFrame(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
  throws IOException
  {
  String s = getId(); file://取得ID
  PrintWriter printwriter = httpservletresponse.getWriter();
  httpservletresponse.setContentType("text/html");
  file://调用applet bridge
  printwriter.println("<html>");
  printwriter.println("<applet code="bridge.class" codebase="" + CODEBASE + "" width=10 height=10>");
  printwriter.println("<param name="servlet" value="" + getUrl(httpservletrequest) + "">");
  printwriter.println("</applet>");
  printwriter.println("<script language="JavaScript">");
  printwriter.println("function javabridge(fName)");
  printwriter.println("{");
  printwriter.println(" var s='';");
  printwriter.println(" if (fName=='jinj.rewriteURL' && javabridge.arguments.length>2)");
  printwriter.println(" {");
  printwriter.println(" if (javabridge.arguments.length==3)");
  printwriter.println(" return rewriteURL(javabridge.arguments[1],javabridge.arguments[2]);");
  printwriter.println(" else");
  printwriter.println(" return rewriteURL(javabridge.arguments[1],javabridge.arguments[2],javabridge.arguments[3]);");
  printwriter.println(" }");
  printwriter.println(" for (i=1;i<javabridge.arguments.length;i++)");
  printwriter.println(" { if (s!='') { s+='@#$';}");
  printwriter.println(" s+=javabridge.arguments[i]; }");
  printwriter.println(" s=document.applets[0].fromJava(fName,s);");
  printwriter.println(" i=s.indexOf('@#$');");
  printwriter.println(" if (i<0) return s;");
  printwriter.println(" ans=new Array(); s=s.substring(3); i=s.indexOf('@#$'); j=0;");
  printwriter.println(" while (i>=0)");
  printwriter.println(" { ans[j]=s.substring(0,i); j=j+1; s=s.substring(i+3); i=s.indexOf('@#$'); }");
  printwriter.println(" ans[j]=s; return ans; ");
  printwriter.println("}");
  printwriter.println("function rewriteURL1(s,id)");
  printwriter.println("{");
  printwriter.println("if (s.indexOf('?')>0) return s+'&'+id+'='+'" + s + "';");
  printwriter.println("return s+'?'+id+'='+'" + s + "';");
  printwriter.println("}");
  printwriter.println("function rewriteURL2(s,id,vl)");
  printwriter.println("{");
  printwriter.println("if (s.indexOf('?')>0) return s+'&'+id+'='+vl;");
  printwriter.println("return s+'?'+id+'='+vl;");
  printwriter.println("}");
  printwriter.println("function rewriteURL(doc)");
  printwriter.println("{");
  printwriter.println(" i=rewriteURL.arguments.length;");
  printwriter.println(" if (i>1)");
  printwriter.println(" {");
  printwriter.println(" tmp=rewriteURL.arguments[1];");
  printwriter.println(" for (j=0; j<doc.links.length; j++)");
  printwriter.println(" {");
  printwriter.println(" s=doc.links[j].href;");
  printwriter.println(" if (s.indexOf(tmp+'=')<0)");
  printwriter.println(" {");
  printwriter.println(" if (i==2) doc.links[j].href=rewriteURL1(s,tmp);");
  printwriter.println(" else doc.links[j].href=rewriteURL2(s,tmp,rewriteURL.arguments[2]);");
  printwriter.println(" }");
  printwriter.println(" }");
  printwriter.println(" for (j=0; j<doc.forms.length; j++)");
  printwriter.println(" {");
  printwriter.println(" s=doc.forms[j].action;");
  printwriter.println(" if (s.indexOf(tmp+'=')<0)");
  printwriter.println(" {");
  printwriter.println(" if (i==2) doc.forms[j].action=rewriteURL1(s,tmp);");
  printwriter.println(" else doc.forms[j].action=rewriteURL2(s,tmp,rewriteURL.arguments[2]);");
  printwriter.println(" }");
  printwriter.println(" }");
  printwriter.println(" }");
  printwriter.println(" return " + s + ";");
  printwriter.println("}");
  printwriter.println("</script>");
  printwriter.println("</html>");
  printwriter.flush();
  printwriter.close();
  }

  private String getFile(String s, HttpServletRequest httpservletrequest)
  {
  String s1 = httpservletrequest.getRequestURI();
  String s2 = "";
  if(s1.endsWith("jinj") s1.endsWith("JinJ.class"))
  {
  if(s == null)
  return null;
  s1 = getFromQuery(s, "df=");
  if(s1.length() == 0)
  s2 = s;
  else
  s2 = s1;
  }
  else
  {
  s2 = s1;
  }
  if(s2 == null)
  return s2;
  if(s2.length() == 0)
  return s2;
  if(s2.charAt(0) == '/')
  s2 = s2.substring(1);
  return DOCUMENT_ROOT + s2.replace('/', separator.charAt(0));
  }

  private String getUrl(HttpServletRequest httpservletrequest)
  {
  if(THIS_SERVLET.length() > 0)
  return THIS_SERVLET;
  String s1 = httpservletrequest.getRequestURI();
  String s = HttpUtils.getRequestURL(httpservletrequest).toString();
  int i;
  if((i = s.indexOf("?")) > 0)
  s = s.substring(0, i);
  if(s1.endsWith("JinJ") s1.endsWith("JinJ.class"))
  return s;
  else
  return null;
  }

  private boolean needComma(String s) file://判定是否缺少括号
  {
  String s1 = s.trim();
  if(s1.length() == 0)
  return true;
  return s1.charAt(0) != ')';
  }

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

   

  
  private String getFromQuery(String s, String s1)
  {
  if(s == null)
  return "";
  int i;
  if((i = s.indexOf(s1)) < 0)
  return "";
  String s2 = s.substring(i + s1.length());
  if((i = s2.indexOf("&")) < 0)
  return s2;
  else
  return s2.substring(0, i);
  }

   

  
  static Class class$(String s)
  {
  try
  {
  return Class.forName(s);
  }
  catch(ClassNotFoundException classnotfoundexception)
  {
  throw new NoClassDefFoundError(classnotfoundexception.getMessage());
  }
  }

  public static Object SessionIdLock = new Object();
  private static final int HOW_LONG = 6;
  private static final String CLASSNAME = "JinJ";
  private static final String STDLIB = "jinj";
  private static final String EXISTS = "exists";
  private static final String DELETE = "delete";
  private static final String CREATE = "create";
  private static final String ID = "id";
  private static final String RANDOM = "random";
  private static final String BRIDGE = "bridge.class";
  private static String NEWLINE = "";
  private static String separator;
  private static final String HFRAME = "hframe";
  private static final String MFRAME = "mframe";
  private static final String EXECUTE = "namiotde";
  private static final String ACTION = "what";
  private static final String DATAFILE = "df";
  private static final String PARAMS = "params";
  private static final String PARAM_DELIMETER = "@#$";
  private static final String SERVLET = "servlet";
  private static final String ROOT = "root";
  private static final String OBJECTS = "objects";
  private static final String BASE = "codebase";
  private static final String ADMIN = "admin";
  private static final String DEFADMIN = "abcd";
  private static String admin;
  private static String THIS_SERVLET = "";
  private static String DOCUMENT_ROOT = "";
  private static String JAVA_FILE = "";
  private static String CODEBASE = "";
  private static final String NEW = "new";
  private static final String JAVA_CALL = "java.";
  private static final int TYPES = 0;
  private static final int VALUES = 1;
  private static final int DIM = 2;
  private static final String ODD = "#D5E6E1";
  private static final String EVEN = "#F7F7F7";
  private static final String ADD = "add";
  private static final String OBJNAME = "oname";
  private static Hashtable inst = null;
  private static Hashtable cls = null;
  static Class class$java$lang$String;

  }

   

  bridge.java

  import java.applet.Applet;
  import java.io.*;
  import java.net.*;

  public class bridge extends Applet
  {

  public void init()
  {
  super.init();
  bridge_servlet = getParameter("servlet");
  }

  public String fromJava(String s, String s1)
  {
  String s2 = "";
  try
  {
  URL url = new URL(bridge_servlet + "?" + "namiotde");
  URLConnection urlconnection = url.openConnection();
  urlconnection.setDoOutput(true);
  urlconnection.setDoInput(true);
  urlconnection.setUseCaches(false);
  urlconnection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
  PrintWriter printwriter = new PrintWriter(urlconnection.getOutputStream());
  printwriter.print("params=" + URLEncoder.encode(s + "@#$" + s1));
  printwriter.close();
  BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(urlconnection.getInputStream()));
  s2 = bufferedreader.readLine();
  bufferedreader.close();
  }
  catch(Exception _ex)
  {
  return "Can not connect to " + bridge_servlet;
  }
  return s2;
  }

  public bridge()
  {
  }

  private static final String SERVLET = "servlet";
  private static String bridge_servlet = "";
  private static final String EXECUTE = "namiotde";
  private static final String PARAMS = "params";
  private static final String PARAM_DELIMETER = "@#$";

  }

   


来源:http://www.tulaoshi.com/n/20160219/1619897.html

延伸阅读
标签: Web开发
JavaScript中splice函数方法是从一个数组中移除一个或多个元素,如果必要,在所移除元素的位置上插入新元素,返回所移除的元素。 其中arrayObj必选项。一个 Array 对象。 start是必选项。指定从数组中移除元素的开始位置,这个位置是从 0 开始计算的。 deleteCount是必选项。要移除的元素的个数。 item1, item...
标签: Web开发
JavaScript中small函数方法是将 HTML 的SMALL 标识添加到String 对象中的文本两端。使用方法: strVariable.small( ) "String Literal".small( ) 下面的示例演示了 JavaScript中small函数方法是如何使用的: var strVariable = "This is a string"; strVariable = strVariable.small( );   ...
标签: Web开发
JavaScript中sort函数方法是返回一个元素已经进行了排序的 Array 对象。 使用方法: 其中arrayObj是必选项。任意 Array 对象。 sortFunction是可选项。是用来确定元素顺序的函数的名称。如果这个参数被省略,那么元素将按照 ASCII 字符顺序进行升序排列。 JavaScript中sort函数方法将 Array 对象进行适当的排序;在...
标签: Web开发
看个例子: 1  代码如下: function a(){      alert("我是脚本之家");  }  2   代码如下: var a = function(){      alert("我是脚本之家");  }         1和2的方法是等价的...
标签: Web开发
我们最希望任何事都是完美的,如在企业应用中,我们只需要选择一个Web平台就可以部署所有的企业应用。但往往理想与现实相去甚远。在现实世界中,信息系统往往是由很多不同的操作系统、平台以及应用环境混合而成的。而且为了保持与旧的系统兼容,系统总是将当前的技术和以前的遗留技术进行混合,这样周而复始。就使系统变得越来越复杂。 &n...

经验教程

953

收藏

34
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部