简单实现 http Server (版本1、2),Java知识总结

把代码改一下:让不同的需求,来看到不同的响应

修改部分代码:

String resp = null;

if(url.equals(“/OK”)){

bufferedWriter.write(version + “200 OK\n”);

resp = “

hello

”;

}

else if(url.equals(“/notfound”)){

bufferedWriter.write(version + “404 Not Found\n”);

resp = “

not found

”;

}

// 重定向情况

else if(url.equals(“/seeother”)){

bufferedWriter.write(version + " 303 See Other\n");

bufferedWriter.write(“Location: http://www.sogou.com\n”);

resp = “”;

}

else{

bufferedWriter.write(version + “200 OK\n”);

resp = “

default

”;

}

运行程序,连接服务器:

在这里插入图片描述

default:

在这里插入图片描述

重定向:

在这里插入图片描述

版本2

1.整理代码格式,让代码更规范

2.解析 URL 中包含的参数(键值对),能够方便的处理用户传过来的参数

3.演示 Cookie 的工作流程

request 类:

/*

  • 专门表示 Http 请求

  • 表示一个 http 请求,并解析

  • */

public class HttpRequest {

private String method;

private String url;

private String version;

private Map<String,String> headers = new HashMap<>();

// 表示 url中的参数

private Map<String,String> parameters = new HashMap<>();

// 请求的构造逻辑,仍使用工厂模式来构造

// 此处的参数就是从 socket 中获取到的 InputStream 对象

// 这个过程本质上是在 “反序列化” 把一个比特流,转换成一个结构化数据

public static HttpRequest build(InputStream inputStream) throws IOException {

HttpRequest request = new HttpRequest();

// 此处的逻辑,不能把 bufferedReader 写入到 try() 中

// 一旦写进去之后就意味着 bufferedReader就会被关闭,会影响到 clientSocket 的状态

// 等到最后整个请求处理完了, 再统一关闭

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

// 此处的 build 的过程就是解析请求的过程

//1.解析首行

String firstLine = bufferedReader.readLine();

String[] firstLineTokens = firstLine.split(" ");

request.method = firstLineTokens[0];

request.url = firstLineTokens[1];

request.version = firstLineTokens[2];

//2.解析 url 中的参数

int pos = request.url.indexOf(“?”);

if(pos != -1){

// 检查url中是否有 ? ,若没有,说明不带参数,就不需要解析了

// pos 表示 ? 的下标 /index.html?a=10&bb=20

// parameters 的结果就相当于是 a=10&bb=20

String parameters = request.url.substring(pos + 1);

// 切分的最终结果,key-a,value-10 ; key-b,value-20

parseKV(parameters,request.parameters);

}

//3.解析header

String line = “”;

while ((line = bufferedReader.readLine()) != null && line.length() != 0){

String[] headerTokens = line.split(": ");

request.headers.put(headerTokens[0],headerTokens[1]);

}

//4.解析 body(暂时不考虑)

return request;

}

private static void parseKV(String input, Map<String, String> output) {

// 1.先按照 & 切分成若干组键值对

String[] kvTokens = input.split(“&”);

// 2.针对切分结果,再分别进行 按照 = 切分,得到键和值

for (String kv : kvTokens) {

String[] result = kv.split(“=”);

output.put(result[0],result[1]);

}

}

// 给这个类构造一些 getter方法 (不要搞 setter 方法)

// 请求对象的内容应该从网络上解析来的,用户不应该修改

public String getMethod() {

return method;

}

public String getUrl() {

return url;

}

public String getVersion() {

return version;

}

public String getHeader(String key) {

return headers.get(key);

}

public String getParameter(String key) {

return parameters.get(key);

}

@Override

public String toString() {

return “HttpRequest{” +

“method='” + method + ‘’’ +

“, url='” + url + ‘’’ +

“, version='” + version + ‘’’ +

“, headers=” + headers +

“, parameters=” + parameters +

‘}’;

}

}

response 类:

/*

  • 专门表示 Http 响应

  • 表示一个 http 响应,负责构造

  • */

public class HttpResponse {

private String version = “HTTP/1.1”;

private int status; // 状态码

private String message; // 状态码描述性信息

private Map<String,String> headers = new HashMap<>();

// 使用StringBuilder 方便进行拼接

private StringBuilder body = new StringBuilder();

// 写回给客户端时需要用到

// 代码把响应写回到客户端时,就往 outputStream 中写

private OutputStream outputStream = null;

public static HttpResponse build(OutputStream outputStream){

HttpResponse response = new HttpResponse();

response.outputStream = outputStream;

// 除了outputStream外,其他的属性内容,暂时无法确定,要根据代码的具体逻辑,来决定

return response;

}

// 提供一些 setter 方法

public void setVersion(String version) {

this.version = version;

}

public void setStatus(int status) {

this.status = status;

}

public void setMessage(String message) {

this.message = message;

}

public void setHeader(String key,String value) {

headers.put(key,value);

}

public void writeBody(String content) {

body.append(content);

}

// 以上设置属性操作,都是在内存中

// 还需要一个专门de方法,把这些属性,按照 Http 协议写到socket中

public void flush() throws IOException {

BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));

// 构造首行

bufferedWriter.write(version + " " + status + " " + message + “\n”);

headers.put(“Content-Length”,body.toString().getBytes().length +“”);

for (Map.Entry<String,String> entry : headers.entrySet()){

bufferedWriter.write(entry.getKey() + ": " + entry.getValue() + “\n”);

}

bufferedWriter.write(“\n”);

bufferedWriter.write(body.toString());

bufferedWriter.flush();

}

}

主类:

public class HttpServerV2 {

private ServerSocket serverSocket = null;

public HttpServerV2(int port) throws IOException {

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

一直到现在。**

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-eS0110OM-1710935129486)]
[外链图片转存中…(img-AS6sJ02F-1710935129487)]
[外链图片转存中…(img-306wdHqe-1710935129488)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-NzT1P1xK-1710935129488)]

  • 29
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值