开发Minicat V4.0,在已有Minicat基础上进一步扩展,模拟出webapps部署效果 磁盘上放置一个webapps目录,webapps中可以有多个项目,例如demo1、demo2、demo

  1. 在minicat的resources目录下,增加server.xml配置文件
    <?xml version="1.0" encoding="UTF-8" ?>
    <Server>
        <!--可以有多个service-->
        <Service>
            <Connector port="8080"/>
            <Engine>
                <Host name="localhost" appBase="D:\lianxi\stage2\module1\miniCat\webapps"></Host>
            </Engine>
        </Service>
    </Server>

  2. 加载解析server.xml,获取到appBase的路径,初始化webapps,webapps中有多个demo(应用项目)
    /**
         *  4.0 版本:  加载 server.xml,解析并初始化 webapps 下面的各个项目的 servlet
         */
        private void loadServlet() throws DocumentException, ClassNotFoundException, FileNotFoundException {
            InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
            // 使用dom4j
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();   //  <Server>    一个server下可以有多个service
            List<Element> servicetNodes = rootElement.selectNodes("//Service");
            for (Element service : servicetNodes) {   // 遍历所有service   找每一个service下的Connector  <Connector port="8080"/>
                Element connectorElement = (Element) service.selectSingleNode("Connector");  // <Connector port="8080"/>
                prot = Integer.parseInt(connectorElement.attributeValue("port"));  //获取到port的值
    
                // 获取 Host
                List<Element> hostList = rootElement.selectNodes("//Host");
                for (Element host : hostList) {
                    // 获取host标签中那么的属性值   name="localhost"
                    String hostName = host.attributeValue("name");
                    // appBase="D:\lianxi\stage2\module1\miniCat\webapps"
                    String appBase = host.attributeValue("appBase");
    //                System.out.println("=======appBase转换前的格式:======="+appBase);
                    String webapps = appBase.replaceAll("\\\\", "/");
    //                System.out.println("=======appBase转换后的格式:======="+webapps);
    
                    // 获取该路径的文件夹  webapps
                    File file = new File(appBase);
                    if (file.exists() && file.isDirectory()){ // 如果该file存在而且是个文件夹  webapps,下面有多个项目应用
                        // 遍历该文件夹
                        File[] files = file.listFiles();
                        for (File file1 : files) {   // 得到每一个demo
                            // 获取每一个demo的路径
                            String path = file1.getPath();
                            System.out.println("获取每一个demo的路径=====>"+path);
                            //  单个项目文件名
    //                        String fileName = path.replace(file.getPath()+"\\","");
    //                        System.out.println("单个项目文件名=====>"+fileName);
                            //读取web.xml文件
                            String webpath = path+"\\web.xml";
                            System.out.println("webpath:"+webpath);
    
                            loadServletwebxml(webpath,appBase);
                        }
                    }
                }
            }
        }
  3. 读取每一个demo下的web.xml,并解析
    private void loadServletwebxml(String webPath,String clazz) throws DocumentException, ClassNotFoundException, FileNotFoundException {
            System.out.println("loadServletwebxml方法中的路径==="+webPath);
            System.out.println("clazz***"+clazz);
            FileInputStream resourceAsStream =  new FileInputStream(webPath);
    //        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(webPath);  // 用这个类加载器加载不了,需要自定义类加载器
            MyClassLoader myClassLoader = new MyClassLoader();
    
            // 使用dom4j
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (Element element : selectNodes) {
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");  // <servlet-name>myservlet</servlet-name>
                String servletName = servletnameElement.getStringValue(); // myservlet
    
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");  // <servlet-class>server.MyServlet</servlet-class>
                String servletClass = servletclassElement.getStringValue(); // server.MyServlet
                System.out.println("servletClass----"+servletClass);
    
    
                myClassLoader.findClass(clazz,servletClass);
    
                // 根据servlet-name的值,定位 url-pattern 的值
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();  //  <url-pattern>/</url-pattern>   就是 :/
    
                try {
                    // 存储解析的web.xml中 <servlet>和<servlet-mapping>的映射关系
                    // Map<String,HttpServlet>
                    servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
    
            }
        }

  4. minicat需要自定义一个类加载器来加载部署在webapps中的class文件
    package server;
    
    import java.io.*;
    
    public class MyClassLoader extends ClassLoader {
    
        @Override
        protected Class<?> findClass(String basePath, String className) {
            byte[] classBytes = getClassBytes(basePath, className);
            return defineClass(className, classBytes, 0, classBytes.length);
        }
    
        /**
         * 读取类的字节码
         *
         * @param basePath  根路径
         * @param className 类的全限定名
         * @return servlet 的字节码信息
         * @throws IOException
         */
        private byte[] getClassBytes(String basePath, String className) {
            InputStream in = null;
            ByteArrayOutputStream out = null;
            String path = basePath + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
            try {
                in = new FileInputStream(path);
                out = new ByteArrayOutputStream();
                byte[] buffer = new byte[2048];
                int len = 0;
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
                return out.toByteArray();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    
    
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值