今天看到有人写了个简单的tomcat,让我想起多年以前自己也写了个demo,兴奋了好意振。贴出来分享下。有些简陋... 自定义服务器及浏览器.rar
转:
最近研究一方socket编程,由于想动手写关于socket方面的东西。然而我们知道通过URL去访问某网址,其实其底层用的就是socket,于是我就写了一个很简单的tomcat服务器,主要目地在于学习,在此分享给大家。同时提供下载源工程。
我写的工程用Maven管理的,但是我没有引入其它的JAR包,为此我就不列出pom.xml文件了。
在此简要地说明每个类的作用:
Server.java
该类的作用就是将服务提起来的,并且利用线程池。
01.
package
com.cloud.tomcat.server;
02.
03.
import
java.io.OutputStreamWriter;
04.
import
java.io.PrintWriter;
05.
import
java.net.ServerSocket;
06.
import
java.net.Socket;
07.
import
java.util.concurrent.ExecutorService;
08.
import
java.util.concurrent.Executors;
09.
10.
public
class
Server {
11.
private
static
ServerSocket serverSocket;
12.
private
static
ExecutorService executorService;
13.
private
final
static
int
POOL_SIZE =
15
;
14.
15.
public
static
void
main(String[] args)
throws
Exception {
16.
serverSocket =
new
ServerSocket(
8080
);
17.
Socket socket =
null
;
18.
executorService = Executors.newFixedThreadPool(POOL_SIZE);
19.
20.
while
(
true
) {
21.
socket = serverSocket.accept();
22.
PrintWriter writer =
new
PrintWriter(
new
OutputStreamWriter(socket.getOutputStream(),
"UTF-8"
));
23.
writer.println(
"HTTP/1.1 200 OK"
);
24.
writer.println(
"Content-Type: text/html;charset=UTF-8"
);
25.
writer.println();
26.
27.
executorService.execute(
new
Handler(socket, writer));
28.
}
29.
}
30.
}
Handler.java
该类的作用是根据浏览器传过来信息做出相应的处理,同时实现Runnable接口。
01.
package
com.cloud.tomcat.server;
02.
03.
import
java.io.BufferedReader;
04.
import
java.io.IOException;
05.
import
java.io.InputStream;
06.
import
java.io.InputStreamReader;
07.
import
java.io.PrintWriter;
08.
import
java.net.Socket;
09.
10.
import
com.cloud.tomcat.servlet.HttpServlet;
11.
12.
public
class
Handler
implements
Runnable {
13.
private
Socket socket;
14.
private
PrintWriter writer;
15.
16.
public
Handler(Socket socket, PrintWriter writer) {
17.
this
.socket = socket;
18.
this
.writer = writer;
19.
}
20.
21.
@Override
22.
public
void
run() {
23.
try
{
24.
InputStream inputStream = socket.getInputStream();
25.
BufferedReader reader =
new
BufferedReader(
new
InputStreamReader(inputStream));
26.
String path =
""
;
27.
String method =
""
;
28.
29.
while
(
true
) {
30.
String msg = reader.readLine();
31.
if
(
null
== msg ||
""
.equals(msg.trim())) {
32.
break
;
33.
}
34.
35.
String[] msgs = msg.split(
" "
);
36.
if
(
3
== msgs.length &&
"HTTP/1.1"
.equalsIgnoreCase(msgs[
2
])) {
37.
method = msgs[
0
];
38.
path = msgs[
1
];
39.
break
;
40.
}
41.
}
42.
43.
if
(path.endsWith(
"ico"
)) {
44.
return
;
45.
}
46.
47.
HttpServlet httpServlet = ServletContainer.getHttpServlet(path);
48.
String html =
""
;
49.
if
(
"GET"
.equals(method)) {
50.
html = httpServlet.doGet();
51.
}
else
if
(
"POST"
.equals(method)) {
52.
html = httpServlet.doGet();
53.
}
54.
writer.write(html);
55.
writer.flush();
56.
}
catch
(IOException e) {
57.
e.printStackTrace();
58.
}
finally
{
59.
try
{
60.
writer.close();
61.
socket.close();
62.
}
catch
(Exception e) {
63.
e.printStackTrace();
64.
}
65.
}
66.
67.
}
68.
69.
}
ServletContainer.java
该类首先会解析web.xml文件,然后根据url的信息,拿到相应的servlet。
01.
package
com.cloud.tomcat.server;
02.
03.
import
java.util.HashMap;
04.
import
java.util.Map;
05.
06.
import
com.cloud.tomcat.model.Servlet;
07.
import
com.cloud.tomcat.model.ServletMapping;
08.
import
com.cloud.tomcat.servlet.HttpServlet;
09.
import
com.cloud.tomcat.util.XMLUtil;
10.
11.
public
class
ServletContainer {
12.
private
static
Map<String, Object> servletMaps =
new
HashMap<String, Object>();
13.
private
static
Map<String, Object> servletMappingMaps =
new
HashMap<String, Object>();
14.
private
static
Map<String, HttpServlet> servletContainer =
new
HashMap<String, HttpServlet>();
15.
16.
static
{
17.
try
{
18.
Map<Integer, Map<String, Object>> maps = XMLUtil.parseWebXML();
19.
if
(
null
!= maps &&
2
== maps.size()) {
20.
servletMaps = maps.get(
0
);
21.
servletMappingMaps = maps.get(
1
);
22.
}
23.
}
catch
(Exception e) {
24.
e.printStackTrace();
25.
}
26.
}
27.
28.
public
static
HttpServlet getHttpServlet(String path) {
29.
30.
if
(
null
== path ||
""
.equals(path.trim()) ||
"/"
.equals(path)) {
31.
path =
"/index"
;
32.
}
33.
34.
if
(servletContainer.containsKey(path)) {
35.
return
servletContainer.get(path);
36.
}
37.
38.
if
(!servletMappingMaps.containsKey(path)) {
39.
return
null
;
40.
}
41.
ServletMapping servletMapping = (ServletMapping) servletMappingMaps.get(path);
42.
String name = servletMapping.getName();
43.
44.
if
(!servletMaps.containsKey(name)) {
45.
return
null
;
46.
}
47.
Servlet servlet = (Servlet) servletMaps.get(name);
48.
String clazz = servlet.getClazz();
49.
50.
if
(
null
== clazz ||
""
.equals(clazz.trim())) {
51.
return
null
;
52.
}
53.
54.
HttpServlet httpServlet =
null
;
55.
try
{
56.
httpServlet = (HttpServlet) Class.forName(clazz).newInstance();
57.
servletContainer.put(path, httpServlet);
58.
}
catch
(Exception e) {
59.
e.printStackTrace();
60.
}
61.
return
httpServlet;
62.
}
63.
}
HttpServlet.java
为了实现起来简单方便,我自己定义了一个HttpServlet。
1.
package
com.cloud.tomcat.servlet;
2.
3.
public
interface
HttpServlet {
4.
public
String doGet();
5.
public
String doPost();
6.
}
CloudServlet.java
HttpServlet的具体实现类。
01.
package
com.cloud.tomcat.servlet;
02.
03.
public
class
CloudServlet
implements
HttpServlet {
04.
05.
@Override
06.
public
String doGet() {
07.
return
this
.doPost();
08.
}
09.
10.
@Override
11.
public
String doPost() {
12.
return
"<h1>Chicago at Cloud!!!</h1>"
;
13.
}
14.
15.
}
下面一一列出解析web.xml用到的类,由于我没有引入第三JAR包,可能这部分有点麻烦。
Servlet.java
01.
package
com.cloud.tomcat.model;
02.
03.
public
class
Servlet {
04.
private
String name;
05.
private
String clazz;
06.
07.
public
String getName() {
08.
return
name;
09.
}
10.
11.
public
void
setName(String name) {
12.
this
.name = name;
13.
}
14.
15.
public
String getClazz() {
16.
return
clazz;
17.
}
18.
19.
public
void
setClazz(String clazz) {
20.
this
.clazz = clazz;
21.
}
22.
}
ServletMapping.java
01.
package
com.cloud.tomcat.model;
02.
03.
public
class
ServletMapping {
04.
private
String name;
05.
private
String url;
06.
07.
public
String getName() {
08.
return
name;
09.
}
10.
11.
public
void
setName(String name) {
12.
this
.name = name;
13.
}
14.
15.
public
String getUrl() {
16.
return
url;
17.
}
18.
19.
public
void
setUrl(String url) {
20.
this
.url = url;
21.
}
22.
}
01.
package
com.cloud.tomcat.util;
02.
03.
import
java.io.InputStream;
04.
import
java.util.HashMap;
05.
import
java.util.Map;
06.
07.
import
javax.xml.parsers.DocumentBuilder;
08.
import
javax.xml.parsers.DocumentBuilderFactory;
09.
10.
import
org.w3c.dom.Document;
11.
import
org.w3c.dom.Element;
12.
import
org.w3c.dom.Node;
13.
import
org.w3c.dom.NodeList;
14.
15.
import
com.cloud.tomcat.model.Servlet;
16.
import
com.cloud.tomcat.model.ServletMapping;
17.
18.
public
class
XMLUtil {
19.
20.
public
static
Map<Integer, Map<String, Object>> parseWebXML()
throws
Exception {
21.
Map<Integer, Map<String, Object>> result =
new
HashMap<Integer, Map<String,Object>>();
22.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
23.
DocumentBuilder db = dbf.newDocumentBuilder();
24.
25.
InputStream in = XMLUtil.
class
.getClassLoader().getResourceAsStream(
"web.xml"
);
26.
Document document = db.parse(in);
27.
Element root = document.getDocumentElement();
28.
NodeList xmlNodes = root.getChildNodes();
29.
for
(
int
i =
0
; i < xmlNodes.getLength(); i++) {
30.
Node config = xmlNodes.item(i);
31.
if
(
null
!= config && config.getNodeType() == Node.ELEMENT_NODE) {
32.
String nodeName1 = config.getNodeName();
33.
if
(
"servlet"
.equals(nodeName1)) {
34.
Map<String, Object> servletMaps =
null
;
35.
if
(result.containsKey(
0
)) {
36.
servletMaps = result.get(
0
);
37.
}
else
{
38.
servletMaps =
new
HashMap<String, Object>();
39.
}
40.
41.
NodeList childNodes = config.getChildNodes();
42.
Servlet servlet =
new
Servlet();
43.
for
(
int
j =
0
; j < childNodes.getLength(); j++) {
44.
Node node = childNodes.item(j);
45.
if
(
null
!= node && node.getNodeType() == Node.ELEMENT_NODE) {
46.
String nodeName2 = node.getNodeName();
47.
String textContent = node.getTextContent();
48.
if
(
"servlet-name"
.equals(nodeName2)) {
49.
servlet.setName(textContent);
50.
}
else
if
(
"servlet-class"
.equals(nodeName2)) {
51.
servlet.setClazz(textContent);
52.
}
53.
}
54.
}
55.
servletMaps.put(servlet.getName(), servlet);
56.
57.
result.put(
0
, servletMaps);
58.
}
else
if
(
"servlet-mapping"
.equals(nodeName1)) {
59.
Map<String, Object> servletMappingMaps =
null
;
60.
if
(result.containsKey(
1
)) {
61.
servletMappingMaps = result.get(
1
);
62.
}
else
{
63.
servletMappingMaps =
new
HashMap<String, Object>();
64.
}
65.
66.
NodeList childNodes = config.getChildNodes();
67.
ServletMapping servletMapping =
new
ServletMapping();
68.
for
(
int
j =
0
; j < childNodes.getLength(); j++) {
69.
Node node = childNodes.item(j);
70.
if
(
null
!= node && node.getNodeType() == Node.ELEMENT_NODE) {
71.
String nodeName2 = node.getNodeName();
72.
String textContent = node.getTextContent();
73.
if
(
"servlet-name"
.equals(nodeName2)) {
74.
servletMapping.setName(textContent);
75.
}
else
if
(
"url-pattern"
.equals(nodeName2)) {
76.
servletMapping.setUrl(textContent);
77.
}
78.
}
79.
}
80.
servletMappingMaps.put(servletMapping.getUrl(), servletMapping);
81.
82.
result.put(
1
, servletMappingMaps);
83.
}
84.
}
85.
}
86.
return
result;
87.
}
88.
89.
public
static
void
main(String[] args)
throws
Exception {
90.
System.out.println(parseWebXML());
91.
}
92.
}
01.
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
02.
<
web-app
xmlns
=
"http://java.sun.com/xml/ns/javaee"
03.
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
04.
xsi:schemaLocation
=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
05.
version
=
"2.5"
>
06.
07.
<
servlet
>
08.
<
servlet-name
>cloud</
servlet-name
>
09.
<
servlet-class
>com.cloud.tomcat.servlet.CloudServlet</
servlet-class
>
10.
</
servlet
>
11.
12.
<
servlet-mapping
>
13.
<
servlet-name
>cloud</
servlet-name
>
14.
<
url-pattern
>/index</
url-pattern
>
15.
</
servlet-mapping
>
16.
</
web-app
>
运行结果:
将Server类运行起来,然后用浏览器输入:
http://localhost:8080/index或http://localhost:8080
得到如下结果: