模仿《netty4 核心核心原理》一书中的例子,通过java自带的IO类和serverSocket 实现简单tomcat功能。
通过启动启动类,在浏览器输入对应的地址,实现访问:
具体代码如下:
- tomcat servlet类
public abstract class MServlet {
public void service(MRequest request,MResponse response)throws Exception{
if("GET".equalsIgnoreCase(request.getMethod())){
doGet(request,response);
}else {
doPost(request,response);
}
}
public abstract void doGet(MRequest request,MResponse response) throws Exception;
public abstract void doPost(MRequest request,MResponse response) throws Exception;
}```
2,tomcat servlet实现类=对应controller
public class FirstServlet extends MServlet{
@Override
public void doGet(MRequest request, MResponse response) throws Exception {
this.doPost(request,response);
}
@Override
public void doPost(MRequest request, MResponse response) throws Exception {
response.write("firstServlet");
}
}
3,tomcat servlet实现类2=对应controller
public class SecondServlet extends MServlet{
@Override
public void doGet(MRequest request, MResponse response) throws Exception {
this.doPost(request,response);
}
@Override
public void doPost(MRequest request, MResponse response) throws Exception {
response.write("SecondServlet");
}
}```
4,请求体类
public class MRequest {
private String method;
private String url;
public MRequest(InputStream in){
try {
String content = "";
byte[] buff = new byte[1024];
int len = 0;
if((len=in.read(buff))>0){
content = new String(buff, 0, len);
}
String line = content.split("\\n")[0];
String[] split = line.split("\\s");
this.method = split[0];
this.url = split[1].split("\\?")[0];
}catch (Exception e){
e.printStackTrace();
}
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
5,响应体类
public class MResponse {
private OutputStream outputStream;
public MResponse(OutputStream out){
this.outputStream = out;
}
public void write(String s)throws Exception{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("HTTP/1.1 200 OK\n").append("Content-Type: text/html;\n").append("\r\n").append(s);
outputStream.write(stringBuilder.toString().getBytes());
}
}
6,tomcat 核心类-启动类
public class Mtomcat {
private int port = 8080;
private ServerSocket serverSocket;
private Map<String, MServlet> servletMapping = new HashMap<>();
private Properties webXml = new Properties();
private void init(){
try {
// 模拟加载配置文件
String path = this.getClass().getResource("/").getPath();
FileInputStream fileInputStream = new FileInputStream(path + "config.properties");
webXml.load(fileInputStream);
for (Object o : webXml.keySet()) {
String key = o.toString();
if(key.endsWith(".url")){
String servletName = key.replaceAll("\\.url$", "");
String url = webXml.getProperty(key);
String className = webXml.getProperty(servletName + ".className");
MServlet servlet = (MServlet) Class.forName(className).newInstance();
servletMapping.put(url, servlet);
}
}
}catch (Exception e){
e.printStackTrace();
}
}
public void start(){
init();
try {
serverSocket = new ServerSocket(this.port);
System.out.println("tomcat 已启动,监听的端口是:"+this.port);
while (true){
process(serverSocket.accept());
}
}catch (Exception e){
e.printStackTrace();
}
}
private void process(Socket client)throws Exception{
InputStream inputStream = client.getInputStream();
OutputStream outputStream = client.getOutputStream();
MRequest request = new MRequest(inputStream);
MResponse response = new MResponse(outputStream);
String url = request.getUrl();
if(servletMapping.containsKey(url)){
servletMapping.get(url).service(request,response);
}else {
response.write("404-not found");
}
outputStream.flush();
outputStream.close();
inputStream.close();
client.close();
}
public static void main(String[] args) {
new Mtomcat().start();
}
}
7配置文件:
servlet.one.url=/firstServlet.do
servlet.one.className=com.test.zlb.FirstServlet
servlet.two.url=/secondServlet.do
servlet.two.className=com.test.zlb.SecondServlet
8,项目结构: