第一章 自定義MVC框架

第一章  自定義MVC框架
1.1 MVC模式設計
    組成;Model:模型,用於數據和業務的處理
          View :視圖,用於數據的顯示
          Controller:控制器,用於進行流程控制
    特色:1.一個模型能夠對應多個視圖
          2.顯示與邏輯控制的分離
          3.分層控制,減低了代碼間的耦合
1.2 DTD驗證XML文檔
        聲明:<!DOCTYPE 根元素 [定義內容]>
            例:<!DOCTYPE poem [
                    <!ELEMENT poem (author,title,content)>
                    <!ELEMENT author (#PCDATA)>
                    <!ELEMENT title (#PCDATA)>
                    <!ELEMENT content (#PCDATA)>
                ]>
                <peom>
                    <author>王維</author>
                    <title>鹿柴</title>
                    <content>空山不見人,但聞人語聲。返景入深林,復照青苔上</content>
                </peom>
        使用外部DTD驗證XML
                myStruts.dtd:
                <!ELEMENT poems (poem*)>
                    <!ELEMENT poem (title,author,year,content)>
                    <!ELEMENT title (#PCDATA)>
                    <!ELEMENT author (#PCDATA)>
                    <!ELEMENT year (#PCDATA)>
                    <!ELEMENT content (#PCDATA)>
                    
                myMvc.xml:
                <!DOCTYPE poems SYSTEM "myStruts.dtd">
                <poems>
                    <poem>
                        <title>春曉</title>
                        <author>孟浩然</author>
                        <content>春眠不覺曉......</content>
                    </poem>
                </poems>
        DTD元素
            <!ELEMENT name CONTENT>
            ELEMENT:關鍵字
            name:元素名稱
            CONTENT:元素類型
                      #PCDATA:任何字符數據,不能在其中包含任何子元素
                      純元素類型:只包含子元素,且這些子元素外沒有文本
            符號:():表示分紅幾組
                   | :必須選其一
                   ,:按順序出現
                   * :能夠出現0到屢次
                   ?:可出現也可不出現,出現且只有一次
                   + :必須出現,且能夠出現屢次
        DTD屬性
            <!ATTLIST 元素名稱  屬性名稱  屬性類型  屬性默認值>
            屬性類型描述:
                        CDATA:字符數據
                        ID:惟一ID
                        IDREFS:另外一個ID
                        ENTITY:實體
                        ENTITIES:實體列表
            屬性值描述:
                        #REQUIRED:屬性值是必須的
                        #IMPLIED:屬性值不是必須的
                        #FIXED:屬性值是固定的
                        例:<!DOCTYPE mystruts[
                            <!ELEMENT mystruts (actions)>
                            <!ELEMENT actions (action*)>
                            <!ELEMENT action (result*)>
                            <!ATTLIST auction
                                name CDATA #REQUIRED
                                CLASS CDATA #REQUIRED>
                            <!ATTLIST result
                                name CDATA #IMPLIED
                                redirect (true|false) "false">
                        ]>
                        <mystruts>
                            <actions>
                                <action name="register" class="cn.jbit.action.RegisterAction">
                                    <result name="success">page/login.jsp</result>
                                    <result name="input">page/register.jsp</result>
                                </action>
                                <action name="login" class="cn.jbit.mvc.LoginAction">
                                    <result name="success">page/guanli.jsp</result>
                                    <result name="input">page/login.jsp</result>
                                </action>
                            </actions>
                        </mystruts>
1.3 XML文檔解析

        獲取root節點     ELement root
        一、獲取節點名稱  root.getName()
        二、獲取節點屬性  root.attribute("dname")
        三、獲取節點中的text  root.getText()
        四、獲取子節點
        
        使用DOM4J操做XML數據(如:dom4j-1.6.1.jar)
        例:student.xml:
                <?xml version="1.0" encoding="gb2312"?>
                <students>
                    <student age="31"><!-- 若是沒有固定的age 默認爲20  -->
                        <name>崔衛兵</name>
                        <college>pc學院</college>
                        <telephone>6234666</telephone>
                        <notes>男,1985年出生,碩士</notes>
                    </student>
                    <student>
                        <name>張洪澤</name>
                        <!-- 若是沒有固定的leader 默認爲leader  -->
                        <college leader="Leader">pc學院</college>
                        <telephone>6238888</telephone>
                        <notes>男,1987年出生,碩士</notes>
                    </student>
                </students>
            Dom4jReadExmple.java:
                public class Dom4jReadExmple {
                    public void iterateWholeXML(String filename,HashMap<String,String> hm){
                        SAXReader saxReader=new SAXReader();
                        try {
                            Document document=saxReader.read(new File(filename));
                            Element root=document.getRootElement();
                            int num=-1;//記錄學生編號的變量
                            //遍歷根元素(students)的全部子節點(student)
                            for(Iterator iter=root.elementIterator();iter.hasNext();){
                                Element element=(Element) iter.next();
                                num++;
                                //獲取person節點的age屬性
                                Attribute ageAttribute=element.attribute("age");
                                if(ageAttribute!=null){
                                    String age=ageAttribute.getValue();
                                    if(age!=null && !age.equals("")){
                                        hm.put(element.getName()+"-"+ageAttribute.getName()+num, age);
                                    }else{
                                        hm.put(element.getName()+"-"+ageAttribute.getName()+num, "20");
                                    }
                                }else{
                                    hm.put(element.getName()+"-age"+num, "20");
                                }
                                //遍歷student節點下的全部子節點(name,college,telephone,notes)
                                for(Iterator iterInner=element.elementIterator();iterInner.hasNext();){
                                    Element elementInner=(Element) iterInner.next();
                                    if(elementInner.getName().equals("college")){
                                        hm.put(elementInner.getName()+num,elementInner.getText());
                                        //獲取college節點的leader屬性
                                        Attribute leaderAttr=elementInner.attribute("leader");
                                        if(leaderAttr!=null){
                                            String leader=leaderAttr.getValue();
                                            if(leader!=null && !leader.equals("")){
                                                hm.put(elementInner.getName()+"-"+leaderAttr.getName()+num,leader);
                                            }else{
                                                hm.put(elementInner.getName()+"-"+leaderAttr.getName()+num,"leader");
                                            }
                                        }else{
                                            hm.put(elementInner.getName()+"-leader"+num, "leader");
                                        }
                                    }else{
                                        hm.put(elementInner.getName()+num, elementInner.getText());
                                    }
                                }
                            }
                        } catch (DocumentException e) {
                            // TODO: handle exception
                            e.printStackTrace();
                        }
                    }
                }
            TestDom4jReadExmple.java:
                    public class TestDom4jReadExmple {
                    public static void main(String[] args) {
                        try {
                            //獲取解析後的解析信息
                            HashMap<String, String> hashMap;
                            Dom4jReadExmple dre=new Dom4jReadExmple();
                            //遍歷xml文件
                            hashMap=new HashMap<String, String>();
                            String n=System.getProperty("user.dir");
                            //獲取xml文件
                            dre.iterateWholeXML(n+"\\src\\cn\\jbit\\action\\Student.xml", hashMap);
                            for (int i = 0; i < hashMap.size(); i++) {
                                int j=i/6;
                                System.out.print(hashMap.get("name"+j)+"\t");
                                System.out.print(hashMap.get("student-age"+j)+"\t");
                                System.out.print(hashMap.get("college"+j)+"\t");
                                System.out.print(hashMap.get("college-leader"+j)+"\t");
                                System.out.print(hashMap.get("telephone"+j)+"\t");
                                System.out.println(hashMap.get("notes"+j)+"\t");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    }
        輸出結果:崔衛兵    31    pc學院    leader    6234666    男,1985年出生,碩士    
                  張洪澤    20    pc學院    Leader    6238888    男,1987年出生,碩士
                
        關鍵操做以下:
            一、Document對象相關
                SAXReader saxReader=new SAXReader();
                Document document=saxReader.read(new File("index.xml"));
            二、節點相關    
                一、獲取文檔的根節點
                    Element root=document.getRootElement();
                二、獲取某節點的單個子節點
                    Element meberElm=root.element("Member");
                三、取得節點的文字
                    String text=MemberElm.getText();
                四、取得某節點下名爲:Member的全部子節點並進行遍歷
                    List nodes=rootElm.elements("Member");
                五、對某節點下的全部子節點進行遍歷
                    for(Iterator iterInner=element.elementIterator();iterInner.hasNext();){
                        Element elementInner=(Element) iterInner.next();
                        //...
                    }
                六、在某節點下添加子節點
                    Element ageElm=newMemberElm.addElement("age");
                七、設置節點文字
                    ageElm.setText("19");
                八、刪除某節點
                    parentElm.remove(childElm);//childElm是待刪除的節點,parentElm是父節點
                九、添加一個CDATA節點
                    Element contentElm=infoElm.addElement(content);
                    contentElm.addCDATA(diary.getContent());
                    contentElm.getText();
                    contentElm.clearContent();
            三、屬性相關
                一、取得某節點下的屬性
                    Element root=document.getRootElement();
                    Attribute ageAttribute=root.attribute("age");
                二、取得屬性的文字
                    String text=ageAttribute.getText();
                三、遍歷某節點的全部屬性
                    Element root=document.getRootElement();
                    for(Iterator it=root.elementIterator();it.hasNext();){
                        Attribute attribute=(Attrinute) it.next();
                        String text=ageAttribute.getText();
                        System.out.print(text);
                    }
                四、設置某節點的屬性和文字
                    newMemberElm.addAttribute("name","sitinspring');
                五、設置屬性的文字
                    Attribute attribute=root.attribute("age");
                    attribute.setText("sitinspring");
1.4 反射機制
        反射的3個動態性質
            1.運行時伸出對象實例
            2.運行期間調用對象
            3.運行時更改對象
            
        反射經常使用API
            Class類:反射核心類
            Field類:類的屬性
            Method類:類的方法
            Constructor類:類的構造方法
            
        使用反射的步驟
            一、導入jar包
            二、得到須要操做的類的java.lang.CLass對象
            三、調用Class的方法獲取Field、Method等對象
            四、使用反射API進行操做
            
        反射的應用
            一、獲取Class對象
                例;
                Class clazz=Class.forName("java.lang.String");//正確
                Class clazz=Class.forName("String");//錯誤
            二、從Class對象獲取信息
                訪問類信息的經常使用方法
                    Constructor[] getConstructors()//返回所表示的類的public構造方法
                    Constructor[] getDeclaredConstructors()//返回所表示的類的構造方法
                    Method [] getMethods()//返回所表示的類的public方法
                    Method [] getDeclaredMethods()//返回所表示的類的所有方法
                    Field[] getFields()//返回所表示的類的public屬性
                    field[] getDeclaredFields()//返回所表示的類的所有屬性
                    Object get(Object obj)//獲得引用類屬性值
                    void set(Object obj,Object val)//將Obj對象的屬性設置val值,針對引用類型
                    Object invoke(Object obj,Object args)//調用類的方法obj是執行方法的對象,args是執行方法時傳入的參數
            三、建立對象
                newInstance():
                例:Object retBean=defaultCtor.newInstance();
1.5 構建基於MVC模式的框架(Controller爲MVC的核心)                
        1.5.一、Controller的設計
            一、定義Action接口
                public interface Action {
                    public String execute(HttpServletRequest request,HttpServletResponse response)throws Exception;
                }
                實現接口:
                public class LoginAction implements Action {
                    @Override
                    public String execute(HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
                        String name=request.getParameter("name");
                        String password=request.getParameter("password");
                        //業務處理                        
                        UserBiz userBiz=new UserBizImpl();
                        User user=userBiz.login(name,password);                    
                        //判斷是否登陸成功
                        if(user==null){
                            request.setAttribute("message","用戶名或密碼錯誤!");
                            return "/page/login.jsp";
                        }else{
                            request.getSession().setAttribute("login", user);
                            return "/page/guanli.jsp";
                        }                        
                        return null;
                    }
                }
            二、實現Controller類
                public class ActionFilter implements Filter {
                    private FilterConfig config;
                    private ActionMappingManager mappingManager;
                    @Override
                    public void destroy() {
                    }

                    @Override
                    public void doFilter(ServletRequest request, ServletResponse response,
                            FilterChain chain) throws IOException, ServletException {
                        //將請求裝換成HttpServletRequest
                        HttpServletRequest hsr=(HttpServletRequest) request;
                        HttpServletResponse hsp=(HttpServletResponse) response;
                        //調用Action的execute方法
                        
                         Action action=this.getAction(hsr);
                         String resultView=null;
                        try {
                            resultView=action.execute(hsr, hsp);
                        } catch (Exception e) {
                            // TODO: handle exception
                            e.printStackTrace();
                        }
                        //頁面跳轉
                        if(resultView!=null){
                            request.getRequestDispatcher(resultView).forward(request, response);
                        }
                    }


                    @Override
                    public void init(FilterConfig conf) throws ServletException {
                        this.config=conf;
                        String conStr=config.getInitParameter("config");
                        //可包含多個配置文件
                        String[] configFiles=null;
                        if(conStr==null||conStr.isEmpty()){
                            configFiles=new String[]{"myMvc.xml"};
                        }else{
                            //拆分配置文件名稱字符串
                            configFiles=conStr.split(",");
                        }
                        this.mappingManager=new ActionMappingManager(configFiles);
                    }
                    private Action getAction(HttpServletRequest request) {
                        //獲取請求的uri
                        String uri = request.getRequestURI();
                        //獲取上下文路徑
                        String contextPath=request.getContextPath();
                        //截取上下文路勁後面的部分
                        String actionPath=uri.substring(contextPath.length());
                        //獲取Action名稱
                        String actionName=actionPath.substring(1,actionPath.lastIndexOf(".")).trim();
                        Action action=null;
                        //添加新功能時在這裏添加
                        if("login".equals(actionName)){
                            action=new LoginAction();
                        }
                        return null;
                    }
                }
        web.xml配置:
            <?xml version="1.0" encoding="UTF-8"?>
            <web-app version="3.0"
                xmlns="http://java.sun.com/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
              <display-name></display-name>    
              <welcome-file-list>
                <welcome-file>login.jsp</welcome-file>
              </welcome-file-list>
              <filter>
                <filter-name>requestFilter</filter-name>
                <filter-class>cn.jbit.mvc.ActionFIlter</filter-class>
              </filter>
              <filter-mapping>
                <filter-name>requestFilter</filter-name>
                <url-pattern>*.action</url-pattern>
              </filter-mapping>
            </web-app>
1.6 升級Controller控制器
        一、配置文件
            myStruts.xml
            <?xml version="1.0" encoding="UTF-8"?>
                <!DOCTYPE mystruts[
                    <!ELEMENT mystruts (actions)>
                    <!ELEMENT actions (action*)>
                    <!ELEMENT action (result*)>
                    <!ATTLIST auction
                        name CDATA #REQUIRED
                        CLASS CDATA #REQUIRED>
                    <!ATTLIST result
                        name CDATA #IMPLIED
                        redirect (true|false) "false">
                ]>
                <mystruts>
                    <actions>
                        <action name="register" class="cn.jbit.action.RegisterAction">
                            <result name="success">page/login.jsp</result>
                            <result name="input">page/register.jsp</result>
                        </action>
                        <action name="login" class="cn.jbit.mvc.LoginAction">
                            <result name="success">page/guanli.jsp</result>
                            <result name="input">page/login.jsp</result>
                        </action>
                    </actions>
                </mystruts>
            二、保存Action信息
                public class ActionMapping {
                    //action元素的name屬性
                    private String name;
                    //action元素的className屬性
                    private String className;
                    //保存配置愛的result屬性信息
                    private Map<String, String > resultMap=new HashMap<String, String>();
                    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;
                    }
                    public Map<String, String> getResultMap() {
                        return resultMap;
                    }
                    public void setResultMap(Map<String, String> resultMap) {
                        this.resultMap = resultMap;
                    }
                    /*
                     * 根據result-name返回Result實例
                     */
                    public String getResult(String name,String result){
                        return resultMap.get(name);
                    }
                    public String getResult(String name){
                        return resultMap.get(name);
                    }
                    /*
                     * 向Map中添加一個View
                     */
                    public void addResult(String name,String result){
                        this.resultMap.put(name, result);
                    }
                }
            三、讀取配置文件
                public class ActionMappingManager {
                    //保存全部Action的ActionMapping
                    private static Map<String,ActionMapping> actionMappings=new HashMap<String, ActionMapping>();
                    /**
                     * init方法用來加載Action配置文件
                     * @param configureFileName 配置文件名
                     */
                    public void init(String configureFileName){
                        try {
                            if(configureFileName==null || configureFileName.isEmpty()){
                                throw new Exception("ConfigureFileName爲空");
                            }
                            InputStream is=this.getClass().getResourceAsStream("/"+configureFileName);
                            Document doc=new SAXReader().read(is);
                            Element root=doc.getRootElement();
                            Iterator<Element> actionsIt=root.elements("actions").iterator();
                            Element actions =actionsIt.next();
                            for(Iterator<Element> actionIt=actions.elementIterator("action");actionIt.hasNext();){
                                Element action=actionIt.next();
                                ActionMapping mapping=new ActionMapping();
                                mapping.setName(action.attributeValue("name"));
                                mapping.setClassName(action.attributeValue("class"));
                                for(Iterator<Element> resultIt=action.elementIterator("result");resultIt.hasNext();){
                                    Element resultElement=resultIt.next();
                                    String name=resultElement.attributeValue("name");
                                    String result=resultElement.getText();
                                    if(name==null || "".equals(name)){
                                        name="success";
                                    }
                                    mapping.addResult(name, result);
                                }
                                actionMappings.put(mapping.getName(), mapping);
                            }
                        } catch (Exception e) {
                            // TODO: handle exception
                            e.printStackTrace();
                        }
                    }
                    /**
                     * 加載Action配置文件
                     * @param configureFileNames 配置文件名的數組
                     */
                    public ActionMappingManager(String[] configureFileNames){
                        for(String configureFileName:configureFileNames){
                            init(configureFileName);
                        }
                    }
                    /**
                     * 根據actionName查詢對應的ActionMapping實例
                     * @param actionName
                     * @return
                     * @throws Exception
                     */
                    public ActionMapping getActionMappingByName(String actionName)throws Exception{
                        if(actionName==null || actionName.isEmpty()){
                            return null;
                        }
                        
                        ActionMapping mapping=this.actionMappings.get(actionName);
                        if(mapping==null){
                            throw new Exception("mapping爲空:["+actionName+"]");
                        }
                        return mapping;
                    }
                }
            四、反射生成Action
                public class ActionManager {
                    public static Action createAction(String className)throws Exception{
                        try {
                            return (Action)loadClass(className).newInstance();
                        }catch (ClassNotFoundException e) {
                                e.printStackTrace();
                        }catch (InstantiationException e) {
                            e.printStackTrace();
                        }catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }

                    private static Class loadClass(String className) throws ClassNotFoundException {
                        Class clazz=null;
                        clazz=Class.forName(className);
                        return clazz;
                    }
                }
            五、完善Controller
                web.xml:
                <filter>
                    <display-name>requestFilter</display-name>
                    <filter-name>requestFilter</filter-name>
                    <filter-class>cn.jbit.mvc.ActionFIlter</filter-class>
                    <init-param>
                        <param-name>config</param-name>
                        <param-value>myMvc.xml</param-value>
                    </init-param>
                  </filter>
            ActionFilter.java修改:    
                    public class ActionFilter implements Filter {
                        private FilterConfig config;
                        private ActionMappingManager mappingManager;
                        @Override
                        public void destroy() {
                        }

                        @Override
                        public void doFilter(ServletRequest request, ServletResponse response,
                                FilterChain chain) throws IOException, ServletException {
                            //將請求裝換成HttpServletRequest
                            HttpServletRequest hsr=(HttpServletRequest) request;
                            HttpServletResponse hsp=(HttpServletResponse) response;
                            try {
                                ActionMapping mapping=this.getActionMapping(hsr);
                                Action action=ActionManager.createAction(mapping.getName());
                                //獲得結果的邏輯名
                                String resultName=action.execute(hsr, hsp);
                                //根據邏輯名返回實際跳轉的視圖名,也就是跳轉的路徑
                                String result=mapping.getResult(resultName);
                                if(result==null){
                                    return;
                                }
                                //頁面跳轉
                                hsp.sendRedirect(result);
                            } catch (Exception e) {
                                // TODO: handle exception
                                e.printStackTrace();
                            }
                            
                        }


                        @Override
                        public void init(FilterConfig conf) throws ServletException {
                            this.config=conf;
                            String conStr=config.getInitParameter("config");
                            //可包含多個配置文件
                            String[] configFiles=null;
                            if(conStr==null||conStr.isEmpty()){
                                configFiles=new String[]{"myMvc.xml"};
                            }else{
                                //拆分配置文件名稱字符串
                                configFiles=conStr.split(",");
                            }
                            this.mappingManager=new ActionMappingManager(configFiles);
                        }
                        private ActionMapping getActionMapping(HttpServletRequest request) throws Exception {
                            //獲取請求路徑
                            String uri=((HttpServletRequest)request).getRequestURI();
                            String contextPath=((HttpServletRequest)request).getContextPath();
                            //截取上下文路勁後面的部分
                            String actionPath=uri.substring(contextPath.length());
                            //獲取Action名稱
                            String actionName=actionPath.substring(1,actionPath.lastIndexOf(".")).trim();
                            ActionMapping mapping=null;
                            mapping=mappingManager.getActionMappingByName(actionName);
                            return mapping;
                            
                        }
                    }java

相關文章
相關標籤/搜索