实现一个简单的 HTTP,京东 java 面试问题大全及答案大全
String newUrl = url.substring(url.indexOf("?") + 1);
//然后将新的 newUrl 用“&”进行分隔变成 key=value 的形式
String[] newUrlArr = newUrl.split("&");
//遍历这个新的 newUrl
for (String kvs : newUrlArr) {
//然后 newUrl 里面的每一个 key=value 用“=”进行分隔
String[] item = kvs.split("=");
//然后放进 map 里面也就是 parents 里面
parments.put(item[0], item[1]);
}
}
}
//如果外部类要去使用的话,我们必须提供 get 方法
public String getMethod() {
return method;
}
public String getUrl() {
return url;
}
public String getVersion() {
return version;
}
//然后手动实现两个 map 的 get 方法
public String getParents(String key){
return this.parments.get(key);
}
public String getRequestHeader(String key){
return this.requsetHeader.get(key);
}
}
[](
)Response
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
输出信息
*/
public class myHttpResponse {
//1.首行信息【http 版本号+状态码+状态描述符】
//版本号,因为版本号是固定的,不可修改的,那么我们可以设置成静态变量,并且用 final 修饰,然后返回的是 HTTP/1.1
private static final String version = "HTTP/1.1";
//状态码
private Integer state;
//状态描述符
private String stateMessage;
//2.header(响应报文头)其中(Content—Type 和 Content—Length)很重要,而且它是以 key: value 的形式存储的
Map<String,String> responseHeader = new HashMap<>();
//3.空行
//4.body
//这个是服务器自定义返回的一个信息,因为 String 的性能很低,而且会产生很多的垃圾,所以我们使用 StringBuffer
StringBuffer responseBody = new StringBuffer();
//这里要严格遵循 HTTP 协议的格式输出
public void flush(PrintWriter writer){
//1.先输出首行,注意:按照空格进行分隔
writer.println(String.format("%s %d %s",version,this.state,this.stateMessage));
//2.写入 header 内容(Content—Type(会自己进行设置)和 Content—Length(不会进行设置,所以要自己写))
for (Map.Entry<String,String> item:responseHeader.entrySet()){
//key Value,拼接输出时要以“: ”(冒号+空格)进行分隔输出
writer.println(String.format("%s: %s",item.getKey(),item.getValue()));
}
//添加一个 Content—Length
writer.println("Content—Length: "+responseBody.toString().getBytes().length);
//输出空行
writer.println();
//输出 body
writer.println(responseBody.toString());
}
//因为它是需要写入的,所以需要提供 set 方法,需要手动添加一个 header 方法
public void setState(Integer state) {
this.state = state;
}
public void setStateMessage(String stateMessage) {
this.stateMessage = stateMessage;
}
//每次可能就只写入一段内容那么就每次把 body 内容加进去
public void setResponseBody(String body) {
this.responseBody.append(body);
}
//需要设置两个值,一个 key,一个 value,然后把这个 key 和 value 放入 responseHeader 中
public void setResponseHeader(String key,String value){
this.responseHeader.put(key,value);
}
}
Server(服务器端)
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyHttpServer2 {
private ServerSocket serverSocket = null;
public MyHttpServer2(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void start() throws IOException {
System.out.println("服务器正常启动了~");
//为了让一个服务器响应多个客户端,所以我们使用线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,15,100,TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10));
while(true){
//首先等待客户端连接,此处的客户端就是浏览器
Socket clientSocket = serverSocket.accept();
threadPoolExecutor.submit(()->{
//然后处理接收到的消息
try {
procescsSocket(clientSocket);
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
private void procescsSocket(Socket clientSocket) throws IOException {
//从 Socket 中拿到两个对象,一个是 Reader 读取对象,一个是响应对象 Writer
try(
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()))
) {
//然后我们
就可以用我们刚刚声明的方法进行封装
myHttpRequest request = new myHttpRequest();
//然后给他的值设置内容,然后这里实现了代码的复用,就不用每次写获取响应的代码了
request.init(bufferedReader);
//打印首行信息
System.out.println(String.format("首行信息: %s %s %s",request.getMethod(),request.getUrl(),request.getVersion()));
//业务处理,不同的访问地址(url)返回不同的页面
myHttpResponse response = new myHttpResponse();
//响应的页面类型为 html
response.setResponseHeader("Content-Type","text/html; charset=utf-8");
//if(requesr.getUrl.indexOf("/404") != -1)等同于 if(request.getUrl().startsWith("/404"))
if(request.getUrl().startsWith("/404")){
//然后 404 页面
response.setState(404);
response.setStateMessage("not found");
//如果是 404body 可以为空
}else if(request.getUrl().startsWith("/302")){
//跳转到指定的页面,如跳转到百度,如果是跳转,一定要设置一个 header Location-> https://www.baidu.com;
response.setState(302);
response.setResponseHeader("Location","https://www.baidu.com");
response.setStateMessage("Location");
//此时跳转到另一个页面了,所以 body 也可以为空
}else {
//正常返回页面
response.setState(200);
response.setStateMessage("OK");
//此时正常返回页面,那么显示一个 body 内容,此时因为有中文,所以一定要注意设置编码格式
评论