XML&反射--案例实现

1、准备工作

     1.1、为了模拟服务器端程序,且可以同时存在多个类似程序。故提供接口,接口中有3个方法,我们人为约定三个方法的调用顺序。

public interface MyServlet{
    
    public void init();     //1、初始化

    public void service();  //2、执行

    puvlic void destory();  //3、销毁
 
}

     1.2、再为接口编写实现类(MyServlet.java)

public class HelloServlet implements MyServlet{

    @override
    pubic void init(){
        System.out.println("1.初始化");
    }

    @override
    public void service(){
       System.out.println("2.执行中..."); 
    }

    @override
    public void destory(){
       System.out.println("3.销毁"); 
    }

}

     1.3、测试,创建实现类实例对象

public class TestApp{

    @Test
    public void demo01(){
        //手动创建执行
        MyServlet myservlet = new HelloMyServlet();
        myservlet.init();
        myservlet.service();
        myservlet.destory();
    }


}

2、反射执行

     测试程序我们直接new HelloServlet,这种编程方式我们称为硬编码,即代码是写死的。为了后期程序的可扩展,开发中通常使用实现类的全限定类名(cn.klh.e_web.HelloServlet),通过反射加字符串指定的类,并通过反射创建实例。

@Test
public void demo02() throws Exception{
    /*反射创建执行
     *1)Class.forName 返回指定接口或类的Class对象
     *2)newInstance() 通过Class对象创建类的实例对象,相当于 new Xxx();
     */
    String servletClass = "cn.klh.e_web.HelloMyServlet";
    
    //3)获得字符串实现类实例
    Class clazz = Class.foeName(servletClass);
    MyServlet myServlet = (MyServlet) clazz.newInstance();

    //4)、执行对象的方法
    myServlet.init();
    myServlet.service();
    myServlet.destory();
    
}

3、解析xml

     使用反射我们已经可以创建对象的实例,此时我们使用的全限定类名,在程序中仍写死了,我们将器配置到哦xml文档中。

     xml文档内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5">

	<servlet>
		<servlet-name>HelloServlet</servlet-name>
		<servlet-class>cn.klh.e_web.HelloServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>HelloServlet</servlet-name>
		<url-pattern>/hello</url-pattern>
	</servlet-mapping>
	<servlet>
		<servlet-name>HelloServlet2</servlet-name>
		<servlet-class>cn.klh.e_web.HelloServlet2</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>HelloServlet2</servlet-name>
		<url-pattern>/hello2</url-pattern>
	</servlet-mapping>
</web-app>

     解析实现:

@Test
public void demo03() throws Exception{
    /*读取xml配置文件,获得<servlet-class>配置的内容,取代固定字符串*/    
	
    //1.创建解析器对象
    SAXReader saxReader = new SAXReader();
    //2.使用解析器加载web.xml文件得到document对象
    Document document = saxReader.read(new file("src/cn/klh/e_web/web.xml"));
    //3.获取根元素节点
    Element rootElement = document.getRootElement();
    //4.根据元素名称获取子元素节点
    Element servletElement = rootElement.element("servlet");
    //5.根据元素名称获取servlet-class的文本节点
    String servletClass = servletElement.element("servlet-class");
    //System.out.println(servletClass);
    //6.通过类全名获取字节码文件
    Class clazz = Class.forName(servletClass);
    //7.创建实例对象
    MyServlet1 my = (MyServlet1) clazz.newInstance();
    //8.调用实例对象里面的方法
    my.init();
    my.service();
    my.destory();
	
}

4、模拟浏览器路径

     我们已经解析xml,不过我们获得的内容是固定的。我们希望如果用户访问的路径是/hello,将执行cn.klh.e_web.HelloServlet程序,如果访问的是/hello2,将执行cn.klh.e_web.HelloServle2t程序。

     在执行测试前(@Before),解析xml文件,将解析的结果存放在Map中,map中的数据的格式为:路径=实现类。

     解析xml思路:先解析<servlet>,将结果存放map,name=class,然后再解析<servlet-mapping> ,通过name获得class,再将url=class存放到map,最后将name=class移除。

//最终存放 key=请求路径,value=实现类
private Map<String,String> data = new HashMap<String,String>();

@Before
public void demo04Before() throws Exception{
    //在执行前执行,解析xml,并将结果存放到Map<路径,实现类>中

    //1.创建解析器对象
    SAXReader saxReader = new SAXReader();
    //2.使用解析器加载web.xml文件得到document对象
    Document document = saxReader.read(new file("src/cn/klh/e_web/web.xml"));
    //3.获取根元素节点
    Element rootElement = document.getRootElement();
    //4、获得所有的子元素<servlet>、<servlet-mapping>等
    List<Element> allChildElement = rootElement.element();
    //5、遍历所有
        //1)解析到<servlet>,将其子标签<servlet-name>、<servlet-class>存放到Map中
        //2)解析到<servlet-mapping>,获得子标签<servlet-name>、<url-pattern>,从map中获得1的内容,组合成url=class键值对
    for(Element childElement : allChildElement){
        //5.1获得元素名
        String eleName = chileElement.getName();
        //5.2如果是servlet,将解析内容存放到Map中
        if("servlet".equals(eleName)){
            String servletName = childElement.elementText("servlet-name");
            String servletClass= childElement.elementText("servlet-class");
            data.put(servletName,servletClass);
        }
        //5.3如果是servlet-mapping,获得之前内容,组成成key=url,value=class,并添加到到Map中
        if("servlet-mapping".equals(eleName)){
            String servletName = childElement.elementText("servlet-name");
            String urlPattern= childElement.elementText("url-pattern");
            //获得<servlet-name>之前存放在Map中<servlet-class>值
            String servletClass = data.get(servletName);
            //存放新的内容 url = class
            data.put(urlPattern,servletClass);
            //将之前存储的数据删除
            data.remove(servletName);
        }

        //打印信息
        System.uot.println(data);

    }

}

     模拟浏览器请求路径,通过url从map获得class,并使用反射执行实现类

@Test
public void demo04() throws Exception{
    
    //1模拟路径
    String url = "/hello";
    //String url = "/hello2";

    //2通过路径获得对应的实现类
    String servletClass = data.get(url);

    //3获得字符串实现类实例
    Class clazz = Class.forMame(servletClass);
    MyServlet myServlet = (MyServlet) clazz.newInstance();

    //4执行对象的方法
    myServlet.init();
    myServlet.service();
    myServlet.destory();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值