原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://qingkechina.blog.51cto.com/5552198/1317441
三、页面跳转封装
【接上】在《
接下来要完成如下功能:
Web容器(Tomcat)接受到HTTP请求后,Web容器把HTTP转换为HttpServletRequest对象,然后根据请求名称匹配规则找到相应的Servlet,调用servlet-class对应类的doGet()或doPost()方法,在该方法中根据请求名称从全局缓存(FrameCache.businessMap)中读取业务对象(FrameBusiness),由FrameBusiness对象跳转到相应的页面。
1、配置名称为action的Servlet。
打开D:\medical\war\WEB-INF\web.xml文件,在里面填充如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
【备注】:该内容在前面已配置过,这里再强调一次一方面是理顺思路,另一方面是强调Web容器处理HTTP请求的流程。
2、把HttpServletRequest请求均交给get处理
打开D:\medical\src\com\medical\frame\FrameLauncher.java,把doPost()处理交给doGet():
1 2 3 4 5 |
|
3、为了保持FrameLauncher功能的简洁性,这里定义一个FrameDispatcher类,FrameLauncher.doGet()的业务逻辑交给FrameDispatcher处理:
I、定义com.medical.frame.FrameDispatcher.java类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
II、FrameLauncher.doGet()交给FrameDispatcher对象处理
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
4、定义FrameDispatcher.getRequestName(HttpServletRequest)方法从HttpServletRequest对象中解析出请求名称(比如从/medical/index.act中获取index)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
5、修改FrameDispatcher.process()方法,其功能是由业务名称获取对应的业务对象,然后由业务对象的forward来决定跳转页面
6、下面初步测试一下:
I、修改D:\medical\war\index.html文件,该文件加载完就跳转到index.act
1 2 3 4 5 6 7 8 9 |
|
II、修改D:\medical\war\WEB-INF\config\sm\system-action.xml文件
1 2 3 4 5 6 |
|
当系统加载时名称为action的Servlet会把该文件读入全局缓存。访问index.html时执行top.location="index.act",action接受到"*.act"就执行FrameDispatcher.process()方法,从而跳转到/module/main/main.html页面
III、在D:\medical\war\module\main\下创建main.html文件,这里只是为了测试,所以main.html只是输出一个<h1>This is main page!</h1>标题:
1 2 3 4 5 6 7 8 9 |
|
IV、启动Tomcat服务,在浏览器中输入http://localhost:8080/medical,会发现页面直接把<h1>This is main page!</h1>显示出来了,见下图:
【备注】:细心的读者可能发现了页面进入了main.html,但地址却依旧停留在index.act处,见上图。其中原因请大家在谷歌上搜索一下“JSP forward”,有文章会给出详细说明。
7、再仔细考虑一个场景:在跳转到页面A之前,(1)有可能需要把当前页面的数据保存在数据库中,(2)或者需要进行一些逻辑判断,符合条件才能进入A页面,不符合则不能进入A页面。这就是当时XXX-action.xml中业务定义"business-class"的原因,但我们的FrameDispatcher.process()并没有这方面的处理,现在进行修改:
I、定义缺省跳转动作执行类com.medical.frame.FrameDefaultAction.java
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 44 45 46 47 48 49 50 51 52 53 |
|
【备注】:这里没有使用接口或抽象类,建议读者在自已实现该功能时最好能抽象出接口,这样做的好处可参见设计模式相关内容
II、定义动作工厂,可以根据XXX-action.xml中的业务business-class名称把相关的跳转动作类反射出来
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 |
|
III、修改FrameDispatcher.process()方法,在其中增加跳转动作逻辑部分的处理(即下图红框部分):
8、测试跳转功能:
I、打开D:\medical\war\WEB-INF\config\sm\system-action.xml文件,对"index.act"动作指定逻辑响应处理类Demo
1 2 3 4 5 6 |
|
II、定义com.medical.frame.forward.Demo类,该类继承FrameDefaultAction类,并重写execute()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
从代码上可以看出,这里逻辑处理完之后,就直接跳转到login.act对应的页面
III、打开D:\medical\war\WEB-INF\config\sm\system-action.xml文件,修改"login.act"对应的业务配置
1 2 3 4 5 6 |
|
IV、在D:\medical\war\module\login下创建login.html文件,填充如下内容:
1 2 3 4 5 6 7 8 9 |
|
V、启动Tomcat后在浏览器中输入http://localhost:8080/medical回车,查看页面,页面上输出“This is Login page!”,这说明页面是跳转到了login.html上,如图:
【备注】:上面的测试也说明当业务配置了business-class,则相应动作执行类跳转动作的优先级要高于<forward>
OK,到这里跳转封装的基本功能已完成,可能会有人问:“只是一个跳转,使用HTML的<a>标签,岂不是更简单,何苦折腾这么一通呢?”
有这个疑问是一件好事情,说明大家都进行了思考。正如上面所说,一些逻辑性处理需要在服务端进行(如有些场景需要根据逻辑判断决定跳转到哪个页面,若纯使用WEB前端处理,显的客户端比较胖或者叫富客户端),另外把眼光放远一些,试想Struts做了哪些事情呢?除了过滤器之外无非也是逻辑判断,数据加工后的页面显示。
下面我们再理顺一下思路:
(1)启动Tomcat时,会加载web.xml,根据web.xml把名称为action的Servlet拉起
(2)名称为action的Servlet启动时,根据其配置规则反射FrameLauncher类,并调用它的init()方法
(3)在init()方法中会读取运行环境中的XXX-action.xml文件,解析该文件后把动作名及动作名对应的业务对象FrameBusiness缓存入全局变量
(4)当在浏览器中输入http://localhost:8080/medical时,Tomcat根据web.xml配置首先加载index.html
(5)在index.html加载完毕后直接使用top.location="index.act"跳转到index.act
(6)tomcat服务器一看到是.act结尾的请求,就使用FrameLauncher的doGet()方法来处理
(7)FrameLauncher.doGet()委托给FrameDispatcher.process(),在process()中它根据index.act在全局缓存中查找FrameBusiness
(8)首先看一下FrameBusiness是否有class-name,若有就获取逻辑处理类指定的路径;若没有就使用forward指定的路径
(9)然后把该路径交给HttpServlet进行具体的页面跳转
本文出自 “青客” 博客,请务必保留此出处http://qingkechina.blog.51cto.com/5552198/1317441