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

xiaoxiao2021-02-28  65

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解析意味着效率底下,从上述代码的改进可以看出效率与扩展性永远是一道单选题,如果要增强效率必然要牺牲效率。

转载请注明原文地址: https://www.6miu.com/read-56369.html

最新回复(0)