自定义tomcat

一、需求分析

开发Minicat V4.0,在已有Minicat基础上进⼀步扩展,模拟出webapps部署效果 磁盘上放置⼀个webapps⽬录,webapps中可以有多个项⽬,⽐如demo1,demo2,demo3… 具体的项⽬⽐如demo1中有serlvet(也即为:servlet是属于具体某⼀个项⽬的servlet),这样的话在 Minicat初始化配置加载,以及根据请求url查找对应serlvet时都需要进⼀步处理。
1.有一个文件夹作为部署的目录,不管是否是在Minicat文件夹下面。
2.webapps下面可以放置项目,一个项目一个servlet.class文件、一个web.xml配置文件。也就是说不要将项目放到Minicat里面,需要自己新建一个项目并编译。

二、实现分析

已完成功能分析

1.使用socket实现接收请求,处理请求的功能。
2.解析接受到的请求,将其封装为request和response对象,分别持有inputstream和ouputstream。
3.通过线程处理请求,根据请求地址去解析,找到相应的servlet对象。
4.在Minicat初始化的时候,读取resource中的web.xml文件,解析其中标签,存储到Map中,等待请求时使用。

待完成功能分析

1.将servlet相关代码脱离出Minicat,打包成一个jar包,供各个项目使用。
2.修改Minicat代码,使之去检查webapps目录下检查其下的文件中是否存在servlet项目。
3.解析class文件。

三、实现

1.获取webapps的路径,检查是否存在,然后遍历其中的文件夹。

URI webapps = this.getClass().getClassLoader().getResource("webapps").toURI();
        File file = new File(webapps);
        if(file.exists()){
            //判断是否是目录,然后进行遍历
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (File file2 : files) {
                    //解析相应的servlet文件夹下面的web.xml
                    if (file2.isDirectory()) {
                        doLoadServlet(file2);
                    }
                }
            }
        }else{
            System.out.println("webapps文件夹不存在!");
        }

2.解析文件夹中的web.xml,在其中我们使用了自定义的类加载器来加载本文件夹下的class类。

   private void doLoadServlet(File servletFile) {
        FileInputStream resourceAsStream;
        SAXReader saxReader = new SAXReader();
        String path=servletFile.getAbsolutePath();
        MyClassLoader  myClassLoader=new MyClassLoader(path);
        //myClassLoader.setClasspath(path);
        File webxml=new File(path+File.separator+ "web.xml");
        if(webxml.exists()){
            try {
                resourceAsStream = new FileInputStream(webxml);
                Document document = saxReader.read(resourceAsStream);
                Element rootElement = document.getRootElement();

                List<Element> selectNodes = rootElement.selectNodes("//servlet");
                for (int i = 0; i < selectNodes.size(); i++) {
                    Element element =  selectNodes.get(i);
                    // <servlet-name>lagou</servlet-name>
                    Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                    String servletName = servletnameElement.getStringValue();
                    // <servlet-class>LagouServlet</servlet-class>
                    Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                    String servletClass = servletclassElement.getStringValue();

                    // 根据servlet-name的值找到url-pattern
                    Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                    // /lagou
                    String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                    //将路径加入到类加载器
                    Class c=myClassLoader.loadClass(servletClass);

                    servletMap.put(urlPattern, (HttpServlet) c.newInstance());

                }
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

    }

MyClassLoader

package server;

import java.io.*;

public class MyClassLoader extends ClassLoader{
    private String classpath;
    public MyClassLoader() {
    }
    public MyClassLoader(String classpath) {
        this.classpath = classpath;
    }

    public String getClasspath() {
        return classpath;
    }

    public void setClasspath(String classpath) {
        this.classpath = classpath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException{
        try {
            byte [] classDate=getData(name);
            if(classDate==null){}
            else{
                //defineClass方法将字节码转化为类
                return defineClass(name,classDate,0,classDate.length); }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }
    //返回类的字节码
    private byte[] getData(String className) throws IOException{
        InputStream in = null;
        ByteArrayOutputStream out = null;
        String path=classpath + 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 (FileNotFoundException e) {
            e.printStackTrace();
        } finally{
            in.close();
            out.close();
        }
        return null;
    }
}

3.在webapps文件夹中放置相应的servlet测试文件夹,配置相关的web.xml,进行请求即可。
在这里插入图片描述

4.我们创建了两个servlet类,打包后将文件拷贝到webapps中,分别返回不同的值,结果如下。
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值