主体思路
当我们的Web运行的时候,从浏览器发出的请求,必然首先到达tomcat中,之后由tomcat进行处理,由此要考虑tomcat要进行哪些处理,首先便是提供Socket服务,之后对于请求进行分发,把请求和产生的响应封装成request和response。
- 提供Socket服务
- 封装请求/响应对象
- 将不同的请求映射到具体的Servlet处理
HTTP协议
HTTP协议就是字符串协议需要截取进行处理。
处理请求
从HTTP请求中解析请求路径、请求方法、请求参数等。
package com;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class MyRequest {
//请求路径
private String url;
//请求方法
private String method;
//请求参数
private Map<String,String> map = new HashMap<>();
public MyRequest(InputStream inputStream) throws Exception{
String httpRequest = "";
byte[] httpRequestBytes = new byte[1024];
int length = 0;
if((length = inputStream.read(httpRequestBytes))>0){
httpRequest = new String(httpRequestBytes,0,length);
}
//解析参数
if(httpRequest.length() > 0){
String httpHead = httpRequest.split("\n")[0];
//index?id=tom
String fullUrl = httpHead.split("\\s")[1];
//是否存在参数
if(fullUrl.contains("?")){
String[] arr = fullUrl.split("\\?");
url = arr[0];
String[] params = arr[1].split("&");
for(String parm : params){
String[] param = parm.split("=");
map.put(param[0],param[1]);
}
}else{
url = fullUrl;
}
method = httpHead.split("\\s")[0];
System.out.println(this.toString());
}
}
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;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public String toString() {
return "MyRequest [url=" + url + ", method=" + method + "]";
}
}
处理响应
响应主要是输出符合浏览器协议的字符串。
package com;
import java.io.OutputStream;
public class MyResponse {
private OutputStream outputStream;
public MyResponse(OutputStream outputStream){
this.outputStream = outputStream;
}
//将文本转换成字节流
public void write(String content) throws Exception{
//HTTP响应协议
StringBuffer httpResponse = new StringBuffer();
httpResponse.append("HTTP/1.1 200 0K\n")
.append("Content-Type:text/html\n")
.append("\r\n")
.append("<html><head><link rel=\"icon\" href=\"data:;base64,=\"></head><body>")
.append(content)
.append("</body></html>");
outputStream.write(httpResponse.toString().getBytes());
outputStream.close();
}
}
封装Servlet规范
把请求和响应封装成Servlet规范要求的格式。
package com;
public abstract class MyServlet {
public abstract void doGet(MyRequest myRequest,MyResponse myResponse);
public abstract void doPost(MyRequest myRequest,MyResponse myResponse);
public void service(MyRequest myRequest,MyResponse myResponse){
if(myRequest.getMethod().equalsIgnoreCase("POST")){
doPost(myRequest,myResponse);
}else if(myRequest.getMethod().equalsIgnoreCase("GET")){
doGet(myRequest,myResponse);
}
}
}
package com;
public class HelloWorldServlet extends MyServlet {
@Override
public void doGet(MyRequest myRequest, MyResponse myResponse) {
try {
myResponse.write("get world");
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void doPost(MyRequest myRequest, MyResponse myResponse) {
try {
myResponse.write("post world");
}catch (Exception e){
e.printStackTrace();
}
}
}
package com;
import java.util.Map;
public class IndexServlet extends MyServlet {
@Override
public void doGet(MyRequest myRequest, MyResponse myResponse) {
try {
StringBuffer content = new StringBuffer();
content.append("<h1>Hello Get</h1><br>");
if(myRequest.getMap().size() > 0){
for(Map.Entry<String,String> map : myRequest.getMap().entrySet()){
content.append("<h2>"+map.getKey()+"="+map.getValue()+"</h2><br>");
}
}
myResponse.write(content.toString());
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void doPost(MyRequest myRequest, MyResponse myResponse) {
try {
String content = "<h1>Hello Post</h1>";
myResponse.write(content);
}catch (Exception e){
e.printStackTrace();
}
}
}
Socket服务
package com;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class MyTomcat {
private int port = 8080;
private Map<String,String> urlServletMap = new HashMap<>();
public MyTomcat(int port){
this.port = port;
}
public void start(){
//初始化 URL与对应处理的servlet的关系
initServletMapping();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("MyTomcat is start");
while (true){
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
MyRequest myRequest = new MyRequest(inputStream);
MyResponse myResponse = new MyResponse(outputStream);
//请求分发
dispatcher(myRequest,myResponse);
socket.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 初始化映射
*/
private void initServletMapping(){
for(ServletMapping servletMapping : ServletMappingConfig.servletMappingList){
urlServletMap.put(servletMapping.getUrl(),servletMapping.getClazz());
}
}
private void dispatcher(MyRequest myRequest,MyResponse myResponse){
String clazz = urlServletMap.get(myRequest.getUrl());
try {
//反射
if(clazz != null){
Class<MyServlet> myServletClass = (Class<MyServlet>)Class.forName(clazz);
MyServlet myServlet = myServletClass.newInstance();
myServlet.service(myRequest,myResponse);
}
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
new MyTomcat(8080).start();
}
}
package com;
public class ServletMapping {
private String servletName;
private String url;
private String clazz;
public ServletMapping(String servletName,String url,String clazz){
this.servletName = servletName;
this.url = url;
this.clazz = clazz;
}
public String getServletName() {
return servletName;
}
public void setServletName(String servletName) {
this.servletName = servletName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
}
package com;
import java.util.ArrayList;
import java.util.List;
public class ServletMappingConfig {
public static List<ServletMapping> servletMappingList = new ArrayList<>();
static {
servletMappingList.add(new ServletMapping("index","/index","com.IndexServlet"));
servletMappingList.add(new ServletMapping("world","/world","com.HelloWorldServlet"));
}
}