文章目录
目的服务器实现步骤req和resp的定义MyServlet模板的定义==加载核心容器==服务器端多线程访问处理
目录结构
目的
理解服务器的核心容器以及servlet工作原理。
服务器实现步骤
浏览器发起的每个请求,都需要解析和响应,对请求报文解析,和响应报文部分内容封装请求对象和响应对象(HttpServletRequest和HttpServletResponse都是接口,由org.apache.catalina.connector(Tomcat)包下面的RequestFacade和ResponseFacade实现并进行实例化)。
定义处理服务类的标准格式(MyServlet)
加载核心容器(MyServlet容器),开启监听
服务器端多线程处理
ps:socket是对TCP/IP协议的封装。
req和resp的定义
遵循http协议,解析请求、响应报文。MyReq.java
public class MyReq {
private String method
;
private String url
;
public MyReq(InputStream is
) {
BufferedReader br
= new BufferedReader(new InputStreamReader(is
));
try {
String reqHeader
= br
.readLine();
String
[] reqHeaderArr
= reqHeader
.split(" ");
this.method
= reqHeaderArr
[0];
this.url
= reqHeaderArr
[1];
} catch (IOException e
) {
e
.printStackTrace();
}
}
public String
getMethod() {
return method
;
}
public String
getUrl() {
return url
;
}
}
MyResp.java
public class MyResp {
public static String respHeader
= "HTTP/1.1 200 OK\r\n" +
"Content-Type:text/html;charset=utf-8\r\n" +
"\r\n";
private OutputStream writer
;
public MyResp(OutputStream os
) {
this.writer
= os
;
}
public OutputStream
getWriter() {
return writer
;
}
}
MyServlet模板的定义
MyServlet.java
public abstract class MyServlet {
public void doService(MyReq req
, MyResp resp
) {
String reqMethod
= req
.getMethod();
if ("GET".equals(reqMethod
)) {
doGet(req
, resp
);
} else {
doPost(req
, resp
);
}
}
public abstract void doGet(MyReq req
, MyResp resp
);
public abstract void doPost(MyReq req
, MyResp resp
);
}
编写两个类继承MyServlet模板,以作测试
public class LoginServlet extends MyServlet {
@Override
public void doGet(MyReq req
, MyResp resp
) {
OutputStream respWriter
= resp
.getWriter();
try {
respWriter
.write(MyResp
.respHeader
.getBytes());
respWriter
.write("login ok!".getBytes());
respWriter
.flush();
respWriter
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
@Override
public void doPost(MyReq req
, MyResp resp
) {
doGet(req
, resp
);
}
}
public class RegistServlet extends MyServlet {
@Override
public void doGet(MyReq req
, MyResp resp
) {
OutputStream respWriter
= resp
.getWriter();
try {
respWriter
.write(MyResp
.respHeader
.getBytes());
respWriter
.write("register ok!".getBytes());
respWriter
.flush();
respWriter
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
@Override
public void doPost(MyReq req
, MyResp resp
) {
doGet(req
, resp
);
}
}
加载核心容器
配置文件:myMapping.properties
servlet
.one
.url
=/login
servlet
.one
.class=com
.myserver
.servlet
.LoginServlet
servlet
.two
.url
=/regist
servlet
.two
.class=com
.myserver
.servlet
.RegistServlet
MyServer.java
public class MyServer {
static Map
<String, MyServlet> myMapping
= new HashMap<>();
static Properties prop
= new Properties();
public static void myInit() {
try {
prop
.load(MyServer
.class.getResourceAsStream("/myMapping.properties"));
Set
<Object> set
= prop
.keySet();
set
.forEach(k
-> {
if (k
.toString().contains("url")) {
String url
= prop
.getProperty(k
.toString());
String classKey
= k
.toString().replace("url", "class");
String className
= prop
.getProperty(classKey
);
try {
MyServlet myms
= (MyServlet
) Class
.forName(className
).newInstance();
myMapping
.put(url
, myms
);
} catch (InstantiationException e
) {
e
.printStackTrace();
} catch (IllegalAccessException e
) {
e
.printStackTrace();
} catch (ClassNotFoundException e
) {
e
.printStackTrace();
}
}
});
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static void serverBegin() {
try {
ServerSocket ss
= new ServerSocket(8021);
System
.out
.println("开始监听 8021 端口,等待访问...");
while (true) {
Socket accept
= ss
.accept();
Thread myThread
= new Thread(new MyProccess(accept
));
myThread
.start();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
public static void main(String
[] args
) {
MyServer
.myInit();
MyServer
.serverBegin();
}
}
服务器端多线程访问处理
MyProccess.java
public class MyProccess implements Runnable {
private Socket accept
;
public MyProccess(Socket accept
) {
this.accept
= accept
;
}
@Override
public void run() {
try {
MyReq req
= new MyReq(accept
.getInputStream());
MyResp resp
= new MyResp(accept
.getOutputStream());
MyServlet myServlet
= MyServer
.myMapping
.get(req
.getUrl());
if (myServlet
!= null
) {
myServlet
.doService(req
, resp
);
} else {
OutputStream respWriter
= resp
.getWriter();
respWriter
.write(MyResp
.respHeader
.getBytes());
respWriter
.write("404 not found!".getBytes());
respWriter
.flush();
respWriter
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
目录结构