开发HTTP服务器 简易版

子曰:“弟子,入则孝,出则弟,谨而信,凡爱众,而亲仁。行有余力,则以学文。”

为了更好的理解netty框架,所以就自己写了一个http服务器(少了一个session)

开发HTTP服务器 简易版_第1张图片

1 Http解码器和编码器

1 .1 http解码器接口
import java.io.BufferedReader;
import java.io.IOException;

public interface HttpDecode {

    String decode(BufferedReader reader) throws IOException, Exception;
}
1.2 http编码器接口
import java.io.IOException;
import java.io.OutputStream;

public interface HttpEncode {

    String encode(OutputStream out) throws IOException;
}

2 实现Http请求和响应 (request和response)

2.1 实现HttpRequest
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest {

    private String requestLine;
    private RequestHeader header;
    private Map keyValue;
    private String body;
    
    public static final String GET = "GET";
    public static final String POST = "POST";
    //静态文件
    private String resources;
    
    public String getUri(){
        String uris = requestLine.split(" ")[1];
        if(uris.indexOf("?") != -1){
            return uris.split("\\?")[0];
        }else{
            return uris;
        }
    }
    
    /**
     * 获取参数
     * @return
     */
    public String getParameter(String key) {
        try {
            if(keyValue.get(key) != null && !keyValue.get(key).equals("")){
                return URLDecoder.decode(keyValue.get(key),"UTF-8");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }
    
    /**
     * 初始化map
     * @return
     */
    public Map initMap(){
        keyValue = new HashMap();
        return keyValue;
    }
    public void removeMap(){
        keyValue = null;
    }
    
    public String getRequestLine() {
        return requestLine;
    }
    public void setRequestLine(String requestLine) {
        this.requestLine = requestLine;
    }
    public RequestHeader getHeader() {
        return header;
    }
    public void setHeader(RequestHeader header) {
        this.header = header;
    }
    public String getResources() {
        return resources;
    }
    public void setResources(String resources) {
        this.resources = resources;
    }
    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
}
2.2实现HttpResponse
public class HttpResponse {

    private String write;

    public String getWrite() {
        return write;
    }

    public void setWrite(String write) {
        this.write = write;
    }
}

3 解析请求和响应

3.1 解析请求HttpRequestDecoder
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;

public class HttpRequestDecoder implements HttpDecode {

    @Override
    public String decode(BufferedReader reader) throws IOException, Exception{
        if(reader != null){
            HttpRequest request = Server.request;
            request.setRequestLine(reader.readLine());
            Class clazz = Class.forName("com.wpixel.http.RequestHeader");
            Object requestHeader = clazz.newInstance();
            String str = "";
            while((str = reader.readLine().trim()) != null && !str.trim().equals("")){
                String[] split = str.split(": ");
                String key = "set"+split[0].replaceAll("-", "");
                Method method = clazz.getMethod(key, String.class);
                method.invoke(requestHeader, split[1]);
            }
            Method method = clazz.getMethod("getContentLength");
            String len = (String)method.invoke(requestHeader);
            String body = "";
            int g = 1;
            if(len != null){
                for (int i = 0; i < Integer.valueOf(len); i++) {
                    body += (char) reader.read();
                }
            }
            request.setBody(body.toString());
            Server.request.setHeader((RequestHeader)requestHeader);
        }
        return null;
    }
    
}
3.2响应编码HttpResponseEncoder
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

public class HttpResponseEncoder implements HttpEncode {

    @Override
    public String encode(OutputStream out) throws IOException{
        out.write("HTTP/1.1 200 OK\r\n".getBytes());
        out.write("Content-Type: text/html;charset=utf-8\r\n".getBytes());
        out.write("Connection: Keep-Alive\r\n".getBytes());
        out.write("\r\n".getBytes());
        
        File file = new File(Server.response.getWrite());
        InputStream in = new FileInputStream(file);
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        byte[] buffer = new byte[(int)(file.length())];
        int len = 0;
        while ((len = in.read(buffer)) != -1) {
            byteOut.write(buffer, 0, len);
        }
        
        out.write(buffer);
        
        return null;
    }
}

4 定义一个http请求头demo类

public class RequestHeader {
    
    private String host;
    private String connection;
    private String contentLength;
    private String cacheControl;
    private String accept;
    private String origin;
    private String upgradeInsecureRequests;
    private String userAgent;
    private String contentType;
    private String referer;
    private String acceptEncoding;
    private String acceptLanguage;
    private String pragma;
    
    public String getContentLength() {
        return contentLength;
    }
    public void setContentLength(String contentLength) {
        this.contentLength = contentLength;
    }
    public String getOrigin() {
        return origin;
    }
    public void setOrigin(String origin) {
        this.origin = origin;
    }
    public String getContentType() {
        return contentType;
    }
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }
    public String getReferer() {
        return referer;
    }
    public void setReferer(String referer) {
        this.referer = referer;
    }
    public String getHost() {
        return host;
    }
    public void setHost(String host) {
        this.host = host;
    }
    public String getConnection() {
        return connection;
    }
    public void setConnection(String connection) {
        this.connection = connection;
    }
    public String getCacheControl() {
        return cacheControl;
    }
    public void setCacheControl(String cacheControl) {
        this.cacheControl = cacheControl;
    }
    public String getAccept() {
        return accept;
    }
    public void setAccept(String accept) {
        this.accept = accept;
    }
    public String getUpgradeInsecureRequests() {
        return upgradeInsecureRequests;
    }
    public void setUpgradeInsecureRequests(String upgradeInsecureRequests) {
        this.upgradeInsecureRequests = upgradeInsecureRequests;
    }
    public String getUserAgent() {
        return userAgent;
    }
    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }
    public String getAcceptEncoding() {
        return acceptEncoding;
    }
    public void setAcceptEncoding(String acceptEncoding) {
        this.acceptEncoding = acceptEncoding;
    }
    public String getAcceptLanguage() {
        return acceptLanguage;
    }
    public void setAcceptLanguage(String acceptLanguage) {
        this.acceptLanguage = acceptLanguage;
    }
    public String getPragma() {
        return pragma;
    }
    public void setPragma(String pragma) {
        this.pragma = pragma;
    }
}

5 定义一个数据传输通道

public class InitChannel {

    static SocketChannel channel = null;
    
    public InitChannel() {
        
    }
    
    protected void initSocketChannel(SocketChannel channel) throws Exception {
        
    }
}

6 定义通道接口

public interface HttpSimpleHeader {

    public void httpWrite() throws Exception;
}

7 整合http请求的业务处理 (get和post)

import java.util.Map;

public class SendAndRev implements HttpSimpleHeader {
    
    @Override
    public void httpWrite() throws Exception {
        //初始化参数
        Map initMap = Server.request.initMap();
        String method = Server.request.getRequestLine().split(" ")[0];
        if(method.equals(HttpRequest.GET)){
            String path = Server.request.getRequestLine().split(" ")[1];
            String[] split = path.split("\\?");
            if(split.length > 1){
                String parameter = split[1];
                String[] parameters = parameter.split("\\&");
                if(parameters.length != 0){
                    for (String string : parameters) {
                        if(string.split("=").length > 1){
                            initMap.put(string.split("\\=")[0], string.split("\\=")[1]);
                        }
                    }
                }
            }
            Servlet.doGet(Server.request, Server.response);
        }else if(method.equals(HttpRequest.POST)){
            String body = Server.request.getBody();
            String[] parameters = body.split("\\&");
            if(parameters.length != 0){
                for (String string : parameters) {
                    if(string.split("=").length > 1){
                        initMap.put(string.split("\\=")[0], string.split("\\=")[1]);
                    }
                }
            }
            Servlet.doPost(Server.request, Server.response);
        }
    }
}

8 定义TCP连接

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServerBootstrap {

    ServerSocket server = null;
    InitChannel initChannel = null;
    //使用线程池
    ExecutorService threadPool = null;
    public ServerBootstrap(){
        threadPool = Executors.newFixedThreadPool(4);
    }
     
    public void childHandler(InitChannel initChannel) throws IOException{
        this.initChannel = initChannel;
    }
    public void bind(int port) throws IOException{
        server = new ServerSocket(port);
    }
    
    public void accept() throws Exception{
        while(true){
            Socket socket = server.accept();
            Runnable runnable = () -> {
                InputStream in = null;
                OutputStream out = null;
                try {
                    in = socket.getInputStream();
                    out = socket.getOutputStream();
                    initChannel.initSocketChannel(new SocketChannel(in, out));
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        out.close();
                        in.close();
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName()+"结束");
            };
            threadPool.execute(runnable);
        }
    }
    
}

9 定义TCP通道

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

public class SocketChannel {
    
    private InputStream in;
    private OutputStream out;
    public SocketChannel(InputStream in, OutputStream out){
        this.in = in;
        this.out = out;
    }
    
    //编码器
    public void addEncode(HttpEncode encoder) throws IOException{
        encoder.encode(out);
    }
    
    //解码器
    public void addDecode(HttpDecode decoder) throws Exception{
        decoder.decode(new BufferedReader(new InputStreamReader(in)));
    }
    
    public void addServer(HttpSimpleHeader header) throws Exception{
        header.httpWrite();
    }
}

10 servlet请求入口

import java.io.UnsupportedEncodingException;

public class Servlet {

    public static void doGet(HttpRequest request, HttpResponse response) {
        System.out.println("doGet");
        String name3 = request.getParameter("name3");
        String name4 = request.getParameter("name4");
        System.out.println("name3:"+name3+";name4:"+name4);
        response.setWrite(System.getProperty("user.dir")+request.getUri());
    }
    
    public static void doPost(HttpRequest request, HttpResponse response) throws UnsupportedEncodingException {
        System.out.println("doPost");
        String name1 = request.getParameter("name1");
        String name2 = request.getParameter("name2");
        System.out.println("name1:"+name1+";name2:"+name2);
        response.setWrite(System.getProperty("user.dir")+request.getUri());
    }
}

11 http服务启动类

public class Server {
    
    public static HttpRequest request = null;
    public static HttpResponse response = null;
    public static ServerBootstrap bootstrap = null;
    static{
        request = new HttpRequest();
        response = new HttpResponse();
    }
    
    public static void main(String[] args) {
        System.out.println("启动服务器;端口8080!!!!!");
        try {
            bootstrap = new ServerBootstrap();
            bootstrap.childHandler(new InitChannel(){
                @Override
                protected void initSocketChannel(SocketChannel sc) throws Exception {
                    sc.addDecode(new HttpRequestDecoder());
                    sc.addServer(new SendAndRev());
                    sc.addEncode(new HttpResponseEncoder());
                }
            });
            bootstrap.bind(8080);
            bootstrap.accept();
            
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            
        }
    }
}

12 新建一个网页 index.html



  
    首页
    
    
    
    
    
    
    
  
  
  
    

This is my HTML page.


-----------------静态资源----------------------

-----------------post请求-----------------------

1name:

2name:


-----------------get请求-----------------------

3name:

4name:


总结

开发HTTP服务器 简易版_第2张图片
开发HTTP服务器 简易版_第3张图片

作者是一名自由程序员,住在上海,喜欢音乐、小说、旅行、以及编程。

P.S. 如果您喜欢这篇文章并且希望学习编程技术的话,请关注一下

你可能感兴趣的:(开发HTTP服务器 简易版)