0%

手写WebServer笔记

手写WebServer笔记


WebServer简介

上网浏览网页,离不开服务器,客户请求页面,服务器响应内容,响应的内容是根据每个web请求来产生动态内容,其内部即启动多个线程来产生不同内容。这种请求响应式的交互,都是基于HTTP协议的。当然现在随着业务越来越多样化,web服务器变得复杂了,拥有了像缓存、安全和session管理这些附加功能。

反射Reflection

把java类中的各种结构(方法、属性、构造器、类名)映射成一个个Java对象。利用反射技术可以 对一个类进行解剖,反射是框架设计的灵魂。

三种方式获取Class对象:

  1. 对象.getClass()

  2. 类.class

  3. Class.forName(“包名.类名")(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.lang.reflect.InvocationTargetException;

/**
* 〈一句话功能简述〉<br>
* 反射:把Java类中的各种结构(方法、属性、构造器、类名)映射成一个个对象
* 1.获取Class对象
* 三种方式:Class.forName(“完整路径")
* 2.可以动态创建对象
* clz.getConstructor().newInstance()
*
* @author zephon
* @create 19-2-12
* @since 1.0.0
*/
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//三种方式
//1.对象.getClass()
Class clz = new Iphon().getClass();
//2.类.class
clz = Iphon.class;
//3.Class.forName("包名.类名")
clz = Class.forName("com.zephon.webserver.webserver.Iphon");

//创建对象
Iphon iphon = (Iphon)clz.getConstructor().newInstance();
System.out.println(iphon);
}
}

class Iphon{
public Iphon(){}
}

XML解析

XML:Extensible Markup Language,可扩展标记语言,作为数据的一种存储格式用于存储软件的参数,程序解析此配置文件,就可以到达不修改代码就能更改程序的目的。

解析XML:采用SAX解析

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person>
<name>至尊宝</name>
<age>9000</age>
</person>
<person>
<name>紫霞仙子</name>
<age>8999</age>
</person>
</persons>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Person {
private String name;
private int age;


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* 〈一句话功能简述〉<br>
* 〈SAX解析〉
*
* @author zephon
* @create 19-2-18
* @since 1.0.0
*/
public class XMLTest01 {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//SAX解析
//1.获取解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2.从解析工厂获取解析器
SAXParser parse = factory.newSAXParser();
//3.加载文档Document注册处理器
//4.编写处理器
PHandler handler = new PHandler();
parse.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("com/zephon/webserver/webserver/p.xml"),handler);
List<Person> l = handler.getPersons();
for(Person p:l)
System.out.println(p.getName()+"--"+p.getAge());
}
}
class PHandler extends DefaultHandler {
private List<Person> persons;
private Person person;
private String tag;

//开始解析文档
@Override
public void startDocument() throws SAXException {
persons = new ArrayList();
}

//开始解析元素 qName-->元素名
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName!=null)
tag = qName;
if(qName.equals("person"))
person = new Person();
}
//内容
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String str = new String(ch,start,length);
if(str.length()>0 && tag!=null){
if(tag.equals("name"))
person.setName(str);
else if(tag.equals("age"))
person.setAge(Integer.valueOf(str));
}
}

//解析元素结束
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(qName.equals("person"))
persons.add(person);
tag = null;
}

//解析文档结束
@Override
public void endDocument() throws SAXException {
super.endDocument();
}

public List getPersons() {
return persons;
}
}

SAX在Serverlet中的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.zephon.webserver.servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>reg</servlet-name>
<servlet-class>com.zephon.webserver.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/g</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>reg</servlet-name>
<url-pattern>/reg</url-pattern>
</servlet-mapping>
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Entity {
private String name;
private String clz;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getClz() {
return clz;
}

public void setClz(String clz) {
this.clz = clz;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Mapping {
private String name;
private Set<String> patterns;
Mapping(){
patterns = new HashSet<>();
}
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<String> getPatterns() {
return patterns;
}

public void setPatterns(Set<String> patterns) {
this.patterns = patterns;
}
public void addPattern(String pattern){
this.patterns.add(pattern);
}
}

1
2
3
4
//接口
public interface Servlet {
void service();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class LoginServlet implements Servlet {
@Override
public void service() {
System.out.println("LoginServlet");
}
}
public class RegisterServlet implements Servlet {

@Override
public void service() {
System.out.println("RegisterServlet");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class WebContext {
private List<Entity> entities = null;
private List<Mapping> mappings = null;

//key-->servlet-name value-->servlet-class
private Map<String,String> entityMap = new HashMap<>();
//key-->url-pattern value-->servlet-name
private Map<String,String> mappingMap = new HashMap<>();

public WebContext(List<Entity> entities, List<Mapping> mappings) {
this.entities = entities;
this.mappings = mappings;

//将entity的List转成对应的map
for(Entity e:entities){
entityMap.put(e.getName(),e.getClz());
}
//将map的List转成对应的map
for(Mapping m:mappings){
for(String p:m.getPatterns()){
mappingMap.put(p,m.getName());
}
}
}

public String getClz(String pattern){
String name = mappingMap.get(pattern);
return entityMap.get(name);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class XMLTest01 {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//SAX解析
//1.获取解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2.从解析工厂获取解析器
SAXParser parse = factory.newSAXParser();
//3.加载文档Document注册处理器
//4.编写处理器
WebHandler handler = new WebHandler();
parse.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("com/zephon/webserver/servlet/web.xml"),handler);

//获取数据
WebContext context = new WebContext(handler.getEntities(),handler.getMappings());
//假设输入了/login
String name = context.getClz("/reg");
Class clz = Class.forName(name);
Servlet servlet = (Servlet) clz.getConstructor().newInstance();
servlet.service();


}
}

class WebHandler extends DefaultHandler {
private List<Entity> entities;
private List<Mapping> mappings;
private Entity entity;
private Mapping mapping;
private String tag;
private boolean isMapping;

//开始解析文档
@Override
public void startDocument() throws SAXException {
entities = new ArrayList<>();
mappings = new ArrayList<>();
}

//开始解析元素 qName-->元素名
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName!=null)
tag = qName;
if(qName.equals("servlet")) {
entity = new Entity();
isMapping = false;
}
else if(qName.equals("servlet-mapping")) {
mapping = new Mapping();
isMapping = true;
}

}
//内容
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String str = new String(ch,start,length);
if(str.length()>0 && tag!=null){
if(isMapping){
if(tag.equals("servlet-name"))
mapping.setName(str);
else if(tag.equals("url-pattern"))
mapping.addPattern(str);
}else{
if(tag.equals("servlet-name"))
entity.setName(str);
else if(tag.equals("servlet-class"))
entity.setClz(str);
}

}
}

//解析元素结束
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(qName.equals("servlet"))
entities.add(entity);
else if(qName.equals("servlet-mapping"))
mappings.add(mapping);
tag = null;
}

//解析文档结束
@Override
public void endDocument() throws SAXException {
super.endDocument();
}

public List<Entity> getEntities() {
return entities;
}

public List<Mapping> getMappings() {
return mappings;
}
}

HTTP协议

基础

超文本传输协议(HTTP,Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。

请求协议:

  1. 请求行:方法(GET/POST)、URI、协议/版本
  2. 请求头:(Request Header)
  3. 请求正文:

响应协议:

  1. 状态行:协议/版本 状态码 状态描述
  2. 响应头(Response Header)
  3. 响应正文:

典型GET的请求协议:

1、请求行

GET /index.html?name=test&pwd=123456 HTTP/1.1

2、请求体

Accept:text/html,application/xhtml+xml,* / *

Accept-Language:zh-CN

User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36

Accept-Encoding:gzip,deflate

Host:localhost

Connection:Keep-Alive

3、请求正文

典型POST的请求协议:

1、请求行

POST /index.html HTTP/1.1

2、请求体

Accept:text/html,application/xhtml+xml,* / * Accept-Language:zh-CN

User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36

Host:localhost

Connection:Keep-Alive

3、请求正文

name=test&pwd=123456

典型的响应协议:

1、状态行:HTTP/1.0 200 OK

2、请求头:

Date:Tue Feb 19 15:18:50 CST 2019

Server:zephon Server/0.0.1;charset=GBK

Content-type:text/html

Content-length:384

3、请求正文(注意与请求头之间有个空行)

xxxxxxxx

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form method="post" action="http://localhost:8888/index.html">
用户名:<input type="text" name="uname" id="uname"/>
密码:<input type="password" name="pwd" id="pwd"/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 〈一句话功能简述〉<br>
* 〈使用ServerSocket建立与浏览器的连接,获取请求协议〉
*
* @author zephon
* @create 19-2-18
* @since 1.0.0
*/
public class Server01 {
private ServerSocket serverSocket;
public static void main(String[] args){
Server01 server = new Server01();
server.start();
}
//启动服务
public void start(){
try {
serverSocket = new ServerSocket(8888);
receive();
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器启动失败");
}
}
//接受连接处理
public void receive(){
try {
Socket client = serverSocket.accept();
System.out.println("一个客户端建立成功");
//获取请求协议
InputStream is = client.getInputStream();
byte[] datas = new byte[1024*1024];
int len = is.read(datas);
String requestInfo = new String(datas,0,len);
System.out.println(requestInfo);
} catch (IOException e) {
e.printStackTrace();
System.out.println("客户端错误");
}
}
//停止服务
public void stop(){

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* 〈一句话功能简述〉<br>
* 〈返回相应协议〉
* 1.准备内容
* 2.获取字节数的长度
* 3.拼接响应协议(注意空格与换行)
* 4.使用输出流输出
*
* @author zephon
* @create 19-2-18
* @since 1.0.0
*/
public class Server02 {
private ServerSocket serverSocket;
public static void main(String[] args){
Server02 server = new Server02();
server.start();
}
//启动服务
public void start(){
try {
serverSocket = new ServerSocket(8888);
receive();
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器启动失败");
}
}
//接受连接处理
public void receive(){
try {
Socket client = serverSocket.accept();
System.out.println("一个客户端建立成功");
//获取请求协议
InputStream is = client.getInputStream();
byte[] datas = new byte[1024*1024];
int len = is.read(datas);
String requestInfo = new String(datas,0,len);
System.out.println(requestInfo);

StringBuilder content = new StringBuilder();
content.append("<html>");
content.append("<head>");
content.append("<title>");
content.append("服务器响应成功");
content.append("</title>");
content.append("</head>");
content.append("<body>");
content.append("终于回来了...");
content.append("</body>");
content.append("</html>");
//字节数
int size = content.toString().getBytes().length;
StringBuilder responseInfo = new StringBuilder();
String blank = " ";
String CRLF = "\r\n";
//返回
//1.响应状态行:HTTP/1.1 200 OK
responseInfo.append("HTTP/1.1").append(blank);
responseInfo.append("200").append(blank);
responseInfo.append("OK").append(CRLF);
//2.响应头(最后一行存在空行):
/*
Date: Tue Feb 19 15:18:50 CST 2019
Server: zephon Server/0.0.1;charset=GBK
Content-type: text/html
Content-length: 93
*/
responseInfo.append("Date:").append(new Date()).append(CRLF);
responseInfo.append("Server:").append("zephon Server/0.0.1;charset=GBK").append(CRLF);
responseInfo.append("Content-type:text/html").append(CRLF);
responseInfo.append("Content-length:").append(size).append(CRLF);
responseInfo.append(CRLF);
//3.正文:
responseInfo.append(content.toString());

//写出到客户端
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
bw.write(responseInfo.toString());
bw.flush();

} catch (IOException e) {
e.printStackTrace();
System.out.println("客户端错误");
}
}
//停止服务
public void stop(){

}

}

Response封装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

/**
* 〈一句话功能简述〉<br>
* 〈封装响应信息〉
* 1.内容可以动态添加
* 2.关注状态码,拼接好响应的协议信息
*
* @author zephon
* @create 19-2-19
* @since 1.0.0
*/
public class Response {
private BufferedWriter bw;
//正文
private StringBuilder content;
//协议头(状态行与请求头 回车)信息
private StringBuilder headInfo;
private int len;//正文的字节数
private final String BLANK = " ";
private final String CRLF = "\r\n";

private Response(){
content = new StringBuilder();
headInfo = new StringBuilder();
len = 0;
}
public Response(Socket client){
this();
try {
bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public Response(OutputStream os){
this();
bw = new BufferedWriter(new OutputStreamWriter(os));
}

/**
* @Description: 动态添加内容(流模式)
* @Param:info信息
* @return:
* @Author: Zephon
* @Date:
*/
public Response print(String info){
content.append(info);
len+=info.getBytes().length;
return this;
}

public Response println(String info){
content.append(info).append(CRLF);
len+=(info+CRLF).getBytes().length;
return this;
}
/**
* @Description: 推送响应信息
* @Param:
* @return:
* @Author: Zephon
* @Date:
*/
public void pushToBrowser(int code) throws IOException {
if(null==headInfo){
code=505;
}
createHeadInfo(code);
bw.append(headInfo);
bw.append(content);
bw.flush();
}
/**
* @Description: 构建头信息
* @Param: code-状态码
* @return:
* @Author: Zephon
* @Date:
*/
private void createHeadInfo(int code){
//1.响应状态行:HTTP/1.1 200 OK
headInfo.append("HTTP/1.1").append(BLANK);
headInfo.append(code).append(BLANK);
switch (code){
case 200:
headInfo.append("OK").append(CRLF);
break;
case 404:
headInfo.append("NOT FOUND").append(CRLF);
break;
case 505:
headInfo.append("SERVER ERROR").append(CRLF);
break;
}
//2.响应头(最后一行存在空行):
/*
Date: Tue Feb 19 15:18:50 CST 2019
Server: zephon Server/0.0.1;charset=GBK
Content-type: text/html
Content-length: 93
*/
headInfo.append("Date:").append(new Date()).append(CRLF);
headInfo.append("Server:").append("zephon Server/0.0.1;charset=GBK").append(CRLF);
headInfo.append("Content-type:text/html").append(CRLF);
headInfo.append("Content-length:").append(len).append(CRLF);
headInfo.append(CRLF);

}
}

封装Request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* 〈一句话功能简述〉<br>
* 〈封装请求协议:封装请求参数为Map〉
*
* @author zephon
* @create 19-2-19
* @since 1.0.0
*/
public class Request2 {
//协议信息
private String requestInfo;
//请求方式
private String method;
//请求url
private String url;
//请求参数
private String queryStr;
//存储参数
private Map<String, List<String>> parameterMap;

private final String CRLF = "\r\n";


public Request2(Socket client) throws IOException {
this(client.getInputStream());
}

public Request2(InputStream is){
parameterMap = new HashMap<>();
byte[] datas = new byte[1024*1024];
int len = 0;
try {
len = is.read(datas);
this.requestInfo = new String(datas,0,len);
} catch (IOException e) {
e.printStackTrace();
return;
}
//分解字符串
parseRequestInfo();
}

//分解字符串
private void parseRequestInfo(){
System.out.println("---分解---");
//1.获取请求方式:开头到第一个/
this.method = this.requestInfo.substring(0,this.requestInfo.indexOf("/")).toLowerCase();
this.method.trim();
//2.获取请求的url:第一个/到HTTP/(可能包含请求参数?前面的为url)
//1)获取/的位置
int idx1 = this.requestInfo.indexOf("/")+1;
//2)获取HTTP/的位置
int endIdx = this.requestInfo.indexOf("HTTP/");
//3)分割字符串
this.url = this.requestInfo.substring(idx1,endIdx);
//4)获取?的位置
int queryIdx = this.url.indexOf("?");
if(queryIdx>=0){//表示存在请求参数
String[] urlArray = this.url.split("\\?");
this.url = urlArray[0];
queryStr = urlArray[1];
}
System.out.println(url);
//3.获取请求参数:如果Get已经获取,如果是Post可能在请求体中
if(method.trim().equals("post")){
String qStr = this.requestInfo.substring(this.requestInfo.lastIndexOf(CRLF)).trim();
if(null==queryStr){
queryStr = qStr;
}else{
queryStr +="&"+qStr;
}
}
queryStr=null==queryStr?"":queryStr;
System.out.println(method+"-->"+url+"-->"+queryStr);
//转成Map fav=1&fav=2&uname=zephon&age=18&others=
convertMap();
}

/**
* @Description: 处理请求参数为Map
* @Param:
* @return:
* @Author: Zephon
* @Date:
*/
private void convertMap(){
//分割字符串 &
String[] keyValues = this.queryStr.split("&");
for(String queryStr:keyValues){
//再次分割字符串 =
String[] kv = queryStr.split("=");
kv = Arrays.copyOf(kv,2);
//获取key和value
String key = kv[0];
String value = kv[1]==null?null:decode(kv[1],"utf-8");
//存储到map中
if(!parameterMap.containsKey(key)){
parameterMap.put(key,new ArrayList<String>());
}
parameterMap.get(key).add(value);
}
}

/**
* @Description: 处理中文
* @Param:
* @return:
* @Author: Zephon
* @Date:
*/
private String decode(String value,String enc){
try {
return java.net.URLDecoder.decode(value,enc);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}

/**
* @Description: 通过name获取对应的多个值
* @Param:
* @return:
* @Author: Zephon
* @Date:
*/
public String[] getParameterValues(String key){
List<String> values = this.parameterMap.get(key);
if(null==values||values.size()<1){
return null;
}
return values.toArray(new String[0]);
}

/**
* @Description: 通过name获取对应的一个值
* @Param:
* @return:
* @Author: Zephon
* @Date:
*/
public String getParameter(String key){
String[] values = getParameterValues(key);
return values==null?null:values[0];
}

public String getMethod() {
return method;
}

public String getUrl() {
return url;
}

public String getQueryStr() {
return queryStr;
}
}

封装Servlet:

1
2
3
4
5
6
7
8
9
10
11
/**
* 〈一句话功能简述〉<br>
* 〈服务器小脚本接口〉
*
* @author zephon
* @create 19-2-21
* @since 1.0.0
*/
public interface Servlet {
void service(Request request,Response response);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 〈一句话功能简述〉<br>
* 〈实现Servlet〉
*
* @author zephon
* @create 19-2-18
* @since 1.0.0
*/
public class LoginServlet implements Servlet {
@Override
public void service(Request request, Response response) {
response.print("<html>");
response.print("<head>");
response.print("<title>");
response.print("第一个Servlet");
response.print("</title>");
response.print("</head>");
response.print("<body>");
response.print("欢迎回来..."+request.getParameter("uname"));
response.print("</body>");
response.print("</html>");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Server06 {
private ServerSocket serverSocket;
public static void main(String[] args){
Server06 server = new Server06();
server.start();
}
//启动服务
public void start(){
try {
serverSocket = new ServerSocket(8888);
receive();
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器启动失败");
}
}
//接受连接处理
public void receive(){
try {
Socket client = serverSocket.accept();
System.out.println("一个客户端建立成功");
//获取请求协议
Request request = new Request(client);

Response response = new Response(client);
Servlet servlet = null;
if(request.getUrl().equals("login")){
servlet = new LoginServlet();
}else{
//首页。。。
}
servlet.service(request,response);
//关注状态码
response.pushToBrowser(200);

} catch (IOException e) {
e.printStackTrace();
System.out.println("客户端错误");
}
}
//停止服务
public void stop(){

}

}

多线程处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

import java.io.IOException;
import java.net.Socket;

/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author zephon
* @create 19-2-21
* @since 1.0.0
*/
public class Dispatcher implements Runnable {
private Socket client;
private Request request;
private Response response;
public Dispatcher(Socket client){
this.client = client;
try {
request = new Request(client);
response = new Response(client);
} catch (IOException e) {
e.printStackTrace();
this.release();
}
}

@Override
public void run() {
try {
Servlet servlet = WebApp.getServletFromUrl(request.getUrl());
if (null != servlet) {
servlet.service(request, response);
response.pushToBrowser(200);
} else {
response.pushToBrowser(404);
}
}catch (Exception e){
try {
response.pushToBrowser(500);
} catch (IOException e1) {
e1.printStackTrace();
}
}
release();
}
//释放资源
private void release(){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 〈一句话功能简述〉<br>
* 〈整合配置文件,〉
*
* @author zephon
* @create 19-2-21
* @since 1.0.0
*/
public class Server07 {
private ServerSocket serverSocket;
private boolean isRunning;
public static void main(String[] args){
Server07 server = new Server07();
server.start();
}
//启动服务
public void start(){
try {
isRunning = true;
serverSocket = new ServerSocket(8888);
receive();
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器启动失败");
stop();
}
}
//接受连接处理
public void receive(){
while (isRunning) {
try{
Socket client = serverSocket.accept();
System.out.println("一个客户端建立成功");
//多线程处理
new Thread(new Dispatcher(client)).start();
} catch(IOException e){
e.printStackTrace();
System.out.println("客户端错误");
}
}
}
//停止服务
public void stop(){
isRunning = false;
try {
this.serverSocket.close();
System.out.println("服务器已停止");
} catch (IOException e) {
e.printStackTrace();
}
}

}