附录内部变量

 

内置变量是kangaroo-egg所保留的变量,用以完成特殊的功能。用户自定义的变量名不能与内部变量名重复,不过内部变量名都是以$ke$开头的,所以一般不会与用户自定义的变量名相同。接下来我们就来看看内置变量的用途。

 

 

F5.1 $ke$sourceLineNumber

$ke$sourceLineNumber变量的类型是int型。

此内部变量记录了当前在动态文件中的行数,比如此变量在动态文件第4行出现,那么此变量就是4。可是这个变量有什么用呢?我们来看一下ke_sourceLineNumber.dqm这个例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

<form method="POST" action="">

  <p>只能输入除了(5060100110)以外的数字:

  <input type="text" name="inputVar" size="20">

  <input type="submit" value="Submit" name="B1"></p>

</form>

 

 

<%

String input = request.getParameter("inputVar");

if (input != null && input.length() > 0) {

  int inputInt;

  try {

    inputInt = Integer.parseInt(input);

  }

  catch(NumberFormatException ex) {

    outErr(out, 1);

    return;

  }

 

  if (inputInt >= 50 && inputInt <= 60) {

    outErr(out, 2);

    return;

  }

 

  if (inputInt >= 100 && inputInt <= 110) {

    outErr(out, 3);

    return;

  }

 

  out.print("输入正确");

}

 

%>

<%!

private static void outErr(AbstractMyOut out, int errId) throws IOException {

  out.print("输入的数字不符合规则 ErrCode = " + errId);

}

%>

 

上面的程序运行界面如下:

F5-1-1

 

此程序要求用户只能输入除了5060(源程序2023行)和100110(源程序2528行)以外的任何数字,如果输入了非数字以及5060100110以内的数字则会报错,但报错信息只是提示“输入的数字不符合规则”(源程序3537行),为此加上出错编号以区分具体错误。

于是又一个问题,如果有很多错误源,那么你就要手动添加删除错误编号了。比如上面程序需要再增加一个非法数集7585,且要增加在检查100110错误前,那么你就需要将检查100110的错误编号改为4,同时增加检查7585的错误编号3,修改后的源程序如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

<form method="POST" action="">

  <p>只能输入除了(50607585100110)以外的数字:

  <input type="text" name="inputVar" size="20">

  <input type="submit" value="Submit" name="B1"></p>

</form>

 

 

<%

String input = request.getParameter("inputVar");

if (input != null && input.length() > 0) {

  int inputInt;

  try {

    inputInt = Integer.parseInt(input);

  }

  catch(NumberFormatException ex) {

    outErr(out, 1);

    return;

  }

 

  if (inputInt >= 50 && inputInt <= 60) {

    outErr(out, 2);

    return;

  }

 

  if (inputInt >= 75 && inputInt <= 85) {

    outErr(out, 3);

    return;

  }

 

  if (inputInt >= 100 && inputInt <= 110) {

    outErr(out, 4);

    return;

  }

 

  out.print("输入正确");

}

 

%>

<%!

private static void outErr(AbstractMyOut out, int errId) throws IOException {

  out.print("输入的数字不符合规则 ErrCode = " + errId);

}

%>

 

或许你会说上面的修改很简单,但是请试想一下如果有很多出错源会怎样,你要将那些位于新增出错编号后的老出错编号重新整理,这样是不是很麻烦?不过有了$ke$sourceLineNumber这个变量事情就变得简单多了,请看下面的源程序:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

<form method="POST" action="">

  <p>只能输入除了(50607585100110)以外的数字:

  <input type="text" name="inputVar" size="20">

  <input type="submit" value="Submit" name="B1"></p>

</form>

 

 

<%

String input = request.getParameter("inputVar");

if (input != null && input.length() > 0) {

  int inputInt;

  try {

    inputInt = Integer.parseInt(input);

  }

  catch(NumberFormatException ex) {

    outErr(out, $ke$sourceLineNumber);

    return;

  }

 

  if (inputInt >= 50 && inputInt <= 60) {

    outErr(out, $ke$sourceLineNumber);

    return;

  }

 

  if (inputInt >= 75 && inputInt <= 85) {

    outErr(out, $ke$sourceLineNumber);

    return;

  }

 

  if (inputInt >= 100 && inputInt <= 110) {

    outErr(out, $ke$sourceLineNumber);

    return;

  }

 

  out.print("输入正确");

}

 

%>

<%!

private static void outErr(AbstractMyOut out, int errId) throws IOException {

  out.print("输入的数字不符合规则 ErrCode = " + errId);

}

%>

 

当再次运行上面的程序,如果出错你会发现出错编号已经变成了源代码抛出错误的行数,同时以后不管在哪里要增加出错源,也不需要关心以前定义的出错编号,因为编译器会帮你重新定义$ke$sourceLineNumber的值,你所做的就是写一个固定的内部变量$ke$sourceLineNumber

那么接下来我们需要讨论另一个问题,上面的程序为什么不直接提示具体错误而非要用数字作为提示信息呢?似乎这个问题很难回答,不同的开发者有不同的考虑,不过有一点可以肯定如果提示信息中含有容易辨别的编号,当发生的错误需要回馈给开发人员,则使用编号更易于定位错误区域,而根据出错的行号定位出错区域则再简单也不过了。

现在再来看一下$ke$sourceLineNumber实现的原理,其实很简单,在将动态文件编译成class文件前编译器会将$ke$sourceLineNumber替换成其所在行的行数,之后再编译。