【SSH进阶之路】一步步重构MVC实现Struts框架——完善转向页面,大功告成(六)

17 篇文章 0 订阅
8 篇文章 0 订阅

第四篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——封装业务逻辑和跳转路径(四),我们解决了第一个问题:封装业务逻辑和跳转路径。第五篇博客【SSH进阶之路】一步步重构MVC实现Struts框架——彻底去掉Servlet中的逻辑判断(五),我们解决了第二个问题:彻底去掉Servlet中的逻辑判断。这篇我们解决最后一个问题,完善转向页面,显示和控制分离。


比如添加用户逻辑,成功不仅仅可以返回成功页面,失败也可以返回失败页面,代码如下:


AddUserAction

[java]  view plain  copy
 print ?
  1. package com.liang.action;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import com.liang.manager.UserManager;  
  7.   
  8. public class AddUserAction implements Action {  
  9.   
  10.     @Override  
  11.     public String execute(HttpServletRequest req, HttpServletResponse resp)  
  12.             throws Exception {  
  13.         //获取参数  
  14.         String username = req.getParameter("username");  
  15.   
  16.         //调用业务逻辑  
  17.         UserManager userManager = new UserManager();  
  18.         try{  
  19.             //添加的业务逻辑  
  20.             userManager.add(username);  
  21.         }catch(Exception e){  
  22.             //返回添加失败的界面  
  23.             return "/add_error.jsp";//转向路径可以通过配置文件读取  
  24.         }     
  25.         //返回添加成功的界面  
  26.         return "/add_success.jsp";//转向路径可以通过配置文件读取  
  27.     }  
  28.   
  29. }  

      从上篇博客中,我们知道,若想系统变的灵活,所有变化都配置到配置文件中,修改时,修改配置文件即可。因此,我们只需要在struts-config.xml中配置转向页面,不仅仅要有成功的转向页面,而且要有失败的转向页面。


我们修改一下struts-config.xml,代码如下:

[html]  view plain  copy
 print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <action-config>  
  3.     <action-mappings>  
  4.         <!--根据不同的path路径,访问各自的Action  -->   
  5.         <action path="/servlet/addUser" type="com.liang.action.AddUserAction">  
  6.             <!-- 转向页面 -->  
  7.             <forward name="success" path="/add_success.jsp"></forward>  
  8.             <forward name="error" path="/add_error.jsp"></forward>  
  9.         </action>  
  10.           
  11.         <action path="/servlet/delUser" type="com.liang.action.DelUserAction">  
  12.             <forward name="success" path="/del_success.jsp"></forward>  
  13.             <forward name="error" path="/del_error.jsp"></forward>  
  14.         </action>  
  15.   
  16.         <action path="/servlet/modifyUser" type="com.liang.action.ModifyUserAction">  
  17.             <forward name="success" path="/modify_success.jsp"></forward>  
  18.             <forward name="error" path="/modify_error.jsp"></forward>  
  19.         </action>  
  20.           
  21.         <action path="/servlet/queryUser" type="com.liang.action.QueryUserAction">  
  22.             <forward name="success" path="/query_success.jsp">/</forward>  
  23.             <forward name="error" path="/query_error.jsp"></forward>  
  24.         </action>  
  25.     </action-mappings>  
  26. </action-config>  

      我们修改了配置文件,使用dom4j读取配置,配置信息也需要放到一个map结构中,我们需要一个存储转向信息的map,因此,在ActionMapping中增加一个map。


ActionMapping

[java]  view plain  copy
 print ?
  1. package com.liang.action;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. public class ActionMapping {  
  7.   
  8.     private String path;  
  9.     private String type;  
  10.     //存储转向信息的map  
  11.     Map forward = new HashMap();  
  12.       
  13.       
  14.     public Map getForward() {  
  15.         return forward;  
  16.     }  
  17.     public void setForward(Map forward) {  
  18.         this.forward = forward;  
  19.     }  
  20.     public String getType() {  
  21.         return type;  
  22.     }  
  23.     public void setType(String type) {  
  24.         this.type = type;  
  25.     }  
  26.     public String getPath() {  
  27.         return path;  
  28.     }  
  29.     public void setPath(String path) {  
  30.         this.path = path;  
  31.     }  
  32. }  

读取配置需要发生相应的变化,但是我们有了上篇博客的例子,修改起来并不难。

ConfigInit

[java]  view plain  copy
 print ?
  1. package com.liang.servlet;  
  2.   
  3. import java.io.File;  
  4. import java.util.HashMap;  
  5. import java.util.Iterator;  
  6. import java.util.Map;  
  7.   
  8. import org.dom4j.Document;  
  9. import org.dom4j.Element;  
  10. import org.dom4j.io.SAXReader;  
  11.   
  12. import com.liang.action.*;  
  13.   
  14. public class ConfigInit {  
  15.   
  16.     public static void init(String config) {  
  17.         // 创建saxReader对象  
  18.         SAXReader reader = new SAXReader();  
  19.         File f = new File(config);  
  20.         try {  
  21.             // 通过read方法读取xml文件, 转换成Document对象  
  22.             Document doc = reader.read(f);  
  23.             // 得到配置文件的根结点  
  24.             Element root = doc.getRootElement();  
  25.             Element actionmappings = (Element) root.element("action-mappings");  
  26.             // 解析action结点的所有参数  
  27.             for (Iterator j = actionmappings.elementIterator("action"); j  
  28.                     .hasNext();) {  
  29.                 Element am = (Element) j.next();  
  30.                 ActionMapping actionMapping = new ActionMapping();  
  31.   
  32.                 // 设置actionMapping的path和type  
  33.                 actionMapping.setPath(am.attributeValue("path"));  
  34.                 actionMapping.setType(am.attributeValue("type"));  
  35.   
  36.                 Map forward = new HashMap();  
  37.                 // 解析forward结点的所有参数  
  38.                 for (Iterator k = am.elementIterator("forward"); k.hasNext();) {  
  39.                     Element fo = (Element) k.next();  
  40.                     forward.put((String) fo.attributeValue("name"), (String) fo  
  41.                             .attributeValue("path"));  
  42.                 }  
  43.                 // 设置forward  
  44.                 //如果是添加ActionMapping的存储如下;  
  45.                 /* 
  46.                  * actionMapping{ path="/servlet/addUser"; 
  47.                  * type="com.liang.action.AddUserAction"  
  48. <span style="white-space:pre">                </span> *forwardMap{ 
  49.                  * <span style="white-space:pre"> </span>key="success",value="/add_success.jsp" 
  50.                  * <span style="white-space:pre"> </span>key="error",value="/add_error.jsp" }  
  51. <span style="white-space:pre">                </span> *} 
  52.                  */  
  53.                 actionMapping.setForward(forward);  
  54.                 /* 
  55.                  * 上面Mappings.actions的存储结构相当于将配置信息与映射一一对应 
  56.                  * map.put("/servlet/delUser", actionMapping); 
  57.                  * map.put("/servlet/addUser", actionMapping); 
  58.                  * map.put("/servlet/modifyUser", actionMapping); 
  59.                  * map.put("/servlet/queryUser", actionMapping); 
  60.                  */  
  61.                 Mappings.actions.put((String) am.attributeValue("path"),  
  62.                         actionMapping);  
  63.                   
  64.             }  
  65.         } catch (Exception e) {  
  66.             e.printStackTrace();  
  67.         }  
  68.     }  
  69. }  

我们的TestServlet只需要增加一句话,如下所示:


TestServlet

[java]  view plain  copy
 print ?
  1. package com.liang.servlet;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.ServletException;  
  6. import javax.servlet.http.HttpServlet;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. import com.liang.action.Action;  
  11. import com.liang.action.ActionMapping;  
  12. import com.liang.action.Mappings;  
  13.   
  14.   
  15.   
  16. /** 
  17.  * 使用servlet做相关的控制,转向多个(V)视图 
  18.  * @author liang 
  19.  * 
  20.  */  
  21. public class TestServlet extends HttpServlet {  
  22.   
  23.     //需要读取的文件名  
  24.     protected static String config = "/WEB-INF/struts-config.xml";  
  25.   
  26.     public void init() throws ServletException {  
  27.         //获得文件的路径  
  28.         //initialize();  
  29.         //根据web.xml中映射的目录获得文件在对应服务器中的真实路径  
  30.         config = getServletContext().getRealPath("/")+ getInitParameter("config");  
  31.         //解析struts-config.xml配置文件  
  32.         ConfigInit.init(config);  
  33.     }  
  34.   
  35.     //根据web.xml中映射的目录获得文件在对应服务器中的真实路径  
  36. //  private void initialize() {  
  37. //      try {  
  38. //          config = getServletContext().getRealPath("/")  
  39. //                  + getInitParameter("config");  
  40. //      } catch (Exception e) {  
  41. //          e.printStackTrace();  
  42. //      }  
  43. //  }  
  44.     @Override  
  45.     protected void doGet(HttpServletRequest request, HttpServletResponse response)  
  46.             throws ServletException, IOException {  
  47.           
  48.         //取得访问的URI  
  49.         String reqeuestURI = request.getRequestURI();  
  50.         //截取URI,获得路径  
  51.         String path = reqeuestURI.substring(reqeuestURI.indexOf("/",1), reqeuestURI.indexOf("."));  
  52.           
  53.         Mappings mapings = new Mappings();  
  54.         // 根据截取的URL请求,到Map中取得本次请求对应的Action类  
  55.         ActionMapping actionMapping = (ActionMapping)mapings.actions.get(path);    
  56.         //取得本请求对应的Action类的完整路径  
  57.         String type = actionMapping.getType(); //com.liang.action.DelUserAction  
  58.         //采用反射,动态实例化Action  
  59.         try {  
  60.             Action action = (Action)Class.forName(type).newInstance();  
  61.             // 采用多态的机制,动态调用Action中的execute方法,返回转向路径  
  62.             String result = action.execute(request, response);  
  63.               
  64.             //获得真实转向页面  
  65.             String forward =(String)actionMapping.getForward().get(result);  
  66.               
  67.             //根据转向路径完成转向  
  68.             request.getRequestDispatcher(forward).forward(request, response);  
  69.         } catch (InstantiationException e) {  
  70.             e.printStackTrace();  
  71.         } catch (IllegalAccessException e) {  
  72.             e.printStackTrace();  
  73.         } catch (ClassNotFoundException e) {  
  74.             e.printStackTrace();  
  75.         } catch (Exception e) {  
  76.             e.printStackTrace();  
  77.         }  
  78.              
  79.     }  
  80.   
  81.     @Override  
  82.     protected void doPost(HttpServletRequest request, HttpServletResponse response)  
  83.             throws ServletException, IOException {  
  84.         doGet(request,response);  
  85.     }  
  86.   
  87. }  


最后,我们看一下AddUserAction已经变得非常灵活了。

  

[java]  view plain  copy
 print ?
  1. package com.liang.action;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import com.liang.manager.UserManager;  
  7.   
  8. public class AddUserAction implements Action {  
  9.   
  10.     @Override  
  11.     public String execute(HttpServletRequest req, HttpServletResponse resp)  
  12.             throws Exception {  
  13.         //获取参数  
  14.         String username = req.getParameter("username");  
  15.   
  16.         //调用业务逻辑  
  17.         UserManager userManager = new UserManager();  
  18.         try{  
  19.             //添加的业务逻辑  
  20.             userManager.add(username);  
  21.         }catch(Exception e){  
  22.             //返回添加失败的界面  
  23.             return "error";//和配置文件的配置一致  
  24.         }     
  25.         //返回添加成功的界面  
  26.         return "success";//和配置文件的配置一致  
  27.   
  28.     }  
  29.   
  30. }  


      大功告成,如果我们想换一个视图显示,我们只需要修改一个配置文件即可。我们用一张类图回顾一下我们重构和封装的历程。


 

      到此刻为止,我们重构MVC实现Struts框架的所有步骤都做完了。不难发现,其实框架并不难,只是咋一看特别神秘,当我们一步步重构,不断封装,不断完善,Struts的雏形已经展现在我们的面前了。框架就是封装的高度化,抽象的高度化。

       当然,它既然是一个雏形就绝对还有不完美的地方,比如,我们没有像Struts一样封装ActionForm,自动完成数据类型的转化,当然我们也可以从现在的基础上进一步完善,但是我们就不再往下做了,我们了解它的基本思想就好,况且我们后面还有更加艰巨的任务。

 

     经过几篇博客的重构,我们实现了一个Struts的雏形,它可以让我们认识mvc和struts的异同点,以及struts的封装过程,对我们更加深入struts埋下了伏笔。下篇博客【SSH进阶之路】Struts详细实现流程,深入Struts(七),通过学习Struts的流程,进一步深入Struts。下篇博客见!


源码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值