博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【斗医】【5】Web应用开发20天
阅读量:6158 次
发布时间:2019-06-21

本文共 13725 字,大约阅读时间需要 45 分钟。

三、页面跳转封装

【接上】在《【斗医】【4】Web应用开发50天》中页面跳转封装只做了如下工作:名称为action的Servlet启动时,解析/WEB-INF/config下各业务模块的XXX-action.xml,并把其业务封装为FrameBusiness对象缓存到全局变量Map中:

083741396.png

接下来要完成如下功能:

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文件,在里面填充如下内容:

    
        
action
        
com.medical.frame.FrameLauncher
        
1
    
    
        
action
        
*.act
    
    
         
index.html
    


【备注】:该内容在前面已配置过,这里再强调一次一方面是理顺思路,另一方面是强调Web容器处理HTTP请求的流程。


2、把HttpServletRequest请求均交给get处理

打开D:\medical\src\com\medical\frame\FrameLauncher.java,把doPost()处理交给doGet():

@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException{    doGet(request, response);}

3、为了保持FrameLauncher功能的简洁性,这里定义一个FrameDispatcher类,FrameLauncher.doGet()的业务逻辑交给FrameDispatcher处理:

I、定义com.medical.frame.FrameDispatcher.java类

public class FrameDispatcher{    private HttpServlet servlet = null;    /**     * 构造器     */    public FrameDispatcher(HttpServlet servlet)    {        this.servlet = servlet;    }    public void process(HttpServletRequest request, HttpServletResponse response) throws FrameException    {        // TODO    }}

II、FrameLauncher.doGet()交给FrameDispatcher对象处理

@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException{    FrameDispatcher dispatcher = new FrameDispatcher(this);    try    {        dispatcher.process(request, response);    }    catch (FrameException e)    {        logger.error(e.getErrorDesc(), e);    }}

4、定义FrameDispatcher.getRequestName(HttpServletRequest)方法从HttpServletRequest对象中解析出请求名称(比如从/medical/index.act中获取index

/** * 由HttpServletRequest对象获取请求名称 */private String getRequestName(HttpServletRequest request){    String name = request.getRequestURI();    if (name == null)    {        return null;    }    if (name.endsWith(FrameConstant.BUS_NAME_POSTFIX) == false)    {        return null;    }    int headIndex = name.lastIndexOf("/") + 1;    int rearIndex = name.lastIndexOf(FrameConstant.BUS_NAME_POSTFIX);    return name.substring(headIndex, rearIndex);}

5、修改FrameDispatcher.process()方法,其功能是由业务名称获取对应的业务对象,然后由业务对象的forward来决定跳转页面

220339683.png

6、下面初步测试一下:

I、修改D:\medical\war\index.html文件,该文件加载完就跳转到index.act

            medical        
            top.location="index.act";              

II、修改D:\medical\war\WEB-INF\config\sm\system-action.xml文件

    
        
         
    

当系统加载时名称为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>标题:

            medical                      

This is main page!

    

IV、启动Tomcat服务,在浏览器中输入http://localhost:8080/medical,会发现页面直接把<h1>This is main page!</h1>显示出来了,见下图:

215023971.png


【备注】:细心的读者可能发现了页面进入了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

/** * 斗医系统业务缺省跳转处理器 * * @author qingkechina */public class FrameDefaultAction{    /**     * 请求对象     */    protected HttpServletRequest request = null;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /**     * 响应对象     */    protected HttpServletResponse response = null;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /**     * 会话对象     */    protected HttpSession session = null;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         public void setRequest(HttpServletRequest request)    {        this.request = request;    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         public void setResponse(HttpServletResponse response)    {        this.response = response;    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         public void setSession(HttpSession session)    {        this.session = session;    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /**     * 读取Request对象中的参数     */    public String getParameter(String param)    {        return request.getParameter(param);    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /**     * 缺省响应动作     */    public String execute() throws FrameException    {        return null;    }}


【备注】:这里没有使用接口或抽象类,建议读者在自已实现该功能时最好能抽象出接口,这样做的好处可参见设计模式相关内容


II、定义动作工厂,可以根据XXX-action.xml中的业务business-class名称把相关的跳转动作类反射出来

package com.medical.frame;import com.medical.frame.constant.FrameConstant;import com.medical.frame.constant.FrameErrorCode;/** * 斗医系统业务跳转动作工厂类 * * @author qingkechina */public class FrameActionFactory{    private static FrameActionFactory instance = new FrameActionFactory();                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              private FrameActionFactory()    {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              public static FrameActionFactory getInstance()    {        return instance;    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              /**     * 反射跳转动作实现类     */    public FrameDefaultAction implement(String className) throws FrameException    {        if (className == null || className.trim().length() == 0)        {            className = FrameConstant.FORWARD_DEFAULT_ACTION;        }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      try        {            return (FrameDefaultAction) Class.forName(className).newInstance();        }        catch (Exception e)        {            throw new FrameException(FrameErrorCode.JAVA_REFLECT_ERROR, e);        }    }}

III、修改FrameDispatcher.process()方法,在其中增加跳转动作逻辑部分的处理(即下图红框部分):

215156404.png

8、测试跳转功能:

I、打开D:\medical\war\WEB-INF\config\sm\system-action.xml文件,对"index.act"动作指定逻辑响应处理类Demo

    
        
        
    

II、定义com.medical.frame.forward.Demo类,该类继承FrameDefaultAction类,并重写execute()方法

package com.medical.frame.forward;import com.medical.frame.FrameDefaultAction;import com.medical.frame.FrameException;public class Demo extends FrameDefaultAction{    @Override    public String execute() throws FrameException    {        // 这里可以处理一些逻辑        System.out.println("===================这里可以进行逻辑处理");        // 逻辑处理完后跳转到相应页面        return "login.act";    }}

从代码上可以看出,这里逻辑处理完之后,就直接跳转到login.act对应的页面

III、打开D:\medical\war\WEB-INF\config\sm\system-action.xml文件,修改"login.act"对应的业务配置

    
        
        
    

IV、在D:\medical\war\module\login下创建login.html文件,填充如下内容:

            medical                

This is Login page!

    

V、启动Tomcat后在浏览器中输入http://localhost:8080/medical回车,查看页面,页面上输出“This is Login page!”,这说明页面是跳转到了login.html上,如图:

220318215.png


【备注】:上面的测试也说明当业务配置了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://buifa.baihongyu.com/

你可能感兴趣的文章
io.js 1.0.x发布
查看>>
一文剖析区块链现状:丛林法则下的胜者
查看>>
《The Corporate Startup》作者访谈
查看>>
分布式数据库TiDB是如何结合OLTP和OLAP的?
查看>>
为什么已有Elasticsearch,我们还要重造实时分析引擎AresDB?
查看>>
腾讯云答治茜:云计算为独角兽和传统企业提供了哪些沃土?
查看>>
Java8 lambda支持
查看>>
HTML5移动端音乐播放器(启蒙篇)
查看>>
sass笔记-1|Sass是如何帮你又快又好地搞定CSS的
查看>>
angular组件-特殊的瀑布流(原创)
查看>>
夯实基础js - 语句篇
查看>>
微信应用号(小程序)资源汇总(1010更新)
查看>>
Vue-Cleave - 在Vue中使用CleaveJS格式化你的输入内容
查看>>
Kubernetes 1.2新功能解析:使用Deployment
查看>>
Consul入门04 - Consul集群
查看>>
Electron初步【02】--第一个Electron App
查看>>
Mysql 架构及优化之-索引优化
查看>>
[LintCode] Simplify Path [字符串操作]
查看>>
【03】把 Elasticsearch 当数据库使:简单指标
查看>>
OneAPM Cloud Test——系统性能监控神器
查看>>