文章出處

一、Model1與Model2:

Model1:就是一種純jsp開發技術,將業務邏輯代碼和視圖渲染代碼雜糅在一起。

Model2:Model2是在Model1的基礎上,將業務邏輯的代碼分離開來,單獨形成一個Servlet,Model2也是基于MVC開發

二、MVC設計模式:

由3個部分組成,各部分作用如下:

Model:模型,主要用于數據和業務的處理

View:視圖,用于數據的顯示

Controller:控制器,用于進行流程控制

MVC設計模式的特點:

①一個模型可以對應多個視圖

②顯示與邏輯控制的分離

③分層控制,減輕了代碼間的耦合


自定義MVC框架只需dom4j.jar包即可!

 

 三、準備XML文檔Framework.xml

注意點:

<!-- ELEMENT 表示元素 -->
<!-- ATTLIST 表示屬性 -->
<!-- CDATA 表示字符串類型 -->
<!-- REQUIRED 表示此屬性必須的寫 -->
<!-- *代表多個 -->
<!-- IMPLIED 表示此屬性可寫 -->

<!DOCTYPE Framework[
<!ELEMENT Framework (actions)>
<!ELEMENT actions (action*)>
<!ELEMENT action (result*)>

<!ATTLIST action name CDATA #REQUIRED
                 class CDATA #REQUIRED
>


<!ATTLIST RESULT name CDATA #IMPLIED
                 redirect (true|false) "false"
>

]>

<Framework>
<actions>
<action name="loginAction" class="cn.happy.action.LoginAction">
<result name="success">success.jsp</result>
<result name="login">index.jsp</result>
</action>
</actions>
</Framework>


四、定義自己的Action接口,用于存放結果集和要執行的方法

public interface Action {
    //定義兩個靜態字符串常量(邏輯視圖名)
    public static final String SUCCESS="success";
    public static final String LOGIN="login";
    //定義一個抽象方法execute
    public String execute(HttpServletRequest request,HttpServletResponse response)throws Exception;

}

五、定義ActionMapping類用于存放Action節點,即一個ActionMapping類可以視為配置文件中的一個action節點

public class ActionMapping {
    //根據action節點中的屬性 以及action節點中的<result></result>節點定義三個私有屬性
    
    private String name;//action的名稱
    private String classname;//action對應程序中的類
    private Map<String,String> results=new HashMap<String,String>();
    
    //向results集合中添加數據的方法
    public void addResult(String name,String value){
        results.put(name, value);
    }

    //根據名稱獲取的方法
    public String getResults(String name){
        return results.get(name);
    }
    
    public Map<String, String> getResults() {
        return results;
    }
    public void setResults(Map<String, String> results) {
        this.results = results;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getClassname() {
        return classname;
    }
    public void setClassname(String classname) {
        this.classname = classname;
    }
    

六、定義ActionMappingManager類用于管理ActionMapping,并通過dom4j解析Framework.xml配置文件。從而獲取根節點,以及actions節點,并通過for循環遍歷actions節點下的action節點拿到name和class的屬性值,由于一個action節點下有多個result節點 及遍歷action下所有的result節點,分別存入到actionMapping中的雙列集合中,最后得到所有action節點的集合

public class ActionMappingManager {
    //actionMapping類的集合
    private Map<String,ActionMapping> maps=new HashMap<String,ActionMapping>();

    public ActionMapping getActionMapping(String name){
        return maps.get(name);
    }
    
    //解析src下所有配置文件
    public ActionMappingManager(String[]files){
        for (String filename : files) {
            init(filename);
        }
    }
    
    //創建初始化方法,使用dom4j解析配置文件
    public void init(String path){
        try {
             //getResourceAsStream取得該資源輸入流的引用保證程序可以從正確的位置抽取數據
            InputStream is=this.getClass().getResourceAsStream("/"+path);
            //解析XML
            Document doc=new SAXReader().read(is);
            //獲取根節點
            Element root = doc.getRootElement();
            //獲取actions節點
             Element actions =(Element)root.elementIterator("actions").next();
             //使用for循環來
             //遍歷actions節點下的所有action節點
             for (Iterator<Element> action=actions.elementIterator("action");action.hasNext();) {
                //獲取到action節點
                 Element actionnext = action.next();
                //分別獲取到action節點中的name屬性和class屬性
                 String name=actionnext.attributeValue("name");
                 String classname=actionnext.attributeValue("class");
                 //將以上兩個屬性保存到ActionMapping類中
                 ActionMapping mapp=new ActionMapping();
                 mapp.setClassname(classname);
                 mapp.setName(name);
                 //由于一個action節點下有多個result節點 遍歷action下所有的result節點
                 for (Iterator<Element> result=actionnext.elementIterator("result");result.hasNext();){
                     //獲取到result節點
                     Element resultnext = result.next();
                     //提取result節點的name屬性值和result節點中的值
                     String resultname= resultnext.attributeValue("name");
                    String resultvalue= resultnext.getText();
                     //將其分別存入到actionMapping中的雙列集合中去,方便調用actionMapping類(actionMapping類中就有數據了!)
                    mapp.addResult(resultname, resultvalue);
                 }
                //得到所有action節點的集合
                 maps.put(mapp.getName(), mapp);
             }
        
        } catch (Exception e) {
            
        }
    }

七、使用反射機制根據字符串類型的類名獲取到具體的類--ActionManager

public class ActionManager {

    public static Action getActionClass(String classname){
        Class clazz=null;
        Action action=null;
        //獲取當前線程的加載類
        try {
            clazz=Thread.currentThread().getContextClassLoader().loadClass(classname);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        if(clazz==null){
            try {
                //如果該線程中沒有,那么使用class.forname方法獲取
                clazz=Class.forName(classname);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        
        if(action==null){
            //將獲取到的類型轉換為action,調用無參構造函數,某種程度上相當于new,不過new需要指定類型
            try {
                action =(Action)clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return action;
    }

八、定義Servlet類,詳情見注釋!注意點在web.xml中添加 <load-on-startup>節點,讓程序一開始就初始化servlet

 

 

public class MyServlet extends HttpServlet {

    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
           doPost(request,response);
        
    }

    ActionMappingManager man=null;
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
          //獲取到ActionMapping對象
        ActionMapping actionMapping=man.getActionMapping(getname(request));
        //獲取action接口利用反射機制
        Action action = ActionManager.getActionClass(actionMapping.getClassname());
        try {
            String message=action.execute(request, response);
            String results=actionMapping.getResults(message);
            response.sendRedirect(results);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
        //獲取請求路徑名
        public String getname(HttpServletRequest request)
        {
            //項目+請求地址
            String requestURI =request.getRequestURI();
            //項目名稱
            String contextPath=request.getContextPath();
            //具體的請求
            String path=requestURI.substring(contextPath.length());
            String filename=path.substring(1,path.lastIndexOf(".")).trim();
            return filename;
        
        }
    
    //重寫servlet的init方法,讓程序一開始就初始化servlet
    //由于一個項目src根目錄下有可能有多個配置文件,不止一個,所以逐個解析
        
    @Override
    public void init(ServletConfig config) throws ServletException {
        
        //初始化參數信息
        String filename = config.getInitParameter("config");
        String [] filenames=null;
        
        if(filename==null){
            //如果沒有別的參數信息,就將已經配好的放入數組中
            filenames=new String[]{"Framework.xml"};
        }
        else{
            //拆分配置文件名稱字符串
            filenames=filename.split(",");
        }
        //使用init方法初始化
        man=new ActionMappingManager(filenames);
    }

 


九、業務邏輯Action并實現Action接口,并重寫自定義的execute方法

public class LoginAction implements Action{

    public String execute(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String name=request.getParameter("name");
        String pwd=request.getParameter("pwd");
        if(name.equals("1")&&pwd.equals("1")){
            return SUCCESS;
        }
        else{
            return LOGIN;
        }
    }

十、編寫登錄界面

  <body>
     <form action="loginAction.action" method="post">
    姓名:<input type="text" name="name"/><br/>
    密碼:<input type="text" name="pwd"/><br/>
    <input type="submit" value="登錄">
    </form>
  </body>

 實現效果:


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()