Server类
1.Server类作用
读取服务器配置
创建服务器倾听Socket,并在每次接收到请求后将请求交由一个新的HttpHandler线程进行处理
2.读取服务器配置
在静态代码块读取服务器配置,包括服务器倾听端口、资源根路径、错误页面路径、默认页面路径
static { InputStream serverConfigStream = Server.class.getClassLoader().getResourceAsStream("server-config.properties"); Properties serverConfigProps = new Properties(); try { serverConfigProps.load(serverConfigStream); } catch (IOException e) { throw new RuntimeException("server-config not found"); } //服务器倾听端口 serverPort = Integer.parseInt(serverConfigProps.getProperty("server-port")); //资源根路径 resourceRoot = serverConfigProps.getProperty("resource-root"); //错误页面路径 errorPage = serverConfigProps.getProperty("error-page"); //默认页面路径 defaultPage = serverConfigProps.getProperty("default-page");}
2.接收请求并移交HttpHandler处理
public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(serverPort); while (true) { Socket socket = serverSocket.accept(); new Thread(new HttpHandler(socket)).start(); } } catch (IOException e) { e.printStackTrace(); }}
HttpHandler类
1.HttpHandler类作用
处理到达服务器的请求,响应资源给客户端
由于是静态资源服务器,所以需要获取资源的路径(注意解决中文路径的乱码问题)
为了浏览器按正确格式解析资源,所以要获取资源的ContentType
2.获取请求资源的路径
通过Socket的输入流获取请求行,在请求行中获取请求资源的路径
/** * 获取请求资源的路径 * 用URLDecoder的decode方法给路径解码防止中文乱码 * * @return */public String getRequestPath() { BufferedReader br = new BufferedReader(new InputStreamReader(is)); try { //请求行 String requestLine = br.readLine(); String[] split = requestLine.split("\\s"); if (split.length == 3) { //用URLDecoder的decode方法给路径解码防止中文乱码 return URLDecoder.decode(split[1], "utf-8"); } } catch (IOException e) { e.printStackTrace(); } return null;}
3.获取请求资源的ContentType
通过MimetypesFileTypeMap对象的getContentType方法获取请求资源的ContentType
/** * 获取请求资源的ContentType * * @param file * @return */private String getContentType(File file) { return mimetypesFileTypeMap.getContentType(file);}
4.响应请求的资源给客户端
请求路径未携带请求资源路径,则响应默认页面
请求资源不存在,则响应错误页面
请求资源存在,则获取资源文件输入流以及资源文件的ContentType并响应给客户端
/** * 响应请求的资源给客户端 */private void response(String path) { //响应请求资源给客户端的输出流 BufferedOutputStream bos; //获取请求资源的输入流 BufferedInputStream bis; try { //请求的资源文件 File file = new File(Server.resourceRoot + path); bos = new BufferedOutputStream(os); String separator = File.separator; if (!path.equals("/")) {//请求路径中含资源路径 if (file.exists()) {//文件存在 //响应头 bos.write("HTTP/1.1 200 ok\r\n".getBytes()); bos.write(("Content-Type:" + getContentType(file) + "\r\n").getBytes()); bos.write(("Content-Length:" + file.length() + "\r\n").getBytes()); //必须写入空行,否则浏览器不解析 bos.write("\r\n".getBytes()); System.out.println("一个客户端建立连接"); } else {//文件不存在 //响应头 bos.write("HTTP/1.1 404 file not found\r\n".getBytes()); bos.write("Content-Type:text/html\r\n".getBytes()); //必须写入空行,否则浏览器不解析 bos.write("\r\n".getBytes()); System.out.println("一个客户端建立连接"); //文件找不到,就用错误页面代替 file = new File(Server.resourceRoot + Server.errorPage); } } else {//请求路径中不含资源路径,则直接跳转到默认页面 //响应头 bos.write("HTTP/1.1 200 ok\r\n".getBytes()); bos.write("Content-Type:text/html\r\n".getBytes()); //必须写入空行,否则浏览器不解析 bos.write("\r\n".getBytes()); System.out.println("一个客户端建立连接"); file = new File(Server.resourceRoot + Server.defaultPage); } //响应体 bis = new BufferedInputStream(new FileInputStream(file)); byte[] buffer = new byte[1024]; int length; while ((length = bis.read(buffer)) != -1) { bos.write(buffer, 0, length); } bos.flush(); } catch (IOException e) { e.printStackTrace(); }}