自定义Tomcat

一、Tomcat_v1

Tomcat服务器本质上就是一个 Server的程序,所以这里我们先写一个Server的程序和Socket程序,先完成最基本的通讯功能

Server.java:

package com.tomcat_v1.mySocket_v1;

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

public class Server {
    public static void main(String[] args) {
        ServerSocket server;

        try {
            server = new ServerSocket(8888);
            System.out.println("服务器已启动,初始化端口为:8888");
            //这里不断接受服务端的请求
            while(true){
                //服务器端接收到客户端的Socket连接过来(在接收客户端请求之前会一直阻塞在这里)
                Socket client = server.accept();
                System.out.println("客户端["+client.getInetAddress().getHostAddress()+"]已连接到服务器");
                /**
                 * 请求信息
                 */
                //获取客户端发送过来的信息
                InputStream in = client.getInputStream();  //异步处理
                byte[] buff = new byte[1024];
                int length = in.read(buff);
                if(length>0) {
                    String msg = new String(buff, 0, length);
                    System.out.println("服务端接收到客户端的信息:" + msg);
                }
                /**
                 * 响应信息
                 */
                //获取客户端输出流, 回复信息
                OutputStream out = client.getOutputStream();
                //构建响应信息
                StringBuffer sb = new StringBuffer();
                //响应正文
                String html = "服务器已收到信息";
                sb.append(html);
                out.write(sb.toString().getBytes());
                System.out.println("服务器响应结束\n");
                out.flush();
                out.close();
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Server类中主要完成了一下功能:

  1. 初始化ServerSocket
  2. 等待接收客户端请求
  3. 解析请求信息
  4. 发出响应信息

Client.java:

package com.tomcat_v1.mySocket_v1;

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

public class Client {
    public static void main(String[] args) {
            try {
                Socket socket = new Socket("127.0.0.1",8888);
                Thread.sleep(10000);
                /**
                 * 发送请求信息
                 */
                OutputStream out = socket.getOutputStream();
                out.write("客户端[2]发送信息".getBytes());
                out.flush(); //刷新缓冲区,将数据发送出去

                /**
                 * 接收响应信息
                 * 在接收到服务端返回的信息之前会一直阻塞在这里,直到服务器端发送流信息过来
                 */
                System.out.println("等待接收服务端信息......");
                InputStream in = socket.getInputStream();
                StringBuffer sb = new StringBuffer();
                int len;
                byte[] buff=new byte[1024];
                while((len=in.read(buff)) != -1 ){
                    sb.append(new String(buff, 0, len));
                }
                System.out.println("服务器响应信息:"+sb.toString());

                in.close();
                out.close();

            } catch (Exception e) {
                e.printStackTrace();
            }


        }
}

Client类主要完成的功能:

  1. 初始化Socket, 连接到服务端
  2. 发送请求信息
  3. 接收服务器的响应信息

控制台输出:

服务器端:

客户端1:

客户端2:

 

由上可见, 服务端与客户端已完成通讯, 在tomcat中接收请求和响应分别由Request和Response来进行处理, 那么, 我们只需要把Server类中关于接收请求部分逻辑和响应分别封装到自定义的Request和Response中即可

二、Tomcat_v2

Server.java

package com.tomcat_v1.mySocket_v2;

import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) {
        ServerSocket server;
        try {
            server = new ServerSocket(8888);
            System.out.println("服务器已启动,初始化端口为:8888");
            /**
             * 接受客户端的请求
             * 每次只能接收一个客户端的请求, 在前一个客户端请求未处理完成之前, 之后的请求会被阻塞(阻塞式IO)
             */
            while(true){
                //服务器端接收到客户端的Socket连接过来(在接收客户端请求之前会一直阻塞在这里)
                Socket client = server.accept();
                System.out.println("客户端["+client.getInetAddress().getHostAddress()+"]已连接到服务器");
                /**
                 * 接收请求信息(由request进行处理)
                 * 如果没有获取到客户端发送过来的流信息,则程序会阻塞,直到客户端发送流信息过来
                 */
                //获取客户端发送过来的信息
                System.out.println("等待接收客户端信息......");
                Request request = new Request(client.getInputStream());
                request.resolverRequest();

               /* Thread.sleep(10000);*/
                /**
                 * 发送响应信息(由response进行处理)
                 */
                //获取客户端输出流, 回复信息
                Response response = new Response(client.getOutputStream());
                response.resolverResponse();

                System.out.println("服务端响应结束\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Request.java

package com.tomcat_v1.mySocket_v2;

import java.io.IOException;
import java.io.InputStream;

public class Request {
    private InputStream in;
    public Request(InputStream in) {
       this.in = in;
    }
    public void resolverRequest() {
        try {
            byte[] buff = new byte[1024];
            int length = in.read(buff);
            if(length>0) {
                String msg = new String(buff, 0, length);
                System.out.println("服务端接收到客户端的信息:" + msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Response.java

package com.tomcat_v1.mySocket_v2;

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

public class Response {

    private OutputStream out;

    public Response(OutputStream out) {
        super();
        this.out = out;
    }

    public void resolverResponse(){
        try {
            //构建响应信息
            StringBuffer sb = new StringBuffer();
            //响应正文
            String content = "服务器已收到信息";
            sb.append(content);
            out.write(sb.toString().getBytes());
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

分别定义Request和Response, 将接收请求和响应的逻辑放在这两类中进行处理, 这里逻辑上并没有变化, 只是封装了一下;

而在tomcat中, 我们可以利用浏览器发送请求信息, 在服务端处理这些请求信息, 然后响应给浏览器; 而主要的处理逻辑是由我们编写的Servlet类来实现; 通常情况下是通过继承HttpServlet类重写doGet和doPost方法实现, 如下:

 自定义Servlet:

package com.bookstore.constant;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		super.service(req, resp);
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		super.doGet(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	
		super.doPost(req, resp);
	}

}

接下来实现自定义的tomcat

三、Tomcat_v3

项目结构:

第一步:  实现主启动类Server.java,在这个类里创建一个ServerSocket,等待客户端的连接,并且创建一个线程池, 把连接交由线程去处理; 在前一个连接处理完成后进入死循环, 继续等待下一个客户端的连接;

Server.java

package com.tomcat_v2.tomcat;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {
    private static ServerSocket serverSocket;
    private static int port = 8080;
    private final static int POOL_SIZE = 8;
    private static ExecutorService executorService;

    public static void start(){
        try {
            serverSocket = new ServerSocket(port);
            Socket socket = null;
            System.out.println("服务器已启动, 初始化端口为:"+port);
            executorService = Executors.newFixedThreadPool(POOL_SIZE); //初始化线程池
            while(true){
                socket = serverSocket.accept();  //等待获取客户端请求
                System.out.println("服务器已接收到请求");
                executorService.execute(new Handler(socket));  //分配线程处理请求,响应
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        start();
    }
}

第二步:  在接收到客户端请求后, 将请求和响应分开处理, 那么首先需要自定义Request和Response; 

Request.java

package com.tomcat_v2.tomcat;

import com.tomcat_v2.servlet.HttpServlet;
import com.tomcat_v2.servlet.ServletContainer;

import java.util.Map;

public class Request {
    private String path;
    private String method;
    private Map<String,Object> parameter;
    private Map<String,String> attributes;

    public HttpServlet getServlet(){
        return ServletContainer.getHttpServlet(path);
    }
    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getMethod() {
        return method;
    }

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

    public Map<String, Object> getParameter() {
        return parameter;
    }

    public void setParameter(Map<String, Object> parameter) {
        this.parameter = parameter;
    }

    public Map<String, String> getAttributes() {
        return attributes;
    }

    public void setAttributes(Map<String, String> attributes) {
        this.attributes = attributes;
    }
}

Request类中包含请求的方式(GET,POST), 请求的路径, 属性,以及参数信息

Response.java

package com.tomcat_v2.tomcat;

import java.io.*;

public class Response {
    private PrintWriter printWriter;

    public Response(PrintWriter printWriter) {
        this.printWriter = printWriter;
    }

    public void write(String msg){
        if(msg != null){
            printWriter.write(msg);
            printWriter.flush();
        }
    }

    public void forword(String dest){
        InputStream in = this.getClass().getClassLoader().getResourceAsStream(dest);
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        try {
            String s =null;
            do{
                 s = reader.readLine();
                 write(s);
            }while (s != null);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Reponse中主要通过对客户端Socket的输出流进行操作, 输出数据;

writer()方法: 通过输出流向浏览器输出信息

forword()方法: 根据指定的资源信息,将该资源输出到浏览器上; 比如请求的html页面

第三步:  tomcat中对于业务逻辑的处理主要维护在Servlet中, 因此我们需要先定义一个抽象类HtppServlet

HttpServlet.java

package com.tomcat_v2.servlet;

import com.tomcat_v2.tomcat.Request;
import com.tomcat_v2.tomcat.Response;
import com.tomcat_v2.util.Constant;

public abstract class HttpServlet {
    public void doGet(Request request, Response response){ }
    public void doPost(Request request, Response response){ }
    public void service(Request request, Response response){
        if(Constant.REQUEST_METHOD_GET.equals(request.getMethod())){
            doGet(request,response);
        }else if(Constant.REQUEST_METHOD_POST.equals(request.getMethod())){
            doPost(request,response);
        }
    }
}

Constant.java

package com.tomcat_v2.util;

public class Constant {
    public final static String REQUEST_METHOD_GET ="GET";
    public final static String REQUEST_METHOD_POST ="POST";
}

根据请求方式的不同进行不同的处理

第四步:  在步骤一中将获取到的客户端Socket交由线程池去处理, 那么需要实现一个线程类Handler; 在Handler中首先对请求信息解析, 对响应头进行设置; 然后根据请求路径信息获取到对应的Servlet, 进行处理

Handler.java

package com.tomcat_v2.tomcat;

import com.tomcat_v2.servlet.HttpServlet;
import com.tomcat_v2.util.Constant;

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

public class Handler implements Runnable{
    private Socket socket;
    private PrintWriter writer;

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

    @Override
    public void run() {
        try {
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
            writer.println("HTTP/1.1 200 OK");
            writer.println("Content-Type: text/html;charset=utf-8");
            writer.println();

            Request request = new Request();
            Response response = new Response(writer);

            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            /**
             * 解析请求信息
             */
            while(true){
                String msg = reader.readLine();
                if(msg == null || "".equals(msg.trim())){
                    break;
                }
                String[] msgs = msg.split(" ");
                if(msgs.length == 3 && msgs[2].equalsIgnoreCase("HTTP/1.1")){
                    //设置请求方式
                    request.setMethod(msgs[0]);
                    //设置请求参数
                    String[] pathAndParams = msgs[1].split("\\?");
                    HashMap<String, Object> requestParams = new HashMap<String, Object>();
                    if(pathAndParams.length == 2){
                        String[] params = pathAndParams[1].split("&");
                        for (String param: params) {
                            String key = param.split("=")[0];
                            String value = param.split("=")[1];
                            requestParams.put(key,value);
                        }
                    }
                    request.setParameter(requestParams);
                    //设置请求路径
                    request.setPath(pathAndParams[0]);
                    break;
                }

            }
            if(request.getPath().endsWith("ico")){
                return;
            }
            /**
             * 根据请求信息获取对应的Servlet
             */
            HttpServlet httpServlet = request.getServlet();
            /**
             * 处理请求,以及响应信息
             */
            dispatcher(httpServlet,request,response);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                writer.close();
                socket.close();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
    }

    private void dispatcher(HttpServlet httpServlet, Request request, Response response) {
        try{
            if(httpServlet == null){
                response.write("<h1>404 Not Found</h1>");
                return;
            }
            httpServlet.service(request,response);
        }catch (Exception e){
            response.write("<h1>500 Server Error</h1>");
        }
    }
}

第五步: 在上一步中, 根据不同的请求路径映射不同的Servlet处理类, 那么, 需要将路径信息与对应的处理类Servlet类路径映射起来, 可以根据路径获取Servlet的类路径信息; 因此, 需要配置web.xml

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
    <servlet>
        <servlet-name>servlet_1</servlet-name>
        <servlet-class>com.tomcat_v2.myServlet.Servlet_1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_1</servlet-name>
        <url-pattern>/index</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>servlet_2</servlet-name>
        <servlet-class>com.tomcat_v2.myServlet.Servlet_2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_2</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>servlet_3</servlet-name>
        <servlet-class>com.tomcat_v2.myServlet.Servlet_3</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_3</servlet-name>
        <url-pattern>/test2</url-pattern>
    </servlet-mapping>
</web-app>

第六步: 有了web.xml来将Servlet与请求路径映射起来, 那么首先要做的就是对web.xml进行解析; 在web.xml中维护着servlet与servlet-mapping信息, 这两个节点通过servlet-name进行关联, 而我们最终需要的是路径信息与servlet类路径进行关联, 因此, 需要定义实体类ServletServletMapping

Servlet.java

package com.tomcat_v2.servlet;

public class Servlet {
    private String name;
    private String clazz;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

ServletMapping.java 

package com.tomcat_v2.servlet;

public class ServletMapping {
    private String name;
    private String url;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
}

第七步: 定义util类来解析web.xml

XMLUtil.java

package com.tomcat_v2.util;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import com.tomcat_v2.servlet.Servlet;
import com.tomcat_v2.servlet.ServletMapping;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;



public class XMLUtil {

    public static Map<String, Map<String, Object>> parseWebXML() throws Exception{

        Map<String, Map<String, Object>> result = new HashMap<String, Map<String,Object>>();
        //DOM解析器工厂实例
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //获取DOM解析器
        DocumentBuilder db = dbf.newDocumentBuilder();
        //把要解析的XML文档转化为输入流,让DOM解析器解析,从src根目录开始读取
        InputStream in = XMLUtil.class.getClassLoader().getResourceAsStream("web.xml");
        //解析输入流,获得document对象
        Document document = db.parse(in);
        //得到xml的根节点
        Element root = document.getDocumentElement();
        //得到根节点的子节点
        NodeList xmlNodes = root.getChildNodes();
        //循环读取
        for(int i = 0; i < xmlNodes.getLength(); i++) {
            Node config = xmlNodes.item(i);
            //判断是否为元素节点
            if(config != null && config.getNodeType()==Node.ELEMENT_NODE) {
                String nodeName1 = config.getNodeName();

                /**
                 * 解析<servlet>节点
                 */
                if("servlet".equals(nodeName1)) {
                    Map<String, Object> servletMaps = null;
                    if(!result.containsKey("servletMaps")) {
                        result.put("servletMaps", new HashMap<String, Object>());
                    }
                    servletMaps = result.get("servletMaps");
                    //获取元素节点的所有子节点
                    NodeList childNodes = config.getChildNodes();
                    //创建servlet实体类准备接受数据
                    Servlet servlet = new Servlet();

                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node node = childNodes.item(j);
                        //判断是否为元素节点
                        if(node != null && node.getNodeType()==Node.ELEMENT_NODE) {
                            //读取servlet-name和servlet-class
                            String nodeName2 = node.getNodeName();
                            //读取文本内容
                            String textContent = node.getTextContent();
                            if(nodeName2.equals("servlet-name")) {
                                servlet.setName(textContent);
                            }else if(nodeName2.equals("servlet-class")) {
                                servlet.setClazz(textContent);
                            }
                        }
                    }
                    //结果放到Map中
                    servletMaps.put(servlet.getName(), servlet);
                }
                /**
                 * 解析<servlet-mapping>节点
                 */
                if (nodeName1.equals("servlet-mapping")) {
                    Map<String, Object> servletMappingMaps = null;
                    if(!result.containsKey("servletMappingMaps")) {
                        result.put("servletMappingMaps", new HashMap<String, Object>());
                    }
                    servletMappingMaps = result.get("servletMappingMaps");
                    //获取元素节点的所有子节点
                    NodeList childNodes = config.getChildNodes();
                    //创建实体类
                    ServletMapping servletMapping = new ServletMapping();

                    for(int j = 0; j < childNodes.getLength(); j++) {
                        Node node = childNodes.item(j);
                        if(node!=null && node.getNodeType()==Node.ELEMENT_NODE) {
                            String nodeName2 = node.getNodeName();
                            String textContent = node.getTextContent();
                            if(nodeName2.equals("servlet-name")) {
                                servletMapping.setName(textContent);
                            }else if (nodeName2.equals("url-pattern")) {
                                servletMapping.setUrl(textContent);
                            }
                        }
                    }
                    servletMappingMaps.put(servletMapping.getUrl(), servletMapping);
                }
            }
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(parseWebXML());
    }

}

第八步: 在第四步中通过调用Request类的getServlet方法,根据路径获取对应的Servlet类; 而在getServlet()方法中调用ServletContainer.getHttpServlet(path)方法来实现

ServletContainer.java

package com.tomcat_v2.servlet;
;

import com.tomcat_v2.util.XMLUtil;

import java.util.HashMap;
import java.util.Map;


public class ServletContainer {

    private static Map<String, Object> servletMaps = new HashMap();
    private static Map<String, Object> servletMappingMaps = new HashMap();
    private static Map<String, HttpServlet> servletContainer = new HashMap();

    //静态代码块加载model实体类
    static {
        try {
            Map<String, Map<String, Object>> maps = XMLUtil.parseWebXML();
            if(maps != null) {
                servletMaps = maps.get("servletMaps");
                servletMappingMaps = maps.get("servletMappingMaps");
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }


    //获取servlet容器中对应的HttpServlet
    public static HttpServlet getHttpServlet(String path) {

        if(path == null || "".equals(path.trim()) || "/".equals(path)) {
            path = "/index";
        }

        if(servletContainer.containsKey(path)) {
            return servletContainer.get(path);
        }
        if(!servletMappingMaps.containsKey(path)) {
            return null;
        }
        ServletMapping servletMapping = (ServletMapping)servletMappingMaps.get(path);
        String name = servletMapping.getName();

        if(!servletMaps.containsKey(name)) {
            return null;
        }

        Servlet servlet = (Servlet)servletMaps.get(name);
        String clazz = servlet.getClazz();

        if(clazz==null || clazz.trim().equals("")) {
            return null;
        }
        HttpServlet httpServlet = null;
        try {
            httpServlet = (HttpServlet)Class.forName(clazz).newInstance();
            servletContainer.put(path, httpServlet);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return httpServlet;
    }

}

ServletContainer中,在静态代码块中调用XMLUtil.parseWebXML()方法来对web.xml进行解析; 然后根据Servlet对象中维护的class信息通过反射进行实例化, 并返回; 在第四步中获取到指定的Servlet后, 通过调用Servlet的service方法来处理请求,响应

第九步: 编写自定义Servlet

Servlet_1.java

package com.tomcat_v2.myServlet;

import com.tomcat_v2.servlet.HttpServlet;
import com.tomcat_v2.tomcat.Request;
import com.tomcat_v2.tomcat.Response;

public class Servlet_1 extends HttpServlet {
    @Override
    public void doGet(Request request, Response response) {
        response.write("<h1>Servlet_1:Hello World</h1>");
    }
}
Servlet_2.java
package com.tomcat_v2.myServlet;

import com.tomcat_v2.servlet.HttpServlet;
import com.tomcat_v2.tomcat.Request;
import com.tomcat_v2.tomcat.Response;

public class Servlet_2 extends HttpServlet {
    @Override
    public void doGet(Request request, Response response) {
        response.write("<h1>Servlet_2:Hello World</h1>");
    }
}
第十步: 启动Server, 在浏览器中输入localhost:8080/index, 向服务器发送信息

至此, 一个简单的自定义tomcat已完成

但是, 在实际应用场景中, 我们并不是让每一个Servlet只处理一个请求的逻辑而是将逻辑写在每一个方法中进行处理; 这里也进行简单的实现:

在servlet中, 逻辑是实现在doGet和doPost方法中, 这样做的局限性是每一个Servlet只能处理一个请求;效率太低; 因此, 我们可以对Servlet进行包装:

BaseServlet.java

package com.tomcat_v2.tomcat;

import com.tomcat_v2.servlet.HttpServlet;

import java.lang.reflect.Method;
import java.util.Map;

public class BaseServlet extends HttpServlet {
    @Override
    public void service(Request request, Response response) {
        Map<String, Object> parameter = request.getParameter();
        String methodName = (String) parameter.get("method");
        if(methodName == null){
            methodName = "index";
        }

        Class clazz = this.getClass();
        try {
            Method method = clazz.getMethod(methodName, request.getClass(), response.getClass());
            String dest = (String) method.invoke(this,request,response);
            if(dest != null){
                response.forword(dest);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String index(Request request, Response response) {
        return null;
    }

}

在HttpServlet的service方法中只是根据请求方式的不同,将请求交由不同的方法进行处理, 局限性是从这里出现的; 因此, 对该方法逻辑进行修改, 通过获取request中请求参数可得到实际请求的方法, 因此可以通过反射执行该方法来完成请求的处理;

Servlet_v3.java

package com.tomcat_v2.myServlet;

import com.tomcat_v2.tomcat.BaseServlet;
import com.tomcat_v2.tomcat.Request;
import com.tomcat_v2.tomcat.Response;

public class Servlet_3 extends BaseServlet {
    public String getAll(Request request, Response response){
        response.write("{name:lic,age:16}");
        return null;
    }
    public String getHtml(Request request, Response response){
        return "index.html";
    }

}

测试1:

不仅可以通过response返回数据, 也可以返回指定的html页面

测试2:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 style="color: red">Hello World</h1>
<h2 style="color: blue;">这是我的第一个网页</h2>
</body>
</html>

在使用tomcat时, 我们需要将自己的项目打成war包,放入tomcat下, 然后启动tomcat即可, 因此可以理解到, 在启动项目时, tomcat会将我们的项目加载到容器中, 通过将请求的路径映射到实体类来完成业务逻辑的处理, 这个后续播客会写出......

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值