zoukankan      html  css  js  c++  java
  • Struts1的实现原理

    一 开文背景 -- 废话讲一段~

      本文借助动力节点-王勇老师的视频教程中的引例来了解struts1的实现原理,虽然现在已经很少使用struts1了,但是了解了其原理之后,对了解其他mvc框架还是有较大的帮助的.

    二 简介 -- 切入主题

      struts1主要实现从请求到servlet的映射.

      e.g. 现有的一个业务为实现用户的添加删除修改,按照原有的model2的原理可以实现上述功能.

      2.1没有struts1之前的基于model2 mvc的实现.

      直接在servlet中实现如下代码:

            String username = request.getParameter("username");
            UserManager userManager = new UserManager();
            String forward = "";
            if ("/servlet/delUser".equals(path)) {
                userManager.del(username);
                forward = "/del_success.jsp";
            }else if ("/servlet/addUser".equals(path)) {
                userManager.add(username);
                forward = "/add_success.jsp";
            }else if ("/servlet/modifyUser".equals(path)) {
                userManager.modify(username);
                forward = "/modify_success.jsp";
            }else if ("/servlet/queryUser".equals(path)) {
                List userList = userManager.query(username);
                request.setAttribute("userList", userList);
                forward = "/query_success.jsp";
            }else {
                throw new RuntimeException("请求失败");
            }
            request.getRequestDispatcher(forward).forward(request, response);

      到现在,基本的功能是已经实现了,但是看着上面的代码就像吐啊~一坨的if-else,复杂的每一个if-else节点处理~毫无半点的扩展性可言.

      解决办法:

        将每一个小的业务处理单独来处理.抽象出一个借口Action,抽象方法:execute(HttpServletRequest,HttpServletResponse). struts1中返回一个ActionForword对象.

              public interface Action {

    public String execute(HttpServletRequest request, HttpServletResponse response)
                throws Exception;
            }

      每一个小的功能(添加删除修改),都抽象成一个action,实现上面的接口.

      

     1 Action action = null;
     2         if ("/servlet/delUser".equals(path)) {
     3             action = new DelUserAction();
     4         }else if ("/servlet/addUser".equals(path)) {
     5             action = new AddUserAction();
     6         }else if ("/servlet/modifyUser".equals(path)) {
     7             action = new ModifyUserAction();
     8         }else if ("/servlet/queryUser".equals(path)) {
     9             action = new QueryUserAction();
    10         }else {
    11             throw new RuntimeException("请求失败");
    12         }
    13         String forward = null;
    14         try {
    15             forward = action.execute(request, response);
    16         } catch (Exception e) {
    17             e.printStackTrace();
    18         }
    19         request.getRequestDispatcher(forward).forward(request, response);

      虽然相对上面的"代码",这次有了一定程度的提高(仅仅是思想上),代码的扩展性,还是没有达到要求的.

      如今,对一些较多可选择性的代码,将其从代码中抽离出来,转化为配置文件是提高扩展性的一种方式.

     1 /  
     2            <action-config>
     3                  <action path="/servlet/delUser" type="com.bjpowernode.servlet.DelUserAction">
     4                    <forward name="success">/del_success.jsp</forward>
     5                    <forward name="error">/del_error.jsp</forward>        
     6               </action     
     7               
     8                  <action path="/servlet/addUser" type="com.bjpowernode.servlet.AddUserAction">
     9                    <forward name="success">/add_success.jsp</forward>
    10                    <forward name="error">/add_error.jsp</forward>        
    11               </action
    12                    
    13                  <action path="/servlet/modifyUser" type="com.bjpowernode.servlet.ModifyUserAction">
    14                    <forward name="success">/modify_success.jsp</forward>
    15                    <forward name="error">/modify_error.jsp</forward>        
    16               </action     
    17            
    18                  <action path="/servlet/queryUser" type="com.bjpowernode.servlet.QueryUserAction">
    19                    <forward name="success">/query_success.jsp</forward>
    20                    <forward name="error">/query_error.jsp</forward>        
    21               </action     
    22            
    23                  
    24            </action-config>

      每一个<action></action>结点指定该action对应的请求路径,对应处理该请求的具体Action类型,以及处理之后的转向.在装载这些配置文件需要一个对象来装填,这就是ActionMapping类型. 

    1         / 
    2            ActionMapping {
    3               private String path;//请求路径
    4               private String type;//对应的处理该请求的action类型.
    5               Map forwardMap; //处理完成之后的跳转信息.
    6           /

      同样,需要将跳转信息保存起来,实现对象为ForwordMap<key,value>

    1         / 
    2            }
    3            forwardMap {
    4               key="success";
    5               value="/del_success.jsp"
    6               key="error"
    7               value="/del_error.jsp"
    8            }
    9          /

      在struts1中使用Map将这些action保存起来Map<request_url,ActionMapping>.在actionmapping中同样保存着request_url.

    1            Map map = new HashMap();
    2            map.put("/servlet/delUser", actionMapping1);
    3            map.put("/servlet/addUser", actionMapping2);
    4            map.put("/servlet/modifyUser", actionMapping3);
    5            map.put("/servlet/queryUser", actionMapping4);
    6            

      如果是删除ActionMapping存储如下  

    1            actionMapping {
    2                path= "/servlet/delUser";
    3             type = "com.bjpowernode.servlet.DelUserAction";
    4             forwardMap {
    5                 key="success",value="/del_success.jsp"
    6                 key="error", value="/del_error.jsp"
    7             }
    8            }

      三 综合总结 

      下面就使用一个例子来总结一下整个struts1的处理流程

        String path = "/servlet/delUser";

        1.根据截取的URL请求,到Map(从配置文件中获取)中取得本次请求对应的Action
        ActionMappint actionMappint = (ActionMappint)map.get(path);

        2.取得本请求对应的Action类的完整路径
        String type = actionMappint.getType(); //com.bjpowernode.servlet.DelUserAction

        3.采用反射动态实例化Action
        Action action = (Action)class.forName(type).newInstance();

        4.动态待用Action中的execute方法
        String forward = action.execute(request, response);

        5.根据路径完成转向
        request.getRequestDispatcher(forward).forward(request, response);


      真正来驱动这一切行为的操作者为Servlet,也就是MVC中的控制器,实现了请求url的截取,然后从配置文件中按照截取的url,来实现分发.读取配置文件,创建actionmapping,forwardmap对象,由此创建action对象,实现业务的处理,然后转向.

  • 相关阅读:
    7-1 词频统计 (30 分)
    VS Code 配置 Python 开发环境
    7-6 求指定层的元素个数 (40 分)
    7-5 列表元素个数的加权和(1) (40 分)
    Oracle中的数据库、用户、方案、表空间、表对象之间的关系
    Oracle归档模式和非归档模式
    Oracle中的单引号和双引号
    PL/SQL编程中的问题
    Oracle数据库语言分类
    Oracle中的delete、truncate和drop
  • 原文地址:https://www.cnblogs.com/plxx/p/5285476.html
Copyright © 2011-2022 走看看