首頁  >  文章  >  Java  >  關於struts1簡單的mvc圖文程式碼實例詳解

關於struts1簡單的mvc圖文程式碼實例詳解

黄舟
黄舟原創
2017-09-05 10:37:081277瀏覽

這篇文章主要介紹了struts1之簡單mvc範例的相關資料,需要的朋友可以參考下

先看MVC模式流程圖(其實MVC設計模式就是java中的model2。):

        就像圖上所標示的C層主要是Servlet層控制頁跳轉,M層就是特定的業務處理邏輯,而JSP就是所謂的V層。 MVC是有別於我們所說的三層,我們平常所說的三層是UI層、BLL層、DAL層,具體的差異如圖:

從圖上看得出來,JSP和Servlet構成了UI層,而Model層則分成了BLL層和DAL層(也就是業務邏輯和資料持久層)。

       理論上認清了MVC設計模式之後,以下開始動手敲一個MVC設計模式範例程式碼:

       JSP索引頁面index.jsp:


#

<%@ page language="java" contentType="text/html; charset=GB18030" 
 pageEncoding="GB18030"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=GB18030"> 
<title>Insert title here</title> 
</head> 
<body> 
 <form action="servlet/addUser.action" method="post"> 
  姓名:<input type="text" name="username" > 
  <input type="submit" value="提交"> 
 </form> 
  
</body> 
</html>

        業務邏輯代碼UserManager:


package com.bjpowernode.servlet; 
 
import java.util.ArrayList; 
import java.util.List; 
 
public class UserManager { 
  
 public void addUser(String username){ 
  System.out.println("UserManager.addUsre()--->username:"+username); 
 } 
  
 public void delUser(String username){ 
  System.out.println("UserManager.delUser()--->username:"+username); 
 } 
  
 public void modifyUser(String username){ 
  System.out.println("UserManager.modifyUser()--->username"+username); 
 } 
  
 public List queryUser(String username){ 
  System.out.println("UserManager.queryUser()--->username"+username); 
  List userList=new ArrayList(); 
  userList.add("a"); 
  userList.add("b"); 
  userList.add("c"); 
  return userList; 
 } 
}

        Servlet控制代碼:


package com.bjpowernode.servlet; 
 
import java.io.IOException; 
import java.util.List; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
public class TestServlet extends HttpServlet { 
 
  
 protected void doGet(HttpServletRequest request, HttpServletResponse response) 
   throws ServletException, IOException { 
   
  String requestURI=request.getRequestURI(); 
  System.out.println("request="+requestURI); 
  String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); 
  System.out.println("path="+path); 
   
  String username=request.getParameter("username"); 
  UserManager userManager=new UserManager(); 
  //userManager.addUser(username); 
  String forward=""; 
  if("/servlet/delUser".equals(path)){ 
   userManager.delUser(username); 
   forward="/del_success.jsp"; 
  }else if("/servlet/addUser".equals(path)){ 
   userManager.addUser(username); 
   forward="/add_success.jsp"; 
  }else if("/servlet/modifyUser".equals(path)){ 
   userManager.modifyUser(username); 
   forward="/modify_success.jsp"; 
  }else if("/servlet/queryUser".equals(path)){ 
   List userList=userManager.queryUser(username); 
   request.setAttribute("userList", userList); 
   forward="/query_success.jsp"; 
  }else{ 
   throw new RuntimeException("请求失败"); 
  } 
  request.getRequestDispatcher(forward).forward(request, response); 
 
}

        這個servlet程式碼主要實現的功能判斷是那個頁面請求伺服器做那些操作,之後調用業務邏輯實現相應業務操作。


        設定Servlet:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> 
 <display-name>test_Servlet</display-name> 
 <welcome-file-list> 
 <welcome-file>index.html</welcome-file> 
 <welcome-file>index.htm</welcome-file> 
 <welcome-file>index.jsp</welcome-file> 
 <welcome-file>default.html</welcome-file> 
 <welcome-file>default.htm</welcome-file> 
 <welcome-file>default.jsp</welcome-file> 
 </welcome-file-list> 
 
 <servlet> 
 <servlet-name>TestServlet</servlet-name> 
 <servlet-class>com.cjq.servlet.TestServlet</servlet-class> 
 </servlet> 
 <servlet-mapping> 
 <servlet-name>TestServlet</servlet-name> 
 <url-pattern>*.action</url-pattern> 
 </servlet-mapping> 
 
 
</web-app>
       輸出結果:

##  已經對MVC設計模式有了初步的認識,其實這個範例是對Struts框架學習的基礎,只有弄清楚了這個實例才能弄清楚Struts框架的實現原理和Struts框架使用。 

       那我們怎麼能透過這個範例引入Struts架構呢?這個問題從IF-Eles開始。

       首先我們看到了TestServlet中出現了許多if-else語句,這樣是非常不穩定的,這樣的程式是非常不靈活的,以後如果有變化,那麼維護是非常差的;而且我們在if-else中出現了大量的字串,這樣在coding的時候會出現寫錯,這樣無形中給調試帶來了麻煩。所以去掉if-else成了我們重構的第一步,也是我們進行Struts框架學習的第一步。因為在TestServlet中出現了If-Else語句塊,所以讓程式變得不再靈活,讓應付需求改變時變得笨拙。所以就承接上篇文章來重構一下TestServlet程式碼,主要是用繼承多型態來進一步對TestServlet進行重構。

      在下方進入重構階段:


##

package com.bjpowernode.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

 
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 
 String requestURI=request.getRequestURI();
 System.out.println("request="+requestURI);
 String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
 System.out.println("path="+path);
 
 String username=request.getParameter("username");
 UserManager userManager=new UserManager();
 //userManager.addUser(username);
 String forward="";
 if("/servlet/delUser".equals(path)){
 userManager.delUser(username);
 forward="/del_success.jsp";
 }else if("/servlet/addUser".equals(path)){
 userManager.addUser(username);
 forward="/add_success.jsp";
 }else if("/servlet/modifyUser".equals(path)){
 userManager.modifyUser(username);
 forward="/modify_success.jsp";
 }else if("/servlet/queryUser".equals(path)){
 List userList=userManager.queryUser(username);
 request.setAttribute("userList", userList);
 forward="/query_success.jsp";
 }else{
 throw new RuntimeException("请求失败");
 }
 request.getRequestDispatcher(forward).forward(request, response);
  }
}

       首先我們看到了每個語句區塊中都出現了給forward賦值,其實也就是給頁面跳轉的路徑賦值,針對每個請求路徑判斷來賦值跳轉路徑。另外每個IF-Else語句區塊都有業務處理,我們要把這些業務處理分別放到類別裡面,讓職責更加單

一,這樣更符合物件導向的想法。

       就從這裡我們開始重構,我們可以將這個跳躍路徑和業務邏輯封裝起來。

       既然封裝,那麼我們就抽像出來一個藉口,主要完成一個方法,這個方法主要的功能就是要完成業務邏輯封裝和路徑跳躍的回報。隨後建立四個類,主要實現對應的增刪改查的業務處理和處理之後的跳轉路徑返回。


       程式碼如下:

       介面Action:



package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

 #   改

##

package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AddUserAction implements Action {

 
 public String execute(HttpServletRequest request,
 HttpServletResponse response) throws Exception {
 String username=request.getParameter("username");
 UserManager userManager=new UserManager();
 userManager.addUser(username);
 return "/add_success.jsp";
 }

}

 #  ##      新增使用者實作類別:


package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DelUserAction implements Action {


 public String execute(HttpServletRequest request,
 HttpServletResponse response) throws Exception {
 String username=request.getParameter("username");
 UserManager userManager=new UserManager();
 userManager.delUser(username);
 return "/del_success.jsp";
 }

}

       刪除使用者實作類別:


package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ModifyUserAction implements Action {

 @Override
 public String execute(HttpServletRequest request,
 HttpServletResponse response) throws Exception {
 String username=request.getParameter("username");
 UserManager userManager=new UserManager();
 userManager.modifyUser(username);
 return "/modify_success.jsp";
 }

}

#
package com.bjpowernode.servlet;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class QueryUserAction implements Action {

 @Override
 public String execute(HttpServletRequest request,
 HttpServletResponse response) throws Exception {
 String username=request.getParameter("username");
 UserManager userManager=new UserManager();
 List userList=userManager.queryUser(username);
 request.setAttribute("userList", userList);
 return "/query_success.jsp";
 }

}

#更新使用者實作類別:



package com.bjpowernode.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

 
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 
 String requestURI=request.getRequestURI();
 System.out.println("request="+requestURI);
 String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
 System.out.println("path="+path);
 
 Action action=null;
 if("/servlet/delUser".equals(path)){
 action=new DelUserAction();
 }else if("/servlet/addUser".equals(path)){
 action=new AddUserAction();
 }else if("/servlet/modifyUser".equals(path)){
 action=new ModifyUserAction();
 }else if("/servlet/queryUser".equals(path)){
 action=new QueryUserAction();
 }else{
 throw new RuntimeException("请求失败");
 }
 String forward=null;
 try{
 forward=action.execute(request, response);
 }catch(Exception e){
 e.printStackTrace();
 }
 request.getRequestDispatcher(forward).forward(request, response);
  }
}

       查詢使用者實作類別:



package com.bjpowernode.servlet; 
 
import java.io.IOException; 
import java.util.List; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
public class TestServlet extends HttpServlet { 
 
   
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     
    String requestURI=request.getRequestURI(); 
    System.out.println("request="+requestURI); 
    String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); 
    System.out.println("path="+path); 
     
 
    Action action=null; 
    if("/servlet/delUser".equals(path)){ 
      action=new DelUserAction(); 
    }else if("/servlet/addUser".equals(path)){ 
      action=new AddUserAction(); 
    }else if("/servlet/modifyUser".equals(path)){ 
      action=new ModifyUserAction(); 
    }else if("/servlet/queryUser".equals(path)){ 
      action=new QueryUserAction(); 
    }else{ 
      throw new RuntimeException("请求失败"); 
    } 
    String forward=null; 
    try{ 
      forward=action.execute(request, response); 
    }catch(Exception e){ 
      e.printStackTrace(); 
    } 
    request.getRequestDispatcher(forward).forward(request, response); 
   } 
}

      TestServlet類別重構如下: 


<?xml version="1.0" encoding="UTF-8"?> 
<action-config> 
  <action path="/servlet/delUser" type="com.cjq.servlet.DelUserAction"> 
    <forward name="success">/del_success.jsp</forward> 
    <forward name="error">/del_error.jsp</forward> 
  </action> 
   
  <action path="/servlet/addUser" type="com.cjq.servlet.AddUserAction"> 
    <forward name="success">/add_success.jsp</forward> 
    <forward name="error">/add_error.jsp</forward> 
  </action> 
   
  <action path="/servlet/modifyUser" type="com.cjq.servlet.ModifyUserAction"> 
    <forward name="success">/modify_success.jsp</forward> 
    <forward name="error">/modify_error.jsp</forward> 
  </action> 
   
  <action path="/servlet/queryUser" type="com.cjq.servlet.QueryUserAction"> 
    <forward name="success">/query_success.jsp</forward> 
    <forward name="error">/query_error.jsp</forward> 
  </action> 
   
</action-config>

      運作結果: 

 ######

        这样TestServlet类虽然没有彻底去掉If-Else,但是这样的代码变得更加简练,利用多肽实现业务逻辑处理和路径跳转返回。职责更加清晰,让维护变得更加轻松。 


package com.bjpowernode.servlet; 
 
import java.io.IOException; 
import java.util.List; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
public class TestServlet extends HttpServlet { 
 
   
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     
    String requestURI=request.getRequestURI(); 
    System.out.println("request="+requestURI); 
    String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); 
    System.out.println("path="+path); 
     
 
    Action action=null; 
    if("/servlet/delUser".equals(path)){ 
      action=new DelUserAction(); 
    }else if("/servlet/addUser".equals(path)){ 
      action=new AddUserAction(); 
    }else if("/servlet/modifyUser".equals(path)){ 
      action=new ModifyUserAction(); 
    }else if("/servlet/queryUser".equals(path)){ 
      action=new QueryUserAction(); 
    }else{ 
      throw new RuntimeException("请求失败"); 
    } 
    String forward=null; 
    try{ 
      forward=action.execute(request, response); 
    }catch(Exception e){ 
      e.printStackTrace(); 
    } 
    request.getRequestDispatcher(forward).forward(request, response); 
   } 
}

         解决字符串问题,当然就要用到配置文件了,用到配置文件就要有用来读取配置文件的相关的类和方法,这里就用dom4j中的类来读取配置文件,这里的配置文件的书写是有点逻辑上的难度的。 

        我们来看TestServlet中的代码,我们要在这个testservlet中实现读取配置文件和path比较,还有利用多肽实例化相应的实现类,最后通过实例化的实现类的方法来返回跳转路径,最终跳转到相应的页面。

        所以我们的配置文件就要不仅配上testservlet中出现的字符串,还要配置相应的Action接口的实现类(我们可以利用反射来实例化该类的对象,进而使用这个类的所有属性和方法),另外还有跳转路径字符串。这样我们的配置文件就变成了如下代码所示:


<?xml version="1.0" encoding="UTF-8"?> 
<action-config> 
  <action path="/servlet/delUser" type="com.cjq.servlet.DelUserAction"> 
    <forward name="success">/del_success.jsp</forward> 
    <forward name="error">/del_error.jsp</forward> 
  </action> 
   
  <action path="/servlet/addUser" type="com.cjq.servlet.AddUserAction"> 
    <forward name="success">/add_success.jsp</forward> 
    <forward name="error">/add_error.jsp</forward> 
  </action> 
   
  <action path="/servlet/modifyUser" type="com.cjq.servlet.ModifyUserAction"> 
    <forward name="success">/modify_success.jsp</forward> 
    <forward name="error">/modify_error.jsp</forward> 
  </action> 
   
  <action path="/servlet/queryUser" type="com.cjq.servlet.QueryUserAction"> 
    <forward name="success">/query_success.jsp</forward> 
    <forward name="error">/query_error.jsp</forward> 
  </action> 
   
</action-config>

        我们有了配置文件之后就要想法通过相关类读取,并且实现相应的功能。所以这里用dom4j来读取完成。其实如果能把这个逻辑捋顺之后就能发现,其实懂我们利用dom4j读取完配置文件的时候,我们是取得的是一个配套的匹配路径字符串、相应业务逻辑类还有处理业务逻辑之后跳转页面路径字符串。这样我们就能直截了当的去掉了if-else。(这里可能逻辑上会出现一些困难,但是看到下面的重构之后的testservlet中的代码和读取配置文件之后的代码就会一目了然)。 

        现在等待解决的问题就是我们要把从配置文件取得的一整套内容放到那里,当然这是毋庸置疑的要放到类中。所以我们就建立一个ActionMapping类来放我们的那一整套内容。 

        ActionMapping中的代码如下:


package com.bjpowernode.servlet; 
 
import java.util.Map; 
 
public class ActionMapping { 
 
  private String path; 
   
  private Object type; 
   
  private Map forwardMap; 
 
  public String getPath() { 
    return path; 
  } 
 
  public void setPath(String path) { 
    this.path = path; 
  } 
 
  public Object getType() { 
    return type; 
  } 
 
  public void setType(Object type) { 
    this.type = type; 
  } 
 
  public Map getForwardMap() { 
    return forwardMap; 
  } 
 
  public void setForwardMap(Map forwardMap) { 
    this.forwardMap = forwardMap; 
  } 
   
}

        现在ActionMapping类已经有了,剩下的工作就是要利用dom4j来读取配置文件类,具体代码如下:       


package com.bjpowernode.servlet; 
 
import java.io.InputStream; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
 
import org.dom4j.Document; 
import org.dom4j.DocumentException; 
import org.dom4j.Element; 
import org.dom4j.io.SAXReader; 
 
public class XmlConfigReader { 
 
   
  private static XmlConfigReader instance=new XmlConfigReader(); 
   
  ActionMapping actionMapping=new ActionMapping(); 
   
  private Document doc; 
   
  private Map actionMap=new HashMap(); 
   
  private XmlConfigReader(){ 
    try { 
      SAXReader reader=new SAXReader(); 
       
      InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml"); 
       
      doc=reader.read(in); 
       
    } catch (DocumentException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
    } 
     
     
  } 
   
   
   
   
  public ActionMapping getActionMapping(String path){ 
    synchronized(this){ 
       
      Object type=null; 
      /*if(action.containsKey(path)){ 
        type=action.get(path); 
      }*/ 
       
       
      Element eltAction = (Element)doc.selectObject("//action[@path=\"" + path + "\"]"); 
      try{ 
        type=Class.forName(eltAction.attributeValue("type")).newInstance(); 
      }catch(Exception e){ 
        e.printStackTrace(); 
      } 
       
       Element eltForwards = eltAction.element("forward"); 
         
        for (Iterator iter = eltForwards.elementIterator(); iter.hasNext();) { 
          Element eltForward = (Element) iter.next(); 
          actionMap.put( eltForward.attributeValue("name"),eltForward.getTextTrim());  
        }  
       
      actionMapping.setPath(path); 
      actionMapping.setType(type); 
      actionMapping.setForwardMap(actionMap); 
       
      return actionMapping; 
    } 
  } 
   
  public static synchronized XmlConfigReader getInstance(){ 
     
    return instance; 
  } 
   
   
  /** 
   * @param args 
   */ 
  public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping("/servlet/delUser"); 
    System.out.println(actionMapping.getPath()); 
    System.out.println(actionMapping.getType()); 
    System.out.println(actionMapping.getForwardMap().toString()); 
  } 
 
}

        我们通过返回ActionMapping来动态创建出action相应的实现类,进而完成业务逻辑和页面跳转,重构之后的TestServlet代码如下:       


package com.bjpowernode.servlet; 
 
import java.io.IOException; 
import java.util.List; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
public class TestServlet extends HttpServlet { 
 
   
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     
    String requestURI=request.getRequestURI(); 
    System.out.println("request="+requestURI); 
    String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); 
    System.out.println("path="+path); 
     
 
    String forward=""; 
    ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping(path); 
    Action action=(Action)actionMapping.getType(); 
    try { 
      forward=action.execute(request, response); 
    } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
    } 
    request.getRequestDispatcher(forward).forward(request, response); 
  } 
 
   
  protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
    doGet(request,response); 
  } 
 
}

         我们可以清晰的看到if-else已经没有了,字符串也已经没有了。通过这篇文章对if-else还有字符串问题的解决,又一次重构了testservlet代码,程序相对灵活许多。通过这一次的重构,我们已经看到了struts框架的雏形,

以上是關於struts1簡單的mvc圖文程式碼實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn