2010年6月29日

1、Log4j是什么?
  Log4j可以帮助调试(有时候debug是发挥不了作 用的)和分析,要下载和了解更详细的内容,还是访问其官方网站吧: http://jakarta.apache.org/log4j .

  2、Log4j的概念
  Log4j中有三个主要的组件,它们分别是 Logger、Appender和Layout,Log4j 允许开发人员定义多个Logger,每个Logger拥有自己的名字,Logger之间通过名字来表明隶属关系。有一个Logger称为Root,它永远存在,且不能通过名字检索或引用,可以通过Logger.getRootLogger()方法获得,其它Logger通过 Logger.getLogger(String name)方法。
  Appender则是用来指明将所有的log信息存放到什么地方,Log4j中支持多种appender,如 console、files、GUI components、NT Event Loggers等,一个Logger可以拥有多个Appender,也就是你既可以将Log信息输出到屏幕,同时存储到一个文件中。
  Layout的作用是控制Log信息的输出方式,也就是格式化输出的信息。
  Log4j中将要输出的Log信息定义了5种级别,依次为DEBUG、INFO、WARN、ERROR和FATAL,当输出时,只有级别高过配置中规定的 级别的信息才能真正的输出,这样就很方便的来配置不同情况下要输出的内容,而不需要更改代码,这点实在是方便啊。

  3、Log4j的配置文件
  虽然可以不用配置文件,而在程序中实现配置,但这种方法在如今的系统开发中显然是不可取的,能采用配置文件的地方一定一定要用配置文件。Log4j支持两 种格式的配置文件:XML格式和Java的property格式,本人更喜欢后者,首先看一个简单的例子吧,如下:
   log4j.rootLogger=debug, stdout, R
   log4j.appender.stdout=org.apache.log4j.ConsoleAppender
   log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

   # Pattern to output the caller's file name and line number.
   log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

   log4j.appender.R=org.apache.log4j.RollingFileAppender
   log4j.appender.R.File=example.log
   log4j.appender.R.MaxFileSize= 100KB

   # Keep one backup file
   log4j.appender.R.MaxBackupIndex=1

   log4j.appender.R.layout=org.apache.log4j.PatternLayout
   log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

  首先,是设置root,格式为 log4j.rootLogger=[level],appenderName, ……,其中level就是设置需要输出信息的级别,后面是appender的输出的目的地,appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。 配置日志信息输出目的地Appender,其语法为
log4j.appender.appenderName = fully.qualified.name.of.appender.class
   log4j.appender.appenderName.option1 = value1
   ...
   log4j.appender.appenderName.option = valueN


  Log4j提供的appender有以下几种:
  org.apache.log4j.ConsoleAppender(控制台)
  org.apache.log4j.FileAppender(文件)
  org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
  org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生新文件)
  org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

  配置日志信息的格式(布局),其语法为:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
   log4j.appender.appenderName.layout.option1 = value1
   ....
   log4j.appender.appenderName.layout.option = valueN

  Log4j提供的layout有以下几种:
  org.apache.log4j.HTMLLayout(以HTML表格形式布局),
  org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
  org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
  org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
     www.jhaccp.com.cn
  Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下: %m 输出代码中指定的消息
  %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
  %r 输出自应用启动到输出该log信息耗费的毫秒数
  %c 输出所属的类目,通常就是所在类的全名
  %t 输出产生该日志事件的线程名
  %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
  %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似: 2002年10月18日 22:10:28,921
  %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)

  4、Log4j在程序中的使用
  要在自己的程序中使用Log4j,首先需要将commons- logging.jar和logging-log4j-1.2.9.jar导入到构建路径中。然后再将log4j.properties放到src根目录下。这样就可以在程序中使用log4j了。在类中使用log4j,首先声明一个静态变量 Logger logger=Logger.getLog("classname");现在就可以使用了,用法如下:logger.debug("debug message")或者logger.info("info message"),看下面一个小例子:

import com.foo.Bar;
   import org.apache.log4j.Logger;
   import org.apache.log4j.PropertyConfigurator;
   public class MyApp {
     static Logger logger = Logger.getLogger(MyApp.class.getName());
     public static void main(String[] args) {
       // BasicConfigurator replaced with PropertyConfigurator.
       PropertyConfigurator.configure(args[0]);
       logger.info("Entering application.");
       Bar bar = new Bar();
       bar.doIt();
       logger.info("Exiting application.");
     }
   }

posted @ 2010-06-29 11:27 FaithChen 阅读(104) | 评论 (0)编辑 收藏


2010年6月28日

java1.5方法参数不确定

Java中"Test(Object...args){}"方法声明的理解——J2SE5的“Varargs”机制收藏

转自:

孙海涛 (sun.haitao@126.com) http://blog.csdn.net/avius

2004年8月5日最初发表,2004年8月19日最后修订

J2SE 1.5提供了“Varargs”机制。借助这一机制,可以定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。本文介绍这一机制的使用方法,以及这一机制与数组、泛型、重载之间的相互作用时的若干问题。


J2SE 1.5提供了“Varargs”机制。借助这一机制,可以定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。本文介绍这一机制的使用方法,以及这一机制与数组、泛型、重载之间的相互作用时的若干问题。

 

到J2SE 1.4为止,一直无法在Java程序里定义实参个数可变的方法——因为Java要求实参(Arguments)和形参(Parameters)的数量和类型都必须逐一匹配,而形参的数目是在定义方法时就已经固定下来了。尽管可以通过重载机制,为同一个方法提供带有不同数量的形参的版本,但是这仍然不能达到让实参数量任意变化的目的。

然而,有些方法的语义要求它们必须能接受个数可变的实参——例如著名的main方法,就需要能接受所有的命令行参数为实参,而命令行参数的数目,事先根本无法确定下来。

对于这个问题,传统上一般是采用“利用一个数组来包裹要传递的实参”的做法来应付。

1. 用数组包裹实参

“用数组包裹实参”的做法可以分成三步:首先,为这个方法定义一个数组型的参数;然后在调用时,生成一个包含了所有要传递的实参的数组;最后,把这个数组作为一个实参传递过去。

这种做法可以有效的达到“让方法可以接受个数可变的参数”的目的,只是调用时的形式不够简单。

J2SE 1.5中提供了Varargs机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。

Varargs的含义

大体说来,“Varargs”是“variable number of arguments”的意思。有时候也被简单的称为“variable arguments”,不过因为这一种叫法没有说明是什么东西可变,所以意义稍微有点模糊。

2. 定义实参个数可变的方法

只要在一个形参的“类型”与“参数名”之间加上三个连续的“.”(即“...”,英文里的句中省略号),就可以让它和不确定个实参相匹配。而一个带有这样的形参的方法,就是一个实参个数可变的方法。

清单1:一个实参个数可变的方法

private static int sumUp(int... values) { }

注意,只有最后一个形参才能被定义成“能和不确定个实参相匹配”的。因此,一个方法里只能有一个这样的形参。另外,如果这个方法还有其它的形参,要把它们放到前面的位置上。

编译器会在背地里把这最后一个形参转化为一个数组形参,并在编译出的class文件里作上一个记号,表明这是个实参个数可变的方法。

清单2:实参个数可变的方法的秘密形态

private static int sumUp(int[] values) { }

由于存在着这样的转化,所以不能再为这个类定义一个和转化后的方法签名一致的方法。

清单3:会导致编译错误的组合

private static int sumUp(int... values) { } private static int sumUp(int[] values) { }

空白的存亡问题

根据J2SE 1.5的语法,在“...”前面的空白字符是可有可无的。这样就有在“...”前面添加空白字符(形如“Object ... args”)和在“...”前面不加空白字符(形如“Object... args”)的两种写法。因为目前和J2SE 1.5相配合的Java Code Conventions还没有正式发布,所以无法知道究竟哪一种写法比较正统。不过,考虑到数组参数也有“Object [] args”和“Object[] args”两种书写方式,而正统的写法是不在“[]”前添加空白字符,似乎采取不加空白的“Object... args”的写法在整体上更协调一些。

3. 调用实参个数可变的方法

只要把要传递的实参逐一写到相应的位置上,就可以调用一个实参个数可变的方法。不需要其它的步骤。

清单4:可以传递若干个实参

sumUp(1, 3, 5, 7);

在背地里,编译器会把这种调用过程转化为用“数组包裹实参”的形式:

清单5:偷偷出现的数组创建

sumUp(new int[]{1, 2, 3, 4});

另外,这里说的“不确定个”也包括零个,所以这样的调用也是合乎情理的:

清单6:也可以传递零个实参

sumUp();

这种调用方法被编译器秘密转化之后的效果,则等同于这样:

清单7:零实参对应空数组

sumUp(new int[]{});

注意这时传递过去的是一个空数组,而不是null。这样就可以采取统一的形式来处理,而不必检测到底属于哪种情况。

4. 处理个数可变的实参

处理个数可变的实参的办法,和处理数组实参的办法基本相同。所有的实参,都被保存到一个和形参同名的数组里。根据实际的需要,把这个数组里的元素读出之后,要蒸要煮,就可以随意了。

清单8:处理收到的实参们

private static int sumUp(int... values) {      int sum = 0;      for (int i = 0; i < values.length; i++) {          sum += values[i];      }      return sum; }

5. 转发个数可变的实参

有时候,在接受了一组个数可变的实参之后,还要把它们传递给另一个实参个数可变的方法。因为编码时无法知道接受来的这一组实参的数目,所以“把它们逐一写到该出现的位置上去”的做法并不可行。不过,这并不意味着这是个不可完成的任务,因为还有另外一种办法,可以用来调用实参个数可变的方法。

在J2SE 1.5的编译器的眼中,实参个数可变的方法是最后带了一个数组形参的方法的特例。因此,事先把整组要传递的实参放到一个数组里,然后把这个数组作为最后一个实参,传递给一个实参个数可变的方法,不会造成任何错误。借助这一特性,就可以顺利的完成转发了。

清单9:转发收到的实参们

public class PrintfSample {      public static void main(String[] args) {          //打印出“Pi:3.141593 E:2.718282”          printOut("Pi:%f E:%f\n", Math.PI, Math.E);      }      private static void printOut(String format, Object... args) {          //J2SE 1.5里PrintStream新增的printf(String format, Object... args)方法          System.out.printf(format, args);      } }

Java里的“printf”和“sprintf”

C语言里的printf(按一定的格式输出字符串)和sprintf(按一定的格式组合字符串)是十分经典的使用Varargs机制的例子。在 J2SE 1.5中,也分别在java.io.PrintStream类和java.lang.String类中提供了类似的功能。

按一定的格式输出字符串的功能,可以通过调用PrintStream对象的printf(String format, Object... args)方法来实现。

按一定的格式组合字符串的工作,则可以通过调用String类的String format(String format, Object... args)静态方法来进行。

6. 是数组?不是数组?

尽管在背地里,编译器会把能匹配不确定个实参的形参,转化为数组形参;而且也可以用数组包了实参,再传递给实参个数可变的方法;但是,这并不表示“能匹配不确定个实参的形参”和“数组形参”完全没有差异。

一个明显的差异是,如果按照调用实参个数可变的方法的形式,来调用一个最后一个形参是数组形参的方法,只会导致一个“cannot be applied to”的编译错误。

清单10:一个“cannot be applied to”的编译错误

private static void testOverloading(int[] i) {      System.out.println("A"); } public static void main(String[] args) {      testOverloading(1, 2, 3);//编译出错 }

由于这一原因,不能在调用只支持用数组包裹实参的方法的时候(例如在不是专门为J2SE 1.5设计第三方类库中遗留的那些),直接采用这种简明的调用方式。

如果不能修改原来的类,为要调用的方法增加参数个数可变的版本,而又想采用这种简明的调用方式,那么可以借助“引入外加函数(Introduce Foreign Method)”和“引入本地扩展(Intoduce Local Extension)”的重构手法来近似的达到目的。

7. 当个数可变的实参遇到泛型

J2SE 1.5中新增了“泛型”的机制,可以在一定条件下把一个类型参数化。例如,可以在编写一个类的时候,把一个方法的形参的类型用一个标识符(如T)来代表,至于这个标识符到底表示什么类型,则在生成这个类的实例的时候再行指定。这一机制可以用来提供更充分的代码重用和更严格的编译时类型检查。

不过泛型机制却不能和个数可变的形参配合使用。如果把一个能和不确定个实参相匹配的形参的类型,用一个标识符来代表,那么编译器会给出一个“generic array creation”的错误。

清单11:当Varargs遇上泛型

private static <T> void testVarargs(T... args) {//编译出错 }

造成这个现象的原因在于J2SE 1.5中的泛型机制的一个内在约束——不能拿用标识符来代表的类型来创建这一类型的实例。在出现支持没有了这个约束的Java版本之前,对于这个问题,基本没有太好的解决办法。

不过,传统的“用数组包裹”的做法,并不受这个约束的限制。

清单12:可以编译的变通做法

private static <T> void testVarargs(T[] args) {      for (int i = 0; i < args.length; i++) {          System.out.println(args[i]);      } }

8. 重载中的选择问题

Java支持“重载”的机制,允许在同一个类拥有许多只有形参列表不同的方法。然后,由编译器根据调用时的实参来选择到底要执行哪一个方法。

传统上的选择,基本是依照“特殊者优先”的原则来进行。一个方法的特殊程度,取决于为了让它顺利运行而需要满足的条件的数目,需要条件越多的越特殊。

在引入Varargs机制之后,这一原则仍然适用,只是要考虑的问题丰富了一些——传统上,一个重载方法的各个版本之中,只有形参数量与实参数量正好一致的那些有被进一步考虑的资格。但是Varargs机制引入之后,完全可以出现两个版本都能匹配,在其它方面也别无二致,只是一个实参个数固定,而一个实参个数可变的情况。

遇到这种情况时,所用的判定规则是“实参个数固定的版本优先于实参个数可变的版本”。

清单13:实参个数固定的版本优先

public class OverloadingSampleA {      public static void main(String[] args) {          testOverloading(1);//打印出A          testOverloading(1, 2);//打印出B          testOverloading(1, 2, 3);//打印出C      }      private static void testOverloading(int i) {          System.out.println("A");      }      private static void testOverloading(int i, int j) {          System.out.println("B");      }      private static void testOverloading(int i, int... more) {          System.out.println("C");      } }

如果在编译器看来,同时有多个方法具有相同的优先权,它就会陷入无法就到底调用哪个方法作出一个选择的状态。在这样的时候,它就会产生一个 “reference to 被调用的方法名 is ambiguous”的编译错误,并耐心的等候作了一些修改,足以免除它的迷惑的新源代码的到来。

在引入了Varargs机制之后,这种可能导致迷惑的情况,又增加了一些。例如现在可能会有两个版本都能匹配,在其它方面也如出一辙,而且都是实参个数可变的冲突发生。

清单14:左右都不是,为难了编译器

public class OverloadingSampleB {      public static void main(String[] args) {          testOverloading(1, 2, 3);//编译出错      }      private static void testOverloading(Object... args) {      }      private static void testOverloading(Object o, Object... args) {      } }

另外,因为J2SE 1.5中有“Autoboxing/Auto-Unboxing”机制的存在,所以还可能发生两个版本都能匹配,而且都是实参个数可变,其它方面也一模一样,只是一个能接受的实参是基本类型,而另一个能接受的实参是包裹类的冲突发生。

清单15:Autoboxing/Auto-Unboxing带来的新问题

public class OverloadingSampleC {      public static void main(String[] args) {          /* 编译出错 */          testOverloading(1, 2);          /* 还是编译出错 */          testOverloading(new Integer(1), new Integer(2));      }      private static void testOverloading(int... args) {      }      private static void testOverloading(Integer... args) {      } }

9. 归纳总结

和“用数组包裹”的做法相比,真正的实参个数可变的方法,在调用时传递参数的操作更为简单,含义也更为清楚。不过,这一机制也有它自身的局限,并不是一个完美无缺的解决方案。

posted @ 2010-06-28 17:55 FaithChen 阅读(906) | 评论 (0)编辑 收藏


2010年6月25日

     摘要:   1.让@Autowired工作起来的准备工作 要使@Autowired能够工作,首先需要在配置文件中加入以下代码 <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />  说...  阅读全文

posted @ 2010-06-25 17:05 FaithChen 阅读(1746) | 评论 (0)编辑 收藏


2008年6月16日

DWR是一个框架,简单的说就是能够在javascript直接调用java方法,而不必去写一大堆的javascript代码。它的实现是基于ajax的,可以实现无刷新效果。
    网上有不少DWR的例子,但大都只是某种方法的调用,本文只在使用层面上介绍DWR,并不涉更多的技术与设计,其目的是让初学者能够很快的学会各种java方法在javascript中是如何调用的。

    本文以DWR 1.1 为基础,对于DWR 2.0,因为还没有正式发布版,故不做介绍。

一、 dwr配置篇之web.xml
   1 、最小配置
<servlet>
  <servlet-name>dwr-invoker</servlet-name>
  <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>dwr-invoker</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
2、当我们想看DWR自动生成的测试页(Using debug/test mode)时,可在servlet配置中加上
<init-param>
  <param-name>debug</param-name>
  <param-value>true</param-value>
</init-param>
这个参数DWR默认是false。如果选择true,我们可以通过 http://localhost:port/app/dwr看到你部署的每个DWR class。并且可以测试java代码的每个方法是否运行正常。为了安全考虑,在正式环境下你一定把这个参数设为false。
3、多个dwr.xml文件的配置
可能有几种情况,我们一一列举。一个servlet,多个dwr.xml配置文件;多个servlet,每个servlet对应一个或多个dwr.xml配置文件。
3.1、一个servlet,多个dwr.xml配置文件
<servlet>
    <servlet-name>dwr-invoker</servlet-name>
    <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
    <init-param>
      <param-name>config-1</param-name>
      <param-value>WEB-INF/dwr1.xml</param-value>
    </init-param>
    <init-param>
      <param-name>config-2</param-name>
      <param-value>WEB-INF/dwr2.xml</param-value>
    </init-param>
</servlet>
在 这种配置下,param-name的值必须以config开头。param-name可以有>=0个。如果没有param-name,那么将会读取 WEB-INF/dwr.xml。如果有大于零个param-name,那么WEB-INF/dwr.xml文件将不会被读取。
3.2 、多个 servlet ,每个 servlet 对应一个或多个 dwr.xml
<servlet>
   <servlet-name>dwr-invoker</servlet-name>
    <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet>
   <servlet-name>dwr-invoker1</servlet-name>
   <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
   <init-param>
     <param-name>config-admin</param-name>
     <param-value>WEB-INF/dwr1.xml</param-value>
   </init-param>
   <init-param>
     <param-name>debug</param-name>
     <param-value>true</param-value>
   </init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
   <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
   <servlet-name>dwr-invoker1</servlet-name>
   <url-pattern>/dwr1/*</url-pattern>
</servlet-mapping>
在这种情况下,我们可以根据 J2EE security 来控制权限,针对不同 url, 加不同的角色。


二、 dwr使用篇
1、调用没有返回值和参数的JAVA方法
1.1、dwr.xml的配置
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod1"/>
</create>
</allow>
</dwr>
<allow> 标签中包括可以暴露给 javascript 访问的东西。
<create> 标签中指定 javascript 中可以访问的 java 类,并定义 DWR 应当如何获得要进行远程的类的实例。 creator="new" 属性指定 java 类实例的生成方式, new 意味着 DWR 应当调用类的默认构造函数来获得实例,其他的还有 spring 方式,通过与 IOC 容器 Spring 进行集成来获得实例等等。 javascript=" testClass " 属性指定 javascript代码访问对象时使用的名称。
<param> 标签指定要公开给 javascript 的 java 类名。
<include> 标签指定要公开给 javascript 的方法。不指定的话就公开所有方法。
<exclude> 标签指定要防止被访问的方法。
1.2、javascript中调用
首先,引入 javascript 脚本
<script src='dwr/interface/ testClass.js'></script>
<script src='dwr/engine.js'></script>
<script src='dwr/util.js'></script>
其中 TestClass.js 是 dwr 根据配置文件自动生成的, engine.js 和 util.js 是 dwr 自带的脚本文件。
其次,编写调用 java 方法的 javascript 函数
Function callTestMethod1(){
      testClass.testMethod1();
}
2、调用有简单返回值的java方法
2.1、dwr.xml的配置
配置同1.1
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod2"/>
</create>
</allow>
</dwr>
2.2、javascript中调用
首先,引入 javascript 脚本
其次,编写调用 java 方法的 javascript 函数和接收返回值的回调函数
Function callTestMethod2(){
      testClass.testMethod2(callBackFortestMethod2);
}
Function callBackFortestMethod2(data){
     // 其中 date 接收方法的返回值
     // 可以在这里对返回值进行处理和显示等等
alert("the return value is " + data);
}
其中 callBackFortestMethod2 是接收返回值的回调函数
3、调用有简单参数的java方法
3.1、dwr.xml的配置
配置同1.1
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod3"/>
</create>
</allow>
</dwr>
3.2、javascript中调用
首先,引入 javascript 脚本
其次,编写调用 java 方法的 javascript 函数
Function callTestMethod3(){
                 // 定义要传到 java 方法中的参数
      var data;
      // 构造参数
      data = “test String”;
      testClass.testMethod3(data);
}
4、调用返回JavaBean的java方法
4.1、dwr.xml的配置
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod4"/>
</create>
<convert converter="bean" match=" "com.dwr.TestBean">
                  <param name="include" value="username,password" />
</convert>
</allow>
</dwr>
<creator> 标签负责公开用于 Web 远程的类和类的方法, <convertor> 标签则负责这些方法的参数和返回类型。 convert 元素的作用是告诉 DWR 在服务器Java 对象表示和序列化的 JavaScript 之间如何转换数据类型。 DWR 自动地在 Java 和 JavaScript 表示之间调整简单数据类型。这些类型包括 Java 原生类型和它们各自的封装类表示,还有 String 、 Date 、数组和集合类型。 DWR 也能把 JavaBean 转换成 JavaScript 表示,但是出于安全性的原因,要求显式的配置, <convertor> 标签就是完成此功能的。 converter="bean" 属性指定转换的方式采用 JavaBean 命名规范, match=""com.dwr.TestBean" 属性指定要转换的 javabean 名称, <param> 标签指定要转换的 JavaBean 属性。
4.2 、javascript中调用
首先,引入 javascript 脚本
其次,编写调用 java 方法的 javascript 函数和接收返回值的回调函数
Function callTestMethod4(){
      testClass.testMethod4(callBackFortestMethod4);
}
Function callBackFortestMethod4(data){
     // 其中 date 接收方法的返回值
// 对于 JavaBean 返回值,有两种方式处理
             // 不知道属性名称时,使用如下方法
           for(var property in data){
              alert("property:"+property);
              alert(property+":"+data[property]);
           }
// 知道属性名称时,使用如下方法
           alert(data.username);
           alert(data.password);
}
其中 callBackFortestMethod4 是接收返回值的回调函数
5、调用有JavaBean参数的java方法
5.1、dwr.xml的配置
配置同4.1
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod5"/>
</create>
<convert converter="bean" match=" com.dwr.TestBean">
                  <param name="include" value="username,password" />
</convert>
</allow>
</dwr>
5.2 、javascript中调用
首先,引入 javascript 脚本
其次,编写调用 java 方法的 javascript 函数
Function callTestMethod5(){
                 // 定义要传到 java 方法中的参数
      var data;
      // 构造参数, date 实际上是一个 object
      data = { username:"user", password:"password"  }
      testClass.testMethod5(data);
}
6、调用返回List、Set或者Map的java方法
6.1、dwr.xml的配置
配置同4.1
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod6"/>
</create>
<convert converter="bean" match= "com.dwr.TestBean ">
<param name="include" value="username,password" />
</convert>
</allow>
</dwr>
注意:如果 List 、 Set 或者 Map 中的元素均为简单类型(包括其封装类)或 String 、 Date 、数组和集合类型,则不需要<convert>标签。
6.2 、javascript中调用(以返回List为例,List的元素为TestBean)
首先,引入 javascript 脚本
其次,编写调用 java 方法的 javascript 函数和接收返回值的回调函数
Function callTestMethod6(){
      testClass.testMethod6(callBackFortestMethod6);
}
Function callBackFortestMethod6(data){
     // 其中 date 接收方法的返回值
// 对于 JavaBean 返回值,有两种方式处理
             // 不知道属性名称时,使用如下方法
           for(var i=0;i<data.length;i++){
for(var property in data){
                  alert("property:"+property);
                  alert(property+":"+data[property]);
               }
}
// 知道属性名称时,使用如下方法
for(var i=0;i<data.length;i++){
               alert(data.username);
               alert(data.password);
}
}
7、调用有List、Set或者Map参数的java方法
7.1、dwr.xml的配置
<dwr>
<allow>
<create creator="new" javascript="testClass" >
<param name="class" value= "com.dwr.TestClass" />
<include method="testMethod7"/>
</create>
<convert converter="bean" match= "com.dwr.TestBean ">
<param name="include" value="username,password" />
</convert>
</allow>
<signatures>
<![CDATA[
import java.util.List;
import com.dwr.TestClass;
import com.dwr.TestBean;
TestClass.testMethod7(List<TestBean>);
]]>
</signatures>
</dwr>
<signatures> 标签是用来声明 java 方法中 List 、 Set 或者 Map 参数所包含的确切类,以便 java 代码作出判断。
7.2 、javascript中调用(以返回List为例,List的元素为TestBean)
首先,引入 javascript 脚本
其次,编写调用 java 方法的 javascript 函数
Function callTestMethod7(){
// 定义要传到 java 方法中的参数
      var data;
      // 构造参数, date 实际上是一个 object 数组,即数组的每个元素均为 object
data = [
                      {
                         username:"user1",
                         password:"password2"
                      },
                      {
                         username:"user2",
                         password:" password2"
                      }
                  ];
      testClass.testMethod7(data);
}
注意:
1、 对于第 6 种情况,如果 java 方法的返回值为 Map ,则在接收该返回值的 javascript 回调函数中如下处理:
function callBackFortestMethod(data){
           // 其中 date 接收方法的返回值
           for(var property in data){
                  var bean = data[property];
                  alert(bean.username);
                  alert(bean.password);
              }
}
2、 对于第 7 种情况,如果 java 的方法的参数为 Map (假设其 key 为 String , value 为 TestBean ),则在调用该方法的 javascript 函数中用如下方法构造要传递的参数:
function callTestMethod (){
              // 定义要传到 java 方法中的参数
              var data;
              // 构造参数, date 实际上是一个 object ,其属性名为 Map 的 key ,属性值为 Map 的 value
              data = {
                         "key1":{
                             username:"user1",
                            password:"password2"
                         },
                         "key2":{
                            username:"user2",
                            password:" password2"
                         }
                     };
              testClass.testMethod(data);
}
并且在 dwr.xml 中增加如下的配置段
<signatures>
<![CDATA[
import java.util.List;
import com.dwr.TestClass;
import com.dwr.TestBean;
TestClass.testMethod7(Map<String,TestBean>);
]]>
</signatures>
3、 由以上可以发现,对于 java 方法的返回值为 List(Set) 的情况, DWR 将其转化为 Object 数组,传递个 javascript ;对于 java 方法的返回值为 Map 的情况, DWR 将其转化为一个 Object ,其中 Object 的属性为原 Map 的 key 值,属性值为原 Map 相应的 value 值。
4、 如果 java 方法的参数为 List(Set) 和 Map 的情况, javascript 中也要根据 3 种所说,构造相应的 javascript 数据来传递到 java 中。

posted @ 2008-06-16 15:55 FaithChen 阅读(171) | 评论 (0)编辑 收藏


2008年3月6日

 (1)使用 ? 指定参数
...
Query query = session.createQuery("from Student s where
              s.age > ? and s.name like ? ");
query.setInteger(0,18);
query.setString(1,"%abc%");
...
(2)使用 : 后跟变量的方法设置参数
...
Query query = session.createQuery("from Student s where
              s.age > :minAge and s.name like :likeName ");
query.setInteger("minAge",18);
query.setString("likeName","%ABC%");
...
(3)setEntity()方法

setEntity()方法把参数与一个持久类的实例绑定,例如下面的示例
...
Team team = (Team)session.get(Team.class,"5f45saf45sdf456f");
Query query = session.createQuery("from Student s where s.team = :team");
query.setEntity("team",team);  //设置参数为team实例
...
注:上述的team对象可以是持久对象也可以是脱管对象

(4)setParameter()方法

setParameter()方法的全称是setParameter(String paraName,实例,实例类型),这个方法
可以绑定任何类型的参数.其中第三个参数可以省略,hibernate要以根据实例推断出绝大部分
对应的映射类型.
下面将(3)中的代码做一下改动
query.setParameter("team",team,Hibernate.entity(Team.class)).
或者query.setparameter("team",team).

(5)setPorperties()方法

该方法的全称是setProperties(类实例).它将类实例的属性名与参数值相对应
...
Student student = new Student();
student.setAge("18");
Query query = sesion.createQuery("from Student s where s.age = :age");
query.setProperties(student);  //设置参数为student对象
...
注意:HQL语句中的变量age必须和student的属性age同名,否则会出错.

posted @ 2008-03-06 16:18 FaithChen 阅读(594) | 评论 (0)编辑 收藏

四种xml操作方式的基本使用方法

xml文件:

<?xml version="1.0" encoding="GB2312"?>
<RESULT>
    <VALUE>
        <NO>A1234</NO>
       <ADDR>四川省XX县XX镇XX路X段XX号</ADDR>
    </VALUE>
    <VALUE>
        <NO>B1234</NO>
       <ADDR>四川省XX市XX乡XX村XX组</ADDR>
    </VALUE>
</RESULT>

1)DOM

import java.io.*;
import java.util.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;

public class MyXMLReader{
 public static void main(String arge[]){

  long lasting =System.currentTimeMillis();
  try{ 
   File f=new File("data_10k.xml");
   DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
   DocumentBuilder builder=factory.newDocumentBuilder();
   Document doc = builder.parse(f);
   NodeList nl = doc.getElementsByTagName("VALUE");
   for (int i=0;i<nl.getLength();i++){
    System.out.print("车牌号码:" + doc.getElementsByTagName("NO").item(i).getFirstChild().getNodeValue());
    System.out.println("车主地址:" + doc.getElementsByTagName("ADDR").item(i).getFirstChild().getNodeValue());
   }
  }catch(Exception e){
   e.printStackTrace();
}

2)SAX

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;

public class MyXMLReader extends DefaultHandler {

 java.util.Stack tags = new java.util.Stack();
 public MyXMLReader() {
  super();
   }

 public static void main(String args[]) {
  long lasting = System.currentTimeMillis();
  try {
   SAXParserFactory sf = SAXParserFactory.newInstance();
   SAXParser sp = sf.newSAXParser();
   MyXMLReader reader = new MyXMLReader();
   sp.parse(new InputSource("data_10k.xml"), reader);
  } catch (Exception e) {
   e.printStackTrace();
  }

  System.out.println("运行时间:" + (System.currentTimeMillis() - lasting) + "毫秒");}
  public void characters(char ch[], int start, int length) throws SAXException {
  String tag = (String) tags.peek();
  if (tag.equals("NO")) { 
   System.out.print("车牌号码:" + new String(ch, start, length));
    }
    if (tag.equals("ADDR")) {
  System.out.println("地址:" + new String(ch, start, length));
    }
   }

  public void startElement(String uri,String localName,String qName,Attributes attrs) {
  tags.push(qName);}

3) JDOM

import java.io.*;
import java.util.*;
import org.jdom.*;
import org.jdom.input.*;

public class MyXMLReader {

 public static void main(String arge[]) {
  long lasting = System.currentTimeMillis();
  try {
   SAXBuilder builder = new SAXBuilder(); 
   Document doc = builder.build(new File("data_10k.xml")); 
   Element foo = doc.getRootElement(); 
   List allChildren = foo.getChildren(); 
   for(int i=0;i<allChildren.size();i++) { 
    System.out.print("车牌号码:" + ((Element)allChildren.get(i)).getChild("NO").getText());
    System.out.println("车主地址:" + ((Element)allChildren.get(i)).getChild("ADDR").getText());
   }
  } catch (Exception e) {
   e.printStackTrace();
}

}

4)DOM4J

import java.io.*;
import java.util.*;
import org.dom4j.*;
import org.dom4j.io.*;

public class MyXMLReader {

 public static void main(String arge[]) {
  long lasting = System.currentTimeMillis();
  try {
   File f = new File("data_10k.xml");
   SAXReader reader = new SAXReader();
   Document doc = reader.read(f);
   Element root = doc.getRootElement();
   Element foo;
   for (Iterator i = root.elementIterator("VALUE"); i.hasNext();) {
    foo = (Element) i.next();
    System.out.print("车牌号码:" + foo.elementText("NO"));
    System.out.println("车主地址:" + foo.elementText("ADDR"));
   }
  } catch (Exception e) {
   e.printStackTrace();
    }
}

posted @ 2008-03-06 11:09 FaithChen 阅读(178) | 评论 (0)编辑 收藏


2008年3月5日

简介:
DWR可以帮助开发人员完成应用AJAX技术的web程序,它可以让浏览器上的javascript方法调用运行在web服务器上java方法。
DWR主要由两部门组成。javascript与web服务器通信并更新web页;运行在web服务器的Servlet处理请求并把响应发回浏览器。
DWR采用新颖的方法实现了AJAX(本来也没有确切的定义),在java代码基础上动态的生成javascript代码。web开发者可以直接调用这些javascript代码,然而真正的代码是运行在web服务器上的java code。出与安全考虑,开发者必须配置哪些java class暴露给DWR.(dwr.xml)
DWR不认为浏览器和web服务器之间协议重要,把系统界面放在首位。最大挑战是java method call的同步特征与ajax异步特性之间的矛盾。在异步模型里,结果只有在方法结束后才有效。DWR解决了这个问题,把回调函数当成参数传给方法,处理完成后,自动调用回调方法。
配置:

  1. web.xml: <servlet>
        <servlet-name>dwr-invoker</servlet-name>
        <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
                   <param-name>debug</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>  
                   <param-name>crossDomainSessionSecurity</param-name>   
                   <param-value>false</param-value>  
            </init-param>
       </servlet>

       <servlet-mapping>
         <servlet-name>dwr-invoker</servlet-name>
         <url-pattern>/dwr/*</url-pattern>
       </servlet-mapping>

  2. dwr.xml:<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr/dwr20.dtd">
    <dwr>
     <allow>
      <create creator="spring" javascript="main_MenuCatalogDWR" scope="page">
       <param name="beanName" value="/main/MenuCatalogDWR"/>
      </create>
      <create creator="spring" javascript="main_TreeDWR" scope="page">
       <param name="beanName" value="/main/TreeDWR"/>
      </create>
      <create creator="spring" javascript="main_OperateFilterDWR" scope="page">
       <param name="beanName" value="/main/OperateFilterDWR"/>
      </create>
      <create creator="spring" javascript="main_RightTreeDWR" scope="page">
       <param name="beanName" value="/main/RightTreeDWR"/>
      </create>
      <convert converter="dom4j" match="org.directwebremoting.convert.DOM4JConverter">
      </convert>
      <convert converter="dom" match="org.directwebremoting.convert.DOMConverter">
      </convert>
     </allow>
    </dwr>

   3.jsp页面设置:
        //以下两行是dwr所必需的
        <script type='text/javascript' src="<c:url value='/dwr/engine.js'/>"></script>
                              <script type='text/javascript' src="<c:url value='/dwr/util.js'/>"></script> 
        <script type='text/javascript' src="<c:url value='/dwr/interface/main_MenuCatalogDWR.js'/>"></script>
说明:<script type='text/javascript' src="<c:url value='/dwr/engine.js'/>"></script>
            <script type='text/javascript' src="<c:url value='/dwr/util.js'/>"></script> 是dwr所必需的
   <script type='text/javascript' src="<c:url value='/dwr/interface/main_MenuCatalogDWR.js'/>"></script>主要作用是:
            dwr/interface/这种请求到来,(如上面的<script type='text/javascript' src="<c:url  value='/dwr/interface/main_MenuCatalogDWR.js'/>"></script>)DWR做一件伟大的事。把我们在WEB-INF/dwr.xml中的
           <create creator="spring" javascript="main_MenuCatalogDWR" scope="page">
                  <param name="beanName" value="/main/MenuCatalogDWR"/>
           </create>转化为javascript函数。 

4.beanName配置(本项目spring配置文件为action-servlet.xml)
 <bean name="/main/MenuCatalogDWR" class="com.icsshs.webapp.main.MenuCatalogDWR" singleton="false">
        <property name="hsRoleRightManager">
            <ref bean="hsRoleRightManager"/>
        </property>
    </bean>
5.jsp页面调用:
function menucatalog(){
     main_MenuCatalogDWR.execute("",callbackok);
    }
    function callbackok(data){
        var root0=data.documentElement;
        if (root0.childNodes.length>0){
            if (root0.childNodes(0).childNodes.length==0) return;
            $("mainmenu").innerHTML=root0.childNodes(0).childNodes(0).text;
            key=root0.childNodes(1).childNodes(0).text;
            if (parent.frames.leftFrame.document.readyState == "complete"){
                setmenuclick(key);
            }else{
                setTimeout("setmenuclick('"+key+"')",500);
            }
        }
    }

说明:callbackok为回调函数,data为dwr返回的结果集

posted @ 2008-03-05 17:40 FaithChen 阅读(228) | 评论 (0)编辑 收藏


仅列出标题  

posts - 4, comments - 0, trackbacks - 0, articles - 4

Copyright © FaithChen