Tomcat 底层是一个Servlet容器,管理了很多的servlet
分为以下内容
1 对请求和响应进行封装
2 提供一个NIOsocket
3 进行请求的转发
一 封装请求和响应
package com.tomcat.http;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.QueryStringDecoder;
import java.util.List;
import java.util.Map;
public class Request {
private ChannelHandlerContext ctx;
private HttpRequest req;
public Request(ChannelHandlerContext ctx, HttpRequest req) {
this.ctx = ctx;
this.req = req;
}
public String getUrl() {
return req.getUri();
}
public String getMethod() {
return req.getMethod().name();
}
public Map<String, List<String>> getParameters() {
QueryStringDecoder decoder = new QueryStringDecoder(req.getUri());
return decoder.parameters();
}
public String getParameter(String name) {
Map<String, List<String>> params = getParameters();
List<String> param = params.get(name);
if (null == param) {
return null;
} else {
return param.get(0);
}
}
}
package com.tomcat.http;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import java.io.IOException;
public class Response {
private ChannelHandlerContext ctx;
private HttpRequest req;
public Response(ChannelHandlerContext ctx, HttpRequest req) {
this.ctx = ctx;
this.req = req;
}
public void write(String out) throws IOException {
if (out == null || out.length() == 0) {
return;
}
try {
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(out.getBytes("UTF-8")));
response.headers().set("Content-Type", "text/html;");
ctx.write(response);
} finally {
ctx.flush();
ctx.close();
}
}
}
二 提供Tomcat启动
package com.tomcat.http;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import java.io.FileInputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class Tomcat {
private int port = 8080;
private ServerSocket server;
private Map<String, ZServlet> servletMap = new HashMap<>();
private Properties webxml = new Properties();
private void init() {
String WEB_INF = this.getClass().getResource("/").getPath();
FileInputStream fis = null;
try {
fis = new FileInputStream(WEB_INF + "web.properties");
webxml.load(fis);
for (Object k : webxml.keySet()) {
String key = k.toString();
if (key.endsWith(".url")) {
String servletName = key.replaceAll("\\.url$", "");
String url = webxml.getProperty(key);
String className = webxml.getProperty(servletName + ".className");
ZServlet ob = (ZServlet) Class.forName(className).newInstance();
servletMap.put(url, ob);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void start() {
init();
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap();
server.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel client) throws Exception {
client.pipeline().addLast(new HttpResponseEncoder());
client.pipeline().addLast(new HttpRequestDecoder());
client.pipeline().addLast(new TomcatHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = server.bind(port).sync();
System.out.println("新版tomcat已经启动,监听:" + this.port);
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
public class TomcatHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest) {
System.out.println("hello");
HttpRequest req = (HttpRequest) msg;
Request requesT = new Request(ctx, req);
Response response = new Response(ctx, req);
String url = requesT.getUrl();
if (servletMap.containsKey(url)) {
servletMap.get(url).service(requesT, response);
}else {
response.write("404");
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable msg) throws Exception {
}
}
}
三 处理handler具体的servlet
package com.tomcat.http;
import java.io.IOException;
public abstract class ZServlet {
public void service(Request zRequest, Response zResponse) throws IOException {
if ("GET".equalsIgnoreCase(zRequest.getMethod())) {
doGet(zRequest, zResponse);
} else {
doPost(zRequest, zResponse);
}
}
public abstract void doGet(Request zRequest, Response zResponse) throws IOException;
public abstract void doPost(Request zRequest, Response zResponse) throws IOException;
}
package com.tomcat.http;
import java.io.IOException;
public class FirstServlet extends ZServlet {
@Override
public void doGet(Request zRequest, Response zResponse) throws IOException {
this.doPost(zRequest, zResponse);
}
@Override
public void doPost(Request zRequest, Response zResponse) throws IOException {
zResponse.write("This is servlet");
}
}