前面的文章,其实我们说过了。。回忆下
tomcat官网:https://tomcat.apache.org
The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies.
Tomcat 是使用了Java WebSocket技术和serlet技术,tomcat使用java实现
最核心的两部分connector和container
connector部分,我们用bio的方式,websocket实现
container部分,用servlet集成
我们一步一步的说明
新建一个maven项目叫my-tomcat
package com.my.tomcat.bio;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
public class Tomcat {
private static Logger logger= LoggerFactory.getLogger(Tomcat.class);
private static Properties pro = new Properties();
public static void init(){
try {
FileInputStream fileInputStream = new FileInputStream("src/main/resources/server.properties");
pro.load(fileInputStream);
logger.info("init 读取配置完成");
} catch (FileNotFoundException e) {
logger.error("初始化server配置文件错误",e.getMessage());
e.printStackTrace();
} catch (IOException e) {
logger.error("pro加载server报错",e.getMessage());
e.printStackTrace();
}
}
public static void start (){
//启动web容器
int port = Integer.parseInt(pro.getProperty("server.port"));
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
while (true){
Socket accept = serverSocket.accept();
logger.info("收到连接请求.....");
OutputStream outputStream=accept.getOutputStream();
InputStream inputStream = accept.getInputStream();
//先不使用servlet容器
//处理输入
dealInputStream(inputStream);
//处理输出
dealOutStream(outputStream,"success request");
}
} catch (IOException e) {
logger.error("启动tomcat报错",e.getMessage());
e.printStackTrace();
}finally {
if(null !=serverSocket)
{
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void dealInputStream(InputStream inputStream) throws IOException {
String httStr = "";
byte [] contentByte = new byte[1024];
int length;
if ((length = inputStream.read(contentByte)) >0){
httStr = new String(contentByte,0,length);
}
logger.info("访问请求内容为:"+httStr);
}
private static void dealOutStream(OutputStream outputStream, String outContent) throws IOException {
String httpResponse =
"HTTP/1.1 200 OKn" +
"Content-Type: text/htmln" +
"rn" + outContent;
outputStream.write(httpResponse.getBytes());
outputStream.close();
}
public static void main(String[] args) {
init();
start();
}
}
pom.xml文件
4.0.0 org.example my-tomcat 1.0-SNAPSHOT 1.11 UTF-8 org.slf4j slf4j-api 1.5.6 ch.qos.logback logback-classic 1.2.3 maven-compiler-plugin ${java.version} ${java.version} ${build.sourceEncoding}
• Server.properties
server.port=8080
• 使用main方法启动
14:38:57.040 [main] INFO com.my.tomcat.bio.Tomcat - init 读取配置完成
• 结果
访问:http://localhost:8080/mytomcat?id=10
看看控制台打印:
14:45:15.590 [main] INFO com.my.tomcat.bio.Tomcat - 收到连接请求.....
14:45:15.612 [main] INFO com.my.tomcat.bio.Tomcat - 访问请求内容为:GET /mytomcat?id=10 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"
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/100.0.4896.60 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*
public class ServletMappingConfig {
public static List servletMappingList = new ArrayList<>();
public static Logger logger = LoggerFactory.getLogger(ServletMappingConfig.class);
public static void initServletMapping(Properties prop) {
Set strings = prop.stringPropertyNames();
for (String str : strings) {
if (str.endsWith(".url")) {
String servletName = str.replaceAll(".url", "");
String value[] = prop.getProperty(str).split(":");
if (null == value || value.length != 2) {
logger.error("servlet配置异常--key=" + str + "--value=" + prop.getProperty(str));
logger.error("servlet请参考模板格式:servletName.url = ClassName:url");
continue;
}
ServletMapping servletInfo = new ServletMapping(servletName, value[0], value[1]);
logger.info("初始化servlet:" + servletInfo.toString());
servletMappingList.add(servletInfo);
}
}
}
}
package com.my.tomcat.bio.servlet;
public class ServletMapping {
private String servletName;
private String clazz;
private String url;
public ServletMapping(String servletName, String clazz, String url) {
this.servletName = servletName;
this.clazz = clazz;
this.url = url;
}
@Override
public String toString() {
return "ServletMapping{" +
"servletName='" + servletName + ''' +
", clazz='" + clazz + ''' +
", url='" + url + ''' +
'}';
}
public String getServletName() {
return servletName;
}
public void setServletName(String servletName) {
this.servletName = servletName;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
• init方法中servlet配置文件初始化并解析,结果放入内存中
这个在Tomcat类中,最后再看
• start方法中的类
package com.my.tomcat.bio.servlet;
public abstract class Servlet {
public static final String GET="GET";
public static final String PUT="POST";
public abstract void doGet(HttpServletRequest request, HttpServletResponse response);
public abstract void doPost(HttpServletRequest request, HttpServletResponse response);
public void service(HttpServletRequest request, HttpServletResponse response)
{
if(request == null)
{
System.out.println("HttpServletRequest is null");
}
if(response == null)
{
System.out.println("HttpServletResponse is null");
}
if(request.getMethod().equals("GET"))
{
doGet(request,response);
}else if(request.getMethod().equals("POST"))
{
doPost(request,response);
}
}
}
package com.my.tomcat.bio.servlet;
import com.my.tomcat.bio.Tomcat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
public class HttpServletRequest {
private static Logger logger= LoggerFactory.getLogger(HttpServletRequest.class);
private String url;
private String method;
public HttpServletRequest(InputStream inputStream)throws IOException
{
String httStr = "";
byte [] contentByte = new byte[1024];
int length;
if ((length = inputStream.read(contentByte)) >0){
httStr = new String(contentByte,0,length);
}
logger.info("servlet访问请求内容为:"+httStr);
if (!httStr.isEmpty() && !httStr.equals("")) {
String httpHead = httStr.split("n")[0];
method = httpHead.split("\s")[0];
url = httpHead.split("\s")[1];
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}
package com.my.tomcat.bio.servlet;
import java.io.IOException;
import java.io.OutputStream;
public class HttpServletResponse {
private OutputStream outputStream;
public HttpServletResponse(OutputStream outputStream)
{
this.outputStream=outputStream;
}
public void write(String content) throws IOException {
String httpResponse =
"HTTP/1.1 200 OKn" +
"Content-Type: text/htmln" +
"servlet响应"+
"rn" + content;
outputStream.write(httpResponse.getBytes());
outputStream.close();
}
}
• 请求controller servlet的类
package com.my.tomcat.bio.servlet.controller;
import com.my.tomcat.bio.servlet.HttpServletRequest;
import com.my.tomcat.bio.servlet.HttpServletResponse;
import com.my.tomcat.bio.servlet.Servlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class LoginServlet extends Servlet {
public static Logger logger = LoggerFactory.getLogger(LoginServlet.class);
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
logger.info("get method Login Servlet");
try {
response.write("login success");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
logger.info("post method Login Servlet");
try {
response.write("login success");
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.my.tomcat.bio.servlet.controller;
import com.my.tomcat.bio.servlet.HttpServletRequest;
import com.my.tomcat.bio.servlet.HttpServletResponse;
import com.my.tomcat.bio.servlet.Servlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class HelloServlet extends Servlet {
public static Logger logger = LoggerFactory.getLogger(LoginServlet.class);
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
logger.info("get method Hello Servlet");
try {
response.write("Hello success");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
logger.info("post method Hello Servlet");
try {
response.write("Hello success");
} catch (IOException e) {
e.printStackTrace();
}
}
}
• tomcatBio主启动类
package com.my.tomcat.bio;
import com.my.tomcat.bio.servlet.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
public class TomcatBio {
private static Logger logger = LoggerFactory.getLogger(TomcatBio.class);
private static Properties pro = new Properties();
//servlet接口请求池
private static Map servletPool = new ConcurrentHashMap<>();
public static void init() {
try {
FileInputStream fileInputStream = new FileInputStream("src/main/resources/server.properties");
pro.load(fileInputStream);
logger.info("init 读取配置完成");
//初始化servlet配置
ServletMappingConfig.initServletMapping(pro);
//解析servlet配置,并放入请求池中
for (ServletMapping servletMapping : ServletMappingConfig.servletMappingList) {
servletPool.put(servletMapping.getUrl(), servletMapping.getClazz());
}
logger.info("init servlet 配置完成");
} catch (FileNotFoundException e) {
logger.error("初始化server配置文件错误", e.getMessage());
e.printStackTrace();
} catch (IOException e) {
logger.error("pro加载server报错", e.getMessage());
e.printStackTrace();
}
}
public static void start() {
//启动web容器
int port = Integer.parseInt(pro.getProperty("server.port"));
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
while (true) {
Socket accept = serverSocket.accept();
logger.info("收到连接请求.....");
OutputStream outputStream = accept.getOutputStream();
InputStream inputStream = accept.getInputStream();
//使用servlet容器
HttpServletRequest httpServletRequest = new HttpServletRequest(inputStream);
HttpServletResponse httpServletResponse = new HttpServletResponse(outputStream);
dispatch(httpServletRequest,httpServletResponse);
logger.info("servlet请求完成.....");
}
} catch (IOException e) {
logger.error("启动tomcat报错", e.getMessage());
e.printStackTrace();
} finally {
if (null != serverSocket) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void dealInputStream(InputStream inputStream) throws IOException {
String httStr = "";
byte[] contentByte = new byte[1024];
int length;
if ((length = inputStream.read(contentByte)) > 0) {
httStr = new String(contentByte, 0, length);
}
logger.info("访问请求内容为:" + httStr);
}
private static void dealOutStream(OutputStream outputStream, String outContent) throws IOException {
String httpResponse =
"HTTP/1.1 200 OKn" +
"Content-Type: text/htmln" +
"rn" + outContent;
outputStream.write(httpResponse.getBytes());
outputStream.close();
}
public static void dispatch(HttpServletRequest request, HttpServletResponse response) {
if (!servletPool.containsKey(request.getUrl())) {
logger.error("servlet分发器未找到对应的servlet的配置");
try {
String httpResponse =
"HTTP/1.1 200 OKn" +
"Content-Type: text/htmln" +
"rn" + "404 Exception";
response.write(httpResponse);
return;
} catch (IOException e) {
e.printStackTrace();
}
}
String className = servletPool.get(request.getUrl());
try {
Class clazz = (Class) Class.forName(className);
Servlet servlet = clazz.newInstance();
servlet.service(request, response);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
init();
start();
}
}
验证
启动TomcatBio.java–>main()
17:45:27.718 [main] INFO com.my.tomcat.bio.TomcatBio - init 读取配置完成
17:45:27.774 [main] INFO com.my.tomcat.bio.servlet.ServletMappingConfig - 初始化servlet:ServletMapping{servletName='helloServlet', clazz='com.my.tomcat.bio.servlet.controller.HelloServlet', url='/hello'}
17:45:27.774 [main] INFO com.my.tomcat.bio.servlet.ServletMappingConfig - 初始化servlet:ServletMapping{servletName='loginServlet', clazz='com.my.tomcat.bio.servlet.controller.LoginServlet', url='/login'}
17:45:27.774 [main] INFO com.my.tomcat.bio.TomcatBio - init servlet 配置完成
访问:http://localhost:8080/mytomcat?id=10
结果:
访问:http://localhost:8080/login
http://localhost:8080/hello
17:57:07.546 [main] INFO com.my.tomcat.bio.servlet.controller.LoginServlet - get method Login Servlet 17:57:07.548 [main] INFO com.my.tomcat.bio.TomcatBio - servlet请求完成..... 17:57:07.548 [main] INFO com.my.tomcat.bio.TomcatBio - 收到连接请求..... 17:57:12.447 [main] INFO com.my.tomcat.bio.servlet.controller.LoginServlet - get method Hello Servlet 17:57:12.448 [main] INFO com.my.tomcat.bio.TomcatBio - servlet请求完成.....



