在前面3.4节和10.4节都介绍了主机或虚拟主机的/WEB-INF/classes和/WEB-INF/lib目录下可以存放各种class或jar文件,如果动态文件需要这些类则服务器会自动从这二个目录中寻找后加载。但是存放在这些目录下的类只能被当前所处的主机或虚拟主机所读取到,其它主机和虚拟主机是无法读取到的。不过有的时候还是需要载入的类能够被主机和所有虚拟主机都访问到,比如JDBC的驱动类等,那么这个时候该如何做呢?当然你完全可以将类似JDBC驱动类放入一个个主机或虚拟主机的/WEB-INF/classes和/WEB-INF/lib目录下。不过这样似乎有点麻烦,也不高效,因为10.4节提到过在这二个目录下的类会载入到类缓存中,而主机和每个虚拟主机都有自己独立的类缓存,这样就会造成多个类缓存中存放着同一个需要的类型。
接下来所介绍的就是如何载入公用类。还记得1.2节中介绍的run.bat和run.sh这二个启动脚本吗?我们可以通过这二个服务脚本来加载公用类,首先来看windows平台下,例如公用类是以class文件形式存在于c:\commclasses目录下,那么要加载此目录下的这些公用类,我们只需在原有的run.bat中增加如图4-1-1中的红框内容。
图4-1-1
而如果公用类是已打包的jar或者zip文件,则必须在脚本中一个个写明,例如需载入的文件位于c:\a.jar和d:\b.zip,则修改如下:
图4-1-2
再来看linux和unix平台下,如果公用类是以class文件形式存在于/commclasses目录下,那么要加载这些公用类,我们只需在原有的run.sh中增加如图4-1-3中的红框内容。
图4-1-3
而如果公用类是已打包的jar或者zip文件,则必须在脚本中一个个写明,例如需载入的文件位于/a.jar和/b.zip,则修改如下:
图4-1-4
注意:windows平台下载入多个类路径时分隔符为分号,而linux和unix平台下为冒号。通过以上方法载入的类是不会进入类缓存中的。 |
因为服务器会自动载入安装目录下的classes主程序目录(参见1.2节),所以如果以class文件形式存在于此目录下是会被自动载入的,即不需要在启动脚本中再加入此类路径,不过如果是jar或zip打包文件的话就像前面所说的还是要在启动脚本中一个个加入。
前面2.3节中所提到的用户可以编写自己的java程序用于和服务器一同启动,而这些用户程序的载入也必须用上面介绍的方法,不能放在某个主机或虚拟主机的classes或lib目录下。同样2.4节介绍的needPassword部分中自己编写的验证密码程序也必须是这样载入。
在前面2.4节的needPassword部分中有介绍到自己编写的验证密码程序必须要继承com.kangaroo_egg.webserver.CheckServerPSW这个接口,于是问题来了当我们编写自己的密码保护类时去哪里载入CheckServerPSW这个接口?其实很简单只要将服务器安装的classes目录也设置为类搜索路径即可(服务器安装的clases目录请参见1.2节)。例如我么自己所编写的密码验证类是d:\myclass\MyCheck.java,而服务器classes的路径是c:\webserver\classes。那么如果直接去编译MyCheck.java会发生什么结果呢?如下图所看到的会提示找不到CheckServerPSW这个接口。
图4-2-1
于是我们将c:\webserver\classes加入类路径,再次编译就会看到成功了。
图4-2-2
所以遇到编译时要用到服务器类就可以采用上面的方法。如果使用JBuilder、eclipse这些IDE工具进行编写,那么请参考这些IDE工具说明用以设置需要的类路径。
在web程序中很多会用到javaBean,而在javaBean中处理内置对象也是很必要的,如下面的例子。
login.dqm的源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<%@bean id="login" class="test.Login" scope="page"%> <% if (session.getAttribute("username") == null) { if (login.action(request, session)) { out.print("Login ok."); } else {%> <form method="POST" action=""> username: <input type="text" name="username" size="20"></p> password: <input type="password" name="password" size="20"></p> <input type="submit" value="Submit" name="B1"> </form> <% } } else { out.print("Login ok."); }%> |
Login.java的源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package test;
public class Login { public Login() { }
public boolean action(com.kangaroo_egg.dqm.DRequestItface request, com.kangaroo_egg.dqm.DSessionItface session) { //判断用户输入的用户名和密码是否正确 String username = request.getParameter("username"); String password = request.getParameter("password"); //如果密码正确则将用户名增加到session中 if ("admin".equals(username) && "123456".equals(password)) { session.setAttribute("username", username); return true; } return false; } } |
login.dqm用于登录界面,如果先前没有登录过则会显示登录界面(如图4-2-3),如果登录成功则会提示"Login Ok."。
图4-2-3
那么首先来看Login.java的源程序,此程序功能就是进行密码检测,这里我们使用固定的用户名密码(源程序13行),如果验证通过则在session中写用户名的同时返回true值(源程序14、15行),如果验证不通过则直接返回false值。而用户输入的用户名和密码是从request中读取的(源程序10和11行),程序中需要使用到的request和session对象是从login.dqm中传进来的(Login.java源程序7和8行,login.dqm源程序第4行)。因为Login.java中含有了request和session这二个对象(Login.java源程序7和8行),所以需要用到服务器类,而载入的方法就是前面介绍过的。
我们再来看login.dqm,如果用户输入的用户名和密码正确则显示"Login Ok."(源程序4到6行)。如果不正确则显示登录界面(源程序6到11行)。如果session中含有用户名则说明先前成功登录过,则也显示"Login Ok."(源程序15到17行)。可以看到将内置对象传入JavaBean的做法可以使web程序更清晰且易于维护。读者可以用用户名admin和密码123456可以测试本例子。
表4-2-1列出了6个内部对象的类型。
内置对象 |
类型 |
out |
com.kangaroo_egg.dqm.AbstractMyOut |
request |
com.kangaroo_egg.dqm.DRequestItface |
response |
com.kangaroo_egg.dqm.DResponseItface |
session |
com.kangaroo_egg.dqm.DSessionItface |
application |
com.kangaroo_egg.dqm.DApplicationItface |
command |
com.kangaroo_egg.dqm.DCommand |
表4-2-1