实现Tomcat底层机制+自己设计Servlet

Tomcat有三种运行模式(BIO,NIO,APR),这里我们来模拟BIO线程模型模拟Tomcat。
Tomcat的运行流程:
当用户在浏览器地址栏输入url,一回车就会发出一个HTTP请求。
这个请求到达Tomcat过后,由tomcat里的Socket网络编程接收请求,它接收这个请求之后就会创建一个线程,一个请求对应一个线程。启动线程去处理请求,这个线程就会分析,解析请求URL,如果发现请求是Servlet就会调用对应的Servlet完成业务,如果是静态资源就会直接返回。

首先我们知道Tomcat的运行机制是这样,分为三个阶段
在这里插入图片描述

基于Socket开发服务流程(第一阶段)

在这里插入图片描述

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Author: 诉衷情の麻雀
 * @Description: 第一个版本的tomcat, 可以完成接收浏览器的请求,并返回信息
 * @DateTime: 2023/7/3 11:59
 **/
public class tomcat {
    public static void main(String[] args) throws IOException {
        //1.创建ServerSocket, 在8080端口监听
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("=====mytomcat在8080端口监听=====");
        while (!serverSocket.isClosed()) {
            //等待浏览器/客户端的连接
            //如果有连接就创建一个socket
            Socket socket = serverSocket.accept();
            //先接收浏览器发送的数据
            // 字节流 => BufferedReader(字符流)
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));

            String mes = null;
            System.out.println("=====接收到浏览器发送的数据==========");
            //循环的读取
            while ((mes = bufferedReader.readLine()) != null) {
                //判定mes的长度是否为0
                if (mes.length() == 0) {
                    break; //退出循环
                }
                System.out.println(mes);

            }

            //我们的tomcat回送http响应方式
            OutputStream outputStream = socket.getOutputStream();
            //构建一个http响应体
            String respHeader = "HTTP/1.1 200\r\n" +
                    "Content-Type: text/html;charset=utf-8\r\n\r\n";
            String resp = respHeader + "hi,诉衷情的麻雀";
            System.out.println("***********自定义的tomcat返回的数据如下:****************");
            System.out.println(resp);
            outputStream.write(resp.getBytes()); //将resp字符串以byte[]方式返回

            outputStream.flush();
            outputStream.close();
            inputStream.close();
            socket.close();
        }
    }
}


在这里插入图片描述

控制台信息:

C:\Users\27837\.jdks\corretto-1.8.0_372\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\lib\idea_rt.jar=49337:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\charsets.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\access-bridge-64.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\cldrdata.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\dnsns.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\jaccess.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\jfxrt.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\localedata.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\nashorn.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\sunec.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\sunjce_provider.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\sunmscapi.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\sunpkcs11.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\ext\zipfs.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\jce.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\jfr.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\jfxswt.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\jsse.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\management-agent.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\resources.jar;C:\Users\27837\.jdks\corretto-1.8.0_372\jre\lib\rt.jar;C:\Users\27837\IdeaProjects\SparrowTomcat2\target\classes tomcat
=====mytomcat在8080端口监听=====
=====接收到浏览器发送的数据==========
GET /calServlet?num1=9&num2=8 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Microsoft Edge";v="114"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/cal.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: adminUserName=admin; Hm_lvt_cd8218cd51f800ed2b73e5751cb3f4f9=1685415115,1685417440,1685417753,1686711339; studentUserName=student; remember-me=c3R1ZGVudDoxNjg5MzAzNjE5MTcwOjVhY2I0ZmIwOWNkNzlhOGNhMzk2Y2VjMzYxN2U3YTA2; Idea-cbb45668=ad78c5a9-9163-44be-bea9-5e6e627f4d28; Pycharm-5a41dc58=6b00e104-f55a-4310-8cad-877cb8a7b5bf; Webstorm-d0f6cdaf=9c2a0698-aac2-42f2-924c-3bf948a95d65; JSESSIONID=8ED27513A220BF1F4CF218CB3E886E61
***********自定义的tomcat返回的数据如下:****************
HTTP/1.1 200
Content-Type: text/html;charset=utf-8

hi,诉衷情的麻雀
=====接收到浏览器发送的数据==========
***********自定义的tomcat返回的数据如下:****************
HTTP/1.1 200
Content-Type: text/html;charset=utf-8

hi,诉衷情的麻雀

因为这个阶段只是单线程,现在我们来模拟多线程

使用BIO线程模型,支持多线程(版本2)

package com.sparrow.servlet.tomcat.handler;

import java.io.*;
import java.net.Socket;

/**
 * @Author: 诉衷情の麻雀
 * @Description: 是一个线程对象
 * 处理一个http请求的
 * @DateTime: 2023/7/3 12:57
 **/
public class RequestHandler implements Runnable {

    //定义Socket
    private Socket socket = null;

    public RequestHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        //这里我们可以对客户端/浏览器进行IO编程/交互
        try {
            InputStream inputStream = socket.getInputStream();
            //把InputStream -> BufferedReader 方便进行按行读取
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
            System.out.println("当前的线程:" + Thread.currentThread().getName());
            System.out.println("*******tomcatV2接收到的数据如下***********");
            String mes = null;
            while ((mes = bufferedReader.readLine()) != null) {
                //如果长度为0 是空字符串”“
                if (mes.length() == 0) {
                    break;
                }
                System.out.println(mes);

                //构建http响应头
                //返回http的响应头之间有两个换行
                String respHeader = "HTTP/1.1 200\r\n" +
                        "Content-Type: text/html;charset=utf-8\r\n\r\n"; //根据HTTP响应头规则 这里要换一行
                String resp = respHeader + "<h1>Hi 诉衷情の麻雀</h1>";
                System.out.println("********TomcatVe返回的数据如下:***************");
                //返回数据给我们的浏览器/客户端->封装成http响应
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write(resp.getBytes());//将resp字符串以byte[]方式返回
                outputStream.flush();
                outputStream.close();
                inputStream.close();
                socket.close();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

package com.sparrow.servlet;

import com.sparrow.servlet.tomcat.handler.RequestHandler;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Author: 诉衷情の麻雀
 * @Description: TODO
 * @DateTime: 2023/7/3 13:12
 **/
public class tomcatV2 {
    public static void main(String[] args) throws IOException {
        //在8080端口监听
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("==========tomcatV2在8080端口监听================");
        //只要serverSocket没有关闭,就一直等待浏览器/客户端连接
        while (!serverSocket.isClosed()) {
            //1.接收到浏览器的连接后,如果成功,就会得到socket
            //2.这个socket就是服务器和浏览器的数据通道
            Socket socket = serverSocket.accept();
            //3.创建一个线程对象,并且把socket给该线程
            new Thread(new RequestHandler(socket)).start();
        }
    }
}

自己封装HttpRequest对象

package com.sparrow.servlet.http;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;

/**
 * @Author: 诉衷情の麻雀
 * @Description: 封装http请求的数据
 * 比如 method get/post URi/参数
 * @DateTime: 2023/7/3 13:55
 **/
public class SparrowRequest {
    private String method;
    private String uri;

    //存放参数列表 参数名->参数值 HashMap
    private HashMap<String, String> parameterMapping = new HashMap<String, String>();
    private InputStream inputStream = null;

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public SparrowRequest(InputStream inputStream) {
        this.inputStream = inputStream;
        //完成对http请求数据的封装...
        init();
    }


    //request对象有个特别重要的方法
    public String getParameter(String name) {
        if (parameterMapping.containsKey(name)) {
            return parameterMapping.get(name);
        }else {
            return "";
        }
    }



    //构造器=> http请求封装 然后提供相关的方法获取
    //inputStream是和对应http请求的socket关联
    public void init() {
        System.out.println("init被调用了........");
        //inputStream->BufferedReader
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
            //读取第一行
            /**
             * GET /calServlet?num1=9&num2=8 HTTP/1.1
             */
            String requestLine = bufferedReader.readLine();
            String[] requestLineArr = requestLine.split(" ");
            method = requestLineArr[0];
            //解析得到 /calServlet
            //1.先看看uri有没有参数列表
            int index = requestLineArr[1].indexOf("?");
            if (index == -1) { //说明没有参数列表
                uri = requestLineArr[1];
            }else {
                //[0,index)
                uri = requestLineArr[1].substring(0, index);
                //获取参数列表->parametersMapping
                //parameters num1=9&num2=8
                String parameters = requestLineArr[1].substring(index + 1);

                String[] parametersPair = parameters.split("&");
                //防止用户提交/calServlet?
                if (null != parametersPair && !"".equals(parametersPair)) {
                    //再次分割
                    for (String parameterPair : parametersPair) {
                        //parameterVal ["num1","9"] ["num2","8"]
                        String[] parameterVal = parameterPair.split("=");
                        if (parameterVal.length == 2) {
                            //放入到parametersMapping
                            parameterMapping.put(parameterVal[0], parameterVal[1]);
                        }
                    }
                }
            }
            //这里不能关闭inputStream
//            inputStream.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public String toString() {
        return "SparrowRequest{" +
                "method='" + method + '\'' +
                ", uri='" + uri + '\'' +
                ", parameterMapping=" + parameterMapping +
                '}';
    }
}

封装HttpResponse对象

package com.sparrow.servlet.http;

import java.io.OutputStream;

/**
 * @Author: 诉衷情の麻雀
 * @Description: Response对象可以封装OutputStream(是socket关联)
 * Response对象的作用等价于原生的servlet的HttpServletResponse
 * @DateTime: 2023/7/3 13:58
 **/
public class SparrowResponse {
    private OutputStream outputStream = null;

    //http的响应头
    public static final String respHeader ="HTTP/1.1 200\r\n" +
            "Content-Type: text/html;charset=utf-8\r\n\r\n";

    //OutputStream是和对应http请求的socket关联
    public SparrowResponse(OutputStream outputStream) {
        this.outputStream = outputStream;
    }

    //当我们需要给浏览器返回数据时,可以通过SparrowResponse的输出流完成
    public OutputStream getOutputStream() {
        return outputStream;
    }
}

改进线程对象Handler

package com.sparrow.servlet.tomcat.handler;

import com.sparrow.servlet.SparrowCalServlet;
import com.sparrow.servlet.http.SparrowRequest;
import com.sparrow.servlet.http.SparrowResponse;

import java.io.*;
import java.net.Socket;

/**
 * @Author: 诉衷情の麻雀
 * @Description: 是一个线程对象
 * 处理一个http请求的
 * @DateTime: 2023/7/3 12:57
 **/
public class RequestHandler implements Runnable {

    //定义Socket
    private Socket socket = null;

    public RequestHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        //这里我们可以对客户端/浏览器进行IO编程/交互
        try {
            InputStream inputStream = socket.getInputStream();
            SparrowRequest sparrowRequest = new SparrowRequest(inputStream);
            SparrowResponse sparrowResponse = new SparrowResponse(socket.getOutputStream());
            //创建SparrowCalServlet对象
            SparrowCalServlet sparrowCalServlet = new SparrowCalServlet();
            sparrowCalServlet.doGet(sparrowRequest, sparrowResponse);


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

构建HttpServlet

package com.sparrow.servlet;

import com.sparrow.servlet.http.SparrowRequest;
import com.sparrow.servlet.http.SparrowResponse;

import java.io.IOException;

/**
 * @Author: 诉衷情の麻雀
 * @Description: TODO
 * @DateTime: 2023/7/3 13:51
 **/
public abstract class SparrowHttpServlet implements SparrowServlet{

    public void service(SparrowRequest request, SparrowResponse response) throws IOException {
        if ("GET".equalsIgnoreCase(request.getMethod())) {
            this.doGet(request, response);
        } else if ("POST".equalsIgnoreCase(request.getMethod())) {
            this.doPost(request, response);
        }
    }

    //使用模板设计模式 延迟到子类Servlet实现
    public abstract void doGet(SparrowRequest request, SparrowResponse response);
    public abstract void doPost(SparrowRequest request, SparrowResponse response);
}

自定义Servlet

package com.sparrow.servlet;

import com.sparrow.servlet.http.SparrowRequest;
import com.sparrow.servlet.http.SparrowResponse;
import com.sparrow.servlet.utils.WebUtils;

import java.io.IOException;
import java.io.OutputStream;

/**
 * @Author: 诉衷情の麻雀
 * @Description: TODO
 * @DateTime: 2023/7/3 13:53
 **/
public class SparrowCalServlet extends SparrowHttpServlet{

    public void doGet(SparrowRequest request, SparrowResponse response) {
        System.out.println("SparrowCalServlet被调用了...");
        //写业务代码完成计算任务
        int num1 = WebUtils.parseInt(request.getParameter("num1"), 0);
        int num2 = WebUtils.parseInt(request.getParameter("num2"), 0);
        int sum = num1 + num2;
        //返回结果数据
        OutputStream outputStream = response.getOutputStream();
        String respMes = SparrowResponse.respHeader + "<h1>" + num1 + " + " + num2 + " = " + sum + "</h1>";
        try {
            outputStream.write(respMes.getBytes());
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void doPost(SparrowRequest request, SparrowResponse response) {
        this.doGet(request, response);
    }

    public void init() throws Exception {

    }

    public void destroy() {

    }
}

在这里插入图片描述

处理Servlet(版本3)

这是原生的HttpServlet类的结构图

在这里插入图片描述

在这里插入图片描述
现在我们自己定义一个Servlet接口规范和HttpServlet抽象类,然后写一个CalServlet继承自定义的Servlet

构建一个容器

package com.sparrow.servlet;

import com.sparrow.servlet.tomcat.handler.RequestHandler;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: 诉衷情の麻雀
 * @Description: 实现通过xml+反射来初始化容器
 * @DateTime: 2023/7/3 16:34
 **/
public class tomcatV3 {

    //1.存放容器servletMapping
    //HashMap
    //key -value
    //ServletName 对应的实例
    public static final ConcurrentHashMap<String, SparrowHttpServlet> servletMapping = new ConcurrentHashMap<String, SparrowHttpServlet>();
    //2.还有一个容器servletURLMapping
    //ConcurrentHashMap
    //HashMap key - value
    //url-Pattern ServletName
    public static final ConcurrentHashMap<String, String> servletUrlMapping = new ConcurrentHashMap<String, String>();
        //tomcat还维护一个容器 存放session
    public static final ConcurrentHashMap<String, HttpSession> sessionMapping = new ConcurrentHashMap<String, HttpSession>();

    //tomcat还维护了filter的容器
    public static final ConcurrentHashMap<String, String> filterUrlMapping = new ConcurrentHashMap<String, String>();
 public static final ConcurrentHashMap<String, Filter> filterMapping = new ConcurrentHashMap<String, Filter>();
    
    //直接对两个容器进行初始化
    public void init() {
        //读取web.xml => dom4j
        //得到web.xml文件的路径
        String path = tomcatV3.class.getResource("/").getPath();
        System.out.println("path=" + path);
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(new File(path + "web.xml"));
            System.out.println(document);
            //得到根元素
            Element rootElement = document.getRootElement();
            //得到根元素下面所有的元素
            List<Element> elements = rootElement.elements();
            //遍历并过滤Servlet servletMapping
            for (Element element : elements) {
                if("servlet".equalsIgnoreCase(element.getName())){
                    //这是一个Servlet配置
                    //使用反射将该servlet实例放入到servletMapping
                    Element servletName = element.element("servlet-name");
                    Element servletClass = element.element("servlet-class");
                    servletMapping.put(servletName.getText().trim(),(SparrowHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());
                } else if ("servlet-mapping".equalsIgnoreCase(element.getName())) {
                    //这是一个servlet-mapping配置
                    System.out.println("发现了servlet-mapping的配置");
                    Element servletName = element.element("servlet-name");
                    Element urlPattern = element.element("url-pattern");
                    servletUrlMapping.put(urlPattern.getText(),servletName.getText());
                }
            }
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //验证这两个容器是否初始化
        System.out.println("servletMapping=" + servletMapping);
        System.out.println("servletUrlMapping=" + servletUrlMapping);
    }

    public static void main(String[] args) {
        tomcatV3 tomcatV3 = new tomcatV3();
        tomcatV3.init();
        //启动tomcat容器
        tomcatV3.run();
    }

    //启动tomcatV3容器
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("********tomcatV3在8080端口监听**********8");
            while (!serverSocket.isClosed()) {
                Socket socket = serverSocket.accept();
                RequestHandler requestHandler = new RequestHandler(socket);
                new Thread(requestHandler).start();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

修改RequestHandler

package com.sparrow.servlet.tomcat.handler;

import com.sparrow.servlet.SparrowCalServlet;
import com.sparrow.servlet.SparrowHttpServlet;
import com.sparrow.servlet.http.SparrowRequest;
import com.sparrow.servlet.http.SparrowResponse;
import com.sparrow.servlet.tomcatV3;

import java.io.*;
import java.net.Socket;

/**
 * @Author: 诉衷情の麻雀
 * @Description: 是一个线程对象
 * 处理一个http请求的
 * @DateTime: 2023/7/3 12:57
 **/
public class RequestHandler implements Runnable {

    //定义Socket
    private Socket socket = null;

    public RequestHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        //这里我们可以对客户端/浏览器进行IO编程/交互
        try {

            SparrowRequest sparrowRequest = new SparrowRequest(socket.getInputStream());
            SparrowResponse sparrowResponse = new SparrowResponse(socket.getOutputStream());
            //创建SparrowCalServlet对象

            //1.得到uri->servletName->servlet的实例,真正的运行类型是其子类sparrowCalServlet
            String uri = sparrowRequest.getUri();
            String servletName = tomcatV3.servletUrlMapping.get(uri);
            if (servletName == null) {
                servletName = "";
            }
            //2.通过uri->servletName->servlet的实例
            SparrowHttpServlet sparrowHttpServlet = tomcatV3.servletMapping.get(servletName);

            //3.调用service方法,通过oop的动态绑定机制,调用运行类型的doGet/doPost
            if (sparrowHttpServlet != null) {
                sparrowHttpServlet.service(sparrowRequest,sparrowResponse);
            }else {
                //没有这个servlet返回404
                String resp = SparrowResponse.respHeader + "<h1>404 Not Found</h1>";
                OutputStream outputStream = sparrowResponse.getOutputStream();
                outputStream.write(resp.getBytes());
                outputStream.flush();
                outputStream.close();
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

web.xml

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>SparrowCalServlet</servlet-name>
    <servlet-class>com.sparrow.servlet.SparrowCalServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>SparrowCalServlet</servlet-name>
    <url-pattern>/sparrowCalServlet</url-pattern>
  </servlet-mapping>
</web-app>

在这里插入图片描述
在这里插入图片描述

 //1.得到uri->servletName->servlet的实例,真正的运行类型是其子类sparrowCalServlet
            String uri = sparrowRequest.getUri();
            if(WebUtils.isHtml(uri)){ //就是静态页面
                String content = WebUtils.readHtml(uri.substring(1));
                content = SparrowResponse.respHeader + content;
                System.out.println("content=" + content);
                //准备返回 得到outputStream,返回信息给浏览器
                OutputStream outputStream = sparrowResponse.getOutputStream();
                outputStream.write(content.getBytes());
                outputStream.flush();
                outputStream.close();
                socket.close();
                return;
            }

在这里再增加是否是静态资源 如果是html则返回
在这里插入图片描述

WebUtils

package com.sparrow.servlet.utils;

import com.sparrow.servlet.tomcatV3;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * @author 诉衷情の麻雀
 * @Description TODO
 * @date 2023/7/2
 * @Version 1.0
 */
public class WebUtils {
    /**
     * 将一个字符串数字转为int,如果转换失败 返回默认值
     * @param strNum
     * @param defaultVal
     * @return
     */
    public static int parseInt(String strNum, int defaultVal) {
        try {
            return Integer.parseInt(strNum);
        } catch (NumberFormatException e) {
            System.out.println(strNum + " 格式不对 转换失败");
        }
        return defaultVal;
    }

    //判定uri是不是html文件
    public static boolean isHtml(String uri) {
        return uri.endsWith(".html");
    }

    //根据文件名来读取该文件->String
    public static String readHtml(String filename) {
        String path = tomcatV3.class.getResource("/").getPath();
        StringBuilder stringBuilder = new StringBuilder();
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader(path + filename));
            String buf = "";
            while ((buf = bufferedReader.readLine()) != null) {
                stringBuilder.append(buf);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return stringBuilder.toString();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
学生成绩管理系统是一个比较典型的Web应用程序,可以使用Java Servlet和JSP技术实现。下面是一个简单的实现步骤: 1. 确定系统功能和设计数据库表 首先,我们需要确定学生成绩管理系统的功能需求,例如学生信息管理、课程信息管理、成绩录入和查询等等。然后,设计数据库表格以存储数据。 例如,我们可以设计以下几个表格: 学生表(Student):学生ID、姓名、性别、出生日期、联系方式等。 课程表(Course):课程ID、课程名称、学分等。 成绩表(Score):学生ID、课程ID、成绩等。 2. 创建项目和配置环境 使用IntelliJ IDEA创建一个Web项目,然后配置环境。我们需要配置Tomcat服务器、MySQL数据库连接和JDBC驱动程序等。 3. 实现数据访问层 在项目中创建一个Java类,用于实现数据库的访问操作。我们可以使用JDBC技术连接数据库,然后实现数据的增删改查操作。 4. 实现业务逻辑层 在项目中创建另一个Java类,用于实现业务逻辑。例如,实现学生信息管理、课程信息管理、成绩录入和查询等功能。 5. 实现表示层 使用JSP技术实现用户界面,为用户提供交互界面。例如,实现学生信息管理页面、课程信息管理页面、成绩录入页面和查询页面等。 6. 部署和测试系统 最后,我们需要将项目部署到Tomcat服务器上,并测试学生成绩管理系统的功能和性能。 总之,使用IntelliJ IDEA、Java Servlet、JSP、MySQL和Tomcat等技术实现学生成绩管理系统是非常简单的。只需要按照上述步骤一步步实现,就可以得到一个完整的Web应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诉衷情の麻雀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值