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对象,实现业务的处理,然后转向.

  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/plxx/p/5285476.html
Copyright © 2011-2022 走看看