Java项目——简单的WebServer(二)

上一篇说了一些必要的知识,下面就开始写我们的项目

1. ServerMain.java

存放main函数,调用各种方法

package cob.briup.webServer.v2_1.main;

import java.net.ServerSocket;
import java.net.Socket;
import cob.briup.webServer.v2_1.util.ServerInfo;

public class ServerMain {
    public static void main(String[] args) {
        ServerSocket server = null;
        Socket socket = null;
        try {
            // 初始化变量
            //从文件中读入端口号
            server = new ServerSocket(Integer.parseInt(ServerInfo.getInfos("port")));
            System.out.println("服务器启动,等待浏览器连接");
            //while死循环,使服务器一直运行
            while (true) {
                socket = server.accept();
                System.out.println("浏览器连接成功");
                //多线程处理多个浏览器发来的请求
                ServerHandler handler = new ServerHandler(socket);
                //启动多线程
                handler.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.ServerHandler.java

多线程处理多个浏览器发来的请求

package cob.briup.webServer.v2_1.main;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
import cob.briup.webServer.v2_1.util.BeanFactory;
import cob.briup.webServer.v2_1.util.ServerInfo;
import cob.briup.webServer.v2_1.webclass.WebClass;

public class ServerHandler extends Thread {
    private Socket socket;
    //处理浏览器发出的http请求,按行读入
    private BufferedReader in = null;
    private PrintStream out = null;
    String errorPage = ServerInfo.getInfos("errorPage");

    public ServerHandler(Socket socket) {
        this.socket = socket;

    }

    @Override
    public void run() {
        try {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintStream(socket.getOutputStream());
            // 构建request对象,分析请求
            Request request = new Request(in);
            String res = request.getResource();
            Response response = new Response(out);
            /*
             * if(程序){ 调用程序 }else if(文件){ 构建Response,调用
             * doResponse(request.getResouse()) 返回数据 }
             */
            if (res.contains(".bean")) {
                System.out.println("调用程序");
                // 1 先拿到资源名 .之前的内容
                String key = res.substring(1, res.indexOf("."));
                System.out.println("资源名:" + key);
                WebClass wc = BeanFactory.getBean(key);
                if (wc != null) {
                    wc.doService(request, response);
                } else {
                    response.doResponse(errorPage);
                }
            } else {
                System.out.println("查看文件");
                response.doResponse(res);
            }
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. Request.java

处理request请求的函数

package cob.briup.webServer.v2_1.requst;

import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;

public class Request {
    /**
     * 1.整合请求过程要用到的属性
     */
    // http请求按行读入
    private BufferedReader in = null;
    // GET 还是 POST
    private String method = null;
    // 请求的资源名
    private String resource = null;
    // 接收页面数据
    private Map<String, String> params = new HashMap<>();

    /**
     * 2.分析请求行,得到请求方式和请求资源 赋值给属性
     */
    public Request(BufferedReader in) {
        try {
            // 分析资源
            String requestLine = in.readLine();
            // "".equals(requestLine)
            // 如果请求行不是空字符串也不是null再进行处理
            if (!"".equals(requestLine) && requestLine != null) {
                System.out.println("请求行:" + requestLine);
                String[] infos = requestLine.split(" ");
                this.method = infos[0];
                // infos[1]在get方式传参的时候
                // 如果真的有参数,资源名?key=value&key2=value2
                String value = infos[1];
                if (getMethod().toUpperCase().equals("GET")) {
                    if (value.contains("?")) {
                        String kv = value.substring(value.indexOf("?") + 1);
                        parseParam(kv);
                        resource = value.substring(0, value.indexOf("?"));
                    } else {
                        resource = value;
                    }
                } else if (getMethod().toUpperCase().equals("POST")) {
                    resource = value;
                    String line = null;
                    int requestBodyLen = 0;
                    // 读请求头,找有木有Content-length
                    while ((line = in.readLine()) != null) {
                        if (line.contains("Content-Length")) {
                            requestBodyLen = Integer.parseInt(line.substring(line.indexOf(":") + 1).trim());
                        }
                        if (line.equals("")) {
                            break;
                        }
                    }
                    // 按照字符读取请求体,再拼接成字符串
                    if (requestBodyLen > 0) {
                        // 拼接字符串使用StringBuffer
                        StringBuffer buff = new StringBuffer();
                        for (int i = 0; i < requestBodyLen; i++) {
                            buff.append((char) in.read());
                        }
                        parseParam(buff.toString());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 解析页面传来的参数放入map中
    public void parseParam(String kv) {
        // 先使用&拆分出一对key-value
        String[] strkv = kv.split("&");
        for (int i = 0; i < strkv.length; i++) {
            // 再使用=拆分出一对key-value中的key和value
            params.put(strkv[i].split("=")[0], strkv[i].split("=")[1]);
        }
    }

    /**
     * 3.提供get方法获取请求资源
     */
    public String getResource() {
        System.out.println("文件名:" + resource);
        return resource;
    }

    public String getMethod() {
        return method;
    }

    // 提供从私有map中获取参数value的方法
    public String getParameter(String key) {
        return params.get(key);
    }
}

4.response.java

做出响应的函数

package cob.briup.webServer.v2_1.response;

import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
import cob.briup.webServer.v2_1.util.ServerInfo;

public class Response {
    /**
     * 1.整合响应过程要用到的属性
     */
    // 数据仓库位置
    private String storage = ServerInfo.getInfos("storage");
    String indexPage = ServerInfo.getInfos("indexPage");
    String errorPage = ServerInfo.getInfos("errorPage");
    // 返还的文件
    private File file = null;
    private FileInputStream fis = null;
    private PrintStream out = null;

    /**
     * 2.初始化属性
     */
    public Response(PrintStream out) {
        this.out = out;
    }

    /**
     * 3.处理响应逻辑,将要返还给客户端的资源
     */
    public void doResponse(String resource) {
        try {
            if (resource.equals("/")) {
                resource = indexPage;
            }
            // 响应行
            String responseLine = "HTTP/1.1 200 OK";
            File file = new File(storage + "/" + resource);
            if (!file.exists()) {
                file = new File(storage + errorPage);
                responseLine = "HTTP/1.1 404 NotFound";
            }
            // 文件存在,统一处理
            // 通过fis读进程序,再通过socket响应给客户端
            fis = new FileInputStream(file);
            byte[] temp = new byte[1024];
            out.println(responseLine);
            // 空行
            out.println();
            // while循环负责写文件,相当于写响应体
            while (fis.read(temp) != -1) {
                out.write(temp);
                out.flush();
            }
            // 文件输出完毕关闭输出流
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.BeanFactory.java

package cob.briup.webServer.v2_1.util;
//1.读取配置文件,将配置文件所描述的类,进行实例化
//2.提供生产方法,传入字符串拿出对应的对象

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import cob.briup.webServer.v2_1.webclass.WebClass;

public class BeanFactory {
    static Properties beans = new Properties();
    static Map<String, WebClass> objects = new HashMap<String, WebClass>();

    static {
        try {
            // 从当前所在类的目录下找beans.properties文件
            beans.load(BeanFactory.class.getResourceAsStream("beans.properties"));
            Set<Object> keys = beans.keySet();
            Iterator<Object> it = keys.iterator();
            while (it.hasNext()) {
                String key = (String) it.next();
                String className = beans.getProperty(key);
                Object o = Class.forName(className).newInstance();
                objects.put(key, (WebClass) o);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static WebClass getBean(String beanName) {
        return objects.get(beanName);
    }
}

6. ServerInfo.java

package cob.briup.webServer.v2_1.util;

import java.io.IOException;
import java.util.Properties;

public class ServerInfo {
    static Properties infos = new Properties();

    static {
        try {
            infos.load(ServerInfo.class.getResourceAsStream("infos.properties"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static String getInfos(String key) {
        return infos.getProperty(key);
    }
}

7. WebClass.java

package cob.briup.webServer.v2_1.webclass;
import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;

//能被客户端访问的服务端的类必须包含某个特定方法
//定义接口,接口中包含doService()方法
public interface WebClass {
    public void doService(Request request, Response response);
}

8.LoginWebClass

用于控制登录的类

package cob.briup.webServer.v2_1.webclass;

import cob.briup.webServer.v2_1.webclass.WebClass;

import java.io.IOException;
import java.util.Properties;

import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
import cob.briup.webServer.v2_1.util.ServerInfo;

public class LoginWebClass implements WebClass {
    static Properties users = new Properties();

    static {
        try {
            users.load(LoginWebClass.class.getResourceAsStream("userInfo.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doService(Request request, Response response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("页面用户名:" + username + "\t" + "页面密码:" + password);

        String psd = users.getProperty(username);

        System.out.println("文件用户名:" + username + "\t" + "文件密码:" + psd);

        if (psd == null || username == null) {
            System.out.println("用户不存在");
            response.doResponse(ServerInfo.getInfos("loginFailP"));
        } else if (psd != null) {
            if (psd.equals(password)) {
                System.out.println("用户存在且密码正确");
                response.doResponse(ServerInfo.getInfos("loginSucceedP"));
            } else if (psd != password) {
                System.out.println("用户名存在但是密码不正确");
                response.doResponse(ServerInfo.getInfos("loginFailP"));
            }
        }
    }
}

9.RegisterWebClass

用于控制注册的类

package cob.briup.webServer.v2_1.webclass;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;

import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
import cob.briup.webServer.v2_1.util.ServerInfo;

public class RegisterWebClass implements WebClass {

    static Properties users = new Properties();
    PrintWriter writeUserInfo = null;
    boolean userExists = false;

    static {
        try {
            users.load(LoginWebClass.class.getResourceAsStream("userInfo.properties"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void doService(Request request, Response response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String path = "F:\\杰普培训\\code\\JD1710_MyWebServer\\src\\cob\\briup\\webServer\\v2_1\\webclass\\userInfo.properties";
        File userInfo = new File(path);

        Set<Object> keySet = users.keySet();
        for (Object o : keySet) {
            if (o.equals(username)) {
                userExists = true;
            }
        }

        try {

            if (!userExists) {
                writeUserInfo = new PrintWriter(new FileWriter(userInfo, true));
                writeUserInfo.println(username + "=" + password);
                writeUserInfo.flush();
                writeUserInfo.close();
                response.doResponse(ServerInfo.getInfos("loginP"));
            } else {
                System.out.println("要注册的用户已经存在");
                response.doResponse(ServerInfo.getInfos("regisFailP"));
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(userInfo.exists());
    }

}

10.运行结果

10.1 服务器开启
这里写图片描述
10.2浏览器访问默认资源
这里写图片描述
10.3浏览器访问服务器没有的资源
这里写图片描述
10.4
注册功能
这里写图片描述
注册失败
这里写图片描述
10.5
登录功能
这里写图片描述
登录成功
这里写图片描述
登录失败
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值