JavaWeb之搭建自己的MVC框架(二)

1. 前言

JavaWeb之搭建自己的MVC框架(一) 中我们完成了URL到JAVA后台方法的最基本跳转。但是实际操作中会发现有一个不方便的地方,现在在com.mvc.controller包中只有一个SayController类,如果我们想增加一个新的***Controller类,我们还需要到UrlMappingCollection中修改controllerList属性,这样是不合理的。

所以我们在这一节中要将这种耦合解除掉。我们要将UrlMappingCollection中controllerList提到xml配置文件中。

2. 准备Jar包

 在这一节里我们需要用dom4j来解析xml文件。当然你也可以用其他工具来解析xml。

3. 实现

(1)首先我们要在web.xml中记录下我们将来需要扫描的controller列表:

<?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">    
    <listener>
        <listener-class>com.mvc.listener.UrlMappingCollection</listener-class>
    </listener>    
    
    <mymvc>
        <controllers>
            <controller>com.mvc.controller.SayController</controller>
        </controllers>
    </mymvc>                    
                        
    <servlet>
        <servlet-name>main</servlet-name>
        <servlet-class>com.mvc.servlet.ServletCenter</servlet-class>        
    </servlet>
    <servlet-mapping>
        <servlet-name>main</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

其中,mymvc节点及其子节点就是我们在本节中新增的节点。

(2)然后我们调整UrlMappingCollection这个类,来读取web.xml中新增的mymvc节点内容。

package com.mvc.listener;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.mvc.annotation.URLMapping;
import com.mvc.base.MVCBase;

public class UrlMappingCollection implements ServletContextListener {
    //被注解了URLMapper的类方法列表
    private static List<MVCBase> mvcBases;
    
    private final String MyMVC_NodeName = "mymvc";
    private final String ControllerList_NodeName = "controllers";
    private final String Control_NodeName = "controller";

    //我们要扫描的Controller列表
    @SuppressWarnings("unchecked")
    private List<String> getControllerList(ServletContextEvent sce) throws DocumentException{
        List<String> ctrlList = new ArrayList<String>();
        String webxml = sce.getServletContext().getRealPath("WEB-INF\\web.xml");
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File(webxml)); 
        Element rootElement = document.getRootElement();
        List<Element> crtlNodeList = rootElement.element(MyMVC_NodeName).
                                                 element(ControllerList_NodeName).
                                                 elements(Control_NodeName);
        for (Element element : crtlNodeList) {
            ctrlList.add(element.getText());
        }
        return ctrlList;
    }
    

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        mvcBases = new ArrayList<MVCBase>();
        try {
            List<String> controllerList = getControllerList(sce);
            //循环所有需要扫描的Controller
            for (int i = 0; i < controllerList.size(); i++) {
                String controllerName = controllerList.get(i); 
                
                String classURL = "";
                String methodURL = "";
                
                Class<?> clazz = Class.forName(controllerName); //获取Controller类
                if (clazz.isAnnotationPresent(URLMapping.class)) { //class被标记了URLMapping注解
                    classURL = ((URLMapping) clazz.getAnnotation(URLMapping.class)).url();             
                }
                //获取method列表
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(URLMapping.class)) { //method被标记了URLMapping注解
                        methodURL = ((URLMapping) method.getAnnotation(URLMapping.class)).url(); 
                        
                        MVCBase mvcBase = new MVCBase();
                        mvcBase.setUrl(classURL+methodURL);
                        mvcBase.setController(controllerName);
                        mvcBase.setMethod(method.getName());
                        
                        mvcBases.add(mvcBase);
                    }
                }
            }
        }
        catch (Exception e) {
            
        }
    }
    
    public static List<MVCBase> getMvcBases() {
        return mvcBases;
    }

}

我们增加了getControllerList函数来读取web.xml中的配置信息,然后把controller列表读取出来,其他地方稍作修改,读着可对比上一节中此处代码来观察做了哪些修改。

4. 测试效果:

首先,我们需要增加一个新的controller:

package com.mvc.controller;

import com.mvc.annotation.URLMapping;

@URLMapping(url="/Eat")
public class EatController {
    
    @URLMapping(url="/Apple")
    public String EatApple(){
        System.out.println("I'm eating apples");
        return "Apple";
    }
    
    @URLMapping(url="/Banana")
    public String EatBanana(){
        System.out.println("I'm eating Banana");
        return "Banana";
    }
}

然后,调整web.xml,增加com.mvc.controller.EatController:

    <mymvc>
        <controllers>
            <controller>com.mvc.controller.SayController</controller>
            <controller>com.mvc.controller.EatController</controller>
        </controllers>
    </mymvc>

最后,我们启动tomcat,在浏览器中输入:

http://127.0.0.1:8080/MyMVC/Eat/Apple

http://127.0.0.1:8080/MyMVC/Eat/Banana

http://127.0.0.1:8080/MyMVC/Say/Hello

http://127.0.0.1:8080/MyMVC/Say/Hi

看看是否能打印出我们想要的结果。

posted @ 2016-03-24 17:26  柚子苹果果  阅读(896)  评论(0编辑  收藏  举报