xml------反射模拟servlet的执行(一)

1.需求的引出
这里写图片描述
每个类有3个方法,这三个方法执行的时候有不同的控制台输出:

public void init(){
    System.out.println("myservlet1-init");
}
public void service(){
    System.out.println("myservlet1-service");
}
public void destory(){
    System.out.println("myservlet1-destory");
}

}

2.实现
而我们需要用java类调用执行。对于我们说这样是不难的,我们可以轻而易举的写出如下的代码:

    // 模拟从外界传递过来的参数
    String url = "/s1";
    // 如果url是s1, 执行myServlet1
    // 如果url是s2, 执行myServlet2
    // 如果url是s3, 执行myServlet3
    if ("/s1".equals(url)) {
        MyServlet1 myServlet1 = new MyServlet1();
        myServlet1.init();
        myServlet1.service();
        myServlet1.destory();
    } else if ("/s2".equals(url)) {
        MyServlet2 myServlet2 = new MyServlet2();
        myServlet2.init();
        myServlet2.service();
        myServlet2.destory();
    }

缺点:不利于程序功能追加,功能扩展,程序扩展性不强 。 优点:执行效率高

而要增强扩展性,自然而然的引出了反射。用反射去改进上述的第一版代码:

        // 模拟从外界传递过来的参数
        String url = "/s1";
        // 如果url是s1, 执行myServlet1
        // 如果url是s2, 执行myServlet2
        // 如果url是s3, 执行myServlet3

        // 反射修改 1.创建字节码文件
        Class clazz = Class.forName("xml.demo1.MyServlet1");
        // 2.创建实例对象
        Object object = clazz.getConstructor().newInstance();
        // 3.反射执行init service destory
        Method init = clazz.getMethod("init");
        init.invoke(object, null);
        Method service = clazz.getMethod("service");
        service.invoke(object, null);
        Method destory = clazz.getMethod("destory");
        destory.invoke(object, null);

反射的优点:增加了代码的复用性,代码可以复用,需要修改的:forName的参数,动态赋值

第三版代码如下;

       // 模拟从外界传递过来的参数
        String url = "/s1";
        // 如果url是s1, 执行myServlet1
        // 如果url是s2, 执行myServlet2
        // 如果url是s3, 执行myServlet3

        // map集合 不需要有序,
        Map<String, String> map = new HashMap<String, String>();
        map.put("/s1", "xml.demo1.MyServlet1");
        map.put("/s2", "xml.demo1.MyServlet2");
        map.put("/s3", "xml.demo1.MyServlet3");
        // 反射修改 1.创建字节码文件
        Class clazz = Class.forName(map.get(url));
        // 2.创建实例对象
        Object object = clazz.getConstructor().newInstance();
        // 3.反射执行init service destory
        Method init = clazz.getMethod("init");
        init.invoke(object, null);
        Method service = clazz.getMethod("service");
        service.invoke(object, null);
        Method destory = clazz.getMethod("destory");
        destory.invoke(object, null);

优点: 增强程序的扩展性,并且将配置信息存储到map 中。 功能追加,只需要维护map数据可以

缺点: .class文件不可以直接修改,如果项目上线【给用户直接使用】,用户得到的全是class文件,不利于用户进行程序维护

那么怎么去解决这个问题呢?最先开始想到的就是可以用Properties配置文件 对应map集合 key = value 的形式。 用properties去解决这个问题是十分不错的,是一个可行的办法,同时与properties一样功能的xml配置文件。从灵活程度上来说: .xml格式的文件要比.properties格式的文件更灵活一些,.properties格式的文件已键值对形式存在,主要就是赋值,而且只能赋值,不能够进行其他的操作。
.xml格式的文件可以有多种操作方法,例如添加一个属性,或者做一些其他的定义等。

3.xml的引入
第四版修改

       //模拟从外界传递进来的参数
        String url="/s2";       
        //需要根据url参数  判断执行哪个java类
        //相当于程序配置信息
        //如果是/s1   执行MyServlet1  如果是/s2   执行MyServlet2   如果是/s3   执行MyServlet3

        //数据是存储在xml中,是把xml中的数据读取出来填充进map中
        //解析三步  把数据读取到内存中
        SAXReader reader = new SAXReader();
        Document dom = reader.read(new FileInputStream("src\\xml\\web.xml"));
        Element root = dom.getRootElement();
        //把所有的Servlet标签都获取到   全路径
        List<Element> servletList = root.elements("servlet");

        //把所有的Servlet-mapping标签都获取   url参数
        List<Element> servletmappingList = root.elements("servlet-mapping");

        //需要将   名字-全路径       key=名字     value=全路径     map
        HashMap<String, String> servletMap = new HashMap<String,String>();
        //填充servletMap
        for(Element temp:servletList){
            String key = temp.elementText("servlet-name");
            String value = temp.elementText("servlet-class");
            servletMap.put(key, value);
        }

        //需要将   名字-url       key=名字     value=url     map
        HashMap<String, String> servletmappingMap = new HashMap<String,String>();
        for(Element temp:servletmappingList){
            String key = temp.elementText("servlet-name");
            String value = temp.elementText("url-pattern");
            servletmappingMap.put(key, value);
        }

        //把上述两个map转存到底下的map中
        //key=url    value=全路径
        Map<String, String> map = new HashMap<String,String>();
        for(String key:servletMap.keySet()){
            String url_param = servletmappingMap.get(key);
            String servlet_class = servletMap.get(key);
            map.put(url_param, servlet_class);
        }

        //反射修改    MyServlet1
        //1、获取对应的字节码文件
        Class clazz = Class.forName(map.get(url));
        //2、创建实例对象     MyServlet1 obj = new MyServlet1();
        Object obj = clazz.getConstructor().newInstance();
        //3、反射执行init   service  destory
        Method init = clazz.getMethod("init");
        init.invoke(obj, null);
        Method service = clazz.getMethod("service");
        service.invoke(obj, null);
        Method destory = clazz.getMethod("destory");
        destory.invoke(obj, null);

    }

xml如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5">
    <servlet>
        <servlet-name>Servlet1</servlet-name>
        <servlet-class>xml.demo1.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/s1</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>Servlet2</servlet-name>
        <servlet-class>xml.demo1.MyServlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet2</servlet-name>
        <url-pattern>/s2</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>Servlet3</servlet-name>
        <servlet-class>xml..demo.MyServlet3</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet3</servlet-name>
        <url-pattern>/s3</url-pattern>
    </servlet-mapping>
</web-app>

注意:
反射和xml解析意味着效率底下,从上述代码的改进可以看出效率与扩展性永远是一道单选题,如果要增强效率必然要牺牲效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值