项目内容

1.手写一个HTTP服务器
2.手写一个博客系统运行在HTTP服务器上

项目环境/平台

Windows10+IDEA+JDK1.8+Maven+MySQL

目录

1.Http请求解析
2.Http响应
3.静态Controller处理
4.自定义类加载器
5.开启服务器Server类
6.博客代码
博客提交页面
博客列表页面
博客文章详情

Http请求

首先编写代码进行解析请求
请求包含以下部分
请求行 GET /aaa.html?id=1&password=ppp&name=10 HTTP/1.1
请求头 Host: www.aaa.com Accept:text/html等信息
请求体 请求体(get方法没有请求体)
特殊格式的请求 “GET /hello?target=%E4%B8%AD%E5%9B%BD HTTP/1.0”

解析请求行
请求的方法method
请求的参数urlall,请求的参数
请求的版本号protocol
解析请求头
请求头Host:网址
请求头Accept:text/html
请求的编码
1.首先定义请求类保存请求行请求头参数
2.在解析请求头的时候判断是post还是get方法
3.进行分步解析

package com.github7.request;
import java.io.*;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;public class Request {String url;String protocol;String method;Map<String, String> headers = new HashMap<>();Map<String, String> requestParam = new HashMap<>();public void setProtocol(String protocol) {this.protocol = protocol;}public void setHeaders(String key, String value) {this.headers.put(key, value);}public void setRequestParam(String key, String value) {this.requestParam.put(key, value);}public void setMethod(String method) throws IOException {this.method = method.toUpperCase();if (this.method.equals("POST") || this.method.equals("GET")) {return;}throw new IOException("不支持的方法");}public void setUrl(String url) throws UnsupportedEncodingException {this.url = URLDecoder.decode(url, "UTF-8");}public String getUrl() {return url;}public String getProtocol() {return protocol;}public String getMethod() {return method;}public Map<String, String> getHeaders() {return headers;}public Map<String, String> getRequestParam() {return requestParam;}//请求方法public static Request parse(InputStream inputStream) throws IOException {//传入浏览器请求的字节流,Server解析BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));Request request = new Request();//设置请求行参数praseRequestLine(bufferedReader, request);//设置请求头参数praseRequestHeader(bufferedReader, request);return request;}//请求第一行 请求行:方法 请求URL HTTP版本号//GET /aaa.html?id=1&password=ppp&name=10 HTTP/1.1private static void praseRequestLine(BufferedReader bufferedReader, Request request) throws IOException {String firstLine = bufferedReader.readLine();//第一行参数是以" "进行分割。然后得到请求方法,请求参数,请求版本号//比如请求行为GET /aaa.html?id=1&name=10 HTTP/1.1String[] fragments = firstLine.split(" ");//fragmens至少存在三个参数if (fragments.length < 3) {throw new IOException("错误的请求行,参数不够");}//第一个参数是请求方式String method = fragments[0];request.setMethod(method);//第二个参数是总的url请求参数String urlAll = fragments[1];//第三个参数是版本号String protocol = fragments[2];request.setProtocol(protocol);//获取url请求页面,是urlAll里面的String[] qFragmens = urlAll.split("\\?");request.setUrl(qFragmens[0]);//获取请求的参数 qFragmens里面的第二个参数//id=1 & name=10if (qFragmens.length > 1) {String[] mess = qFragmens[1].split("&");for (int i = 0; i < mess.length; i++) {String[] keyvalue = mess[i].split("=");String key = keyvalue[0];String value = "";if (keyvalue.length > 1) {value = URLDecoder.decode(keyvalue[1], "utf-8");}//将获取到的键值对添加进去request.setRequestParam(key, value);}}}//请求第二部分,直到遇到空行结束// 请求头有很多信息如下:// Host:www.baidu.com// Accept:text/htmlprivate static void praseRequestHeader(BufferedReader bufferedReader, Request request) throws IOException {String secondLine;//将请求头的信息全部保存到HashMap中。while ((secondLine = bufferedReader.readLine()) != null && secondLine.trim().length() != 0) {String[] keyValue = secondLine.split(":");//分割之后可能会出现空格。所以要去掉空格String key = keyValue[0];String value = "";if (keyValue.length > 1) {value = keyValue[1].trim();}//将信息头保存到请求头里面request.setHeaders(key, value);}}@Overridepublic String toString() {return "Request{" +"请求页面='" + url + '\'' +", 版本号='" + protocol + '\'' +", 请求方法='" + method + '\'' +", 请求头=" + headers +", 请求行参数=" + requestParam +'}';}
}

Http响应

响应主要包括三部分 1.响应行 2.响应头 3.响应体
第一行版本信息和状态码:HTTP/1.1 200 OK
第二行响应头里面有:
Server HTTP 服务器编号
Date Wed, 07 Aug 2019 10:14:53 GMT 指定格式的响应时间说明
Content-Type 响应体的格式说明
Content-Length 响应体的长度说明
常见状态码
200 OK
302 Temporarily Moved
400 Bad Request
404 Not Found
405 Method Not Allowed
500 Internal Server Error
编码
1.首先我们创建一个输出流数组,保存所有的信息
2.创建一个枚举类保存状态码
3.设置我们的响应服务器,类型等信息。
4.设置好之后,将响应行,响应头,响应体写到字节数组中去
5.将字节数组中的内容拷贝到输出流中,并设置长度。

package com.github7.response;import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;public class Response {public static Response start(OutputStream outputStream) throws IOException {Response response = new Response();response.setServer();response.setOutputStream(outputStream);response.setContentType("text/html");response.setDate();return response;}//保存输出流private byte[] resByteArray = new byte[8192];private OutputStream outputStream;private void setOutputStream(OutputStream outputStream) {this.outputStream = outputStream;}private int contentLength = 0;//保存以下信息Content-Type:Content-Lenth:Data:Server:private Map<String, String> headers = new HashMap<>();//将默认状态置为200 okprivate State state = State.OK;public void setState(State state) {this.state = state;}private void setServer() {headers.put("Server", "LR/1.0");}public void setContentType(String contentType) {headers.put("Content-Type", contentType + ";charset=utf-8");}private void setDate() {SimpleDateFormat dateFormat = new SimpleDateFormat("E,dd MMM yyyy HH:mm:ss z");headers.put("Date", dateFormat.format(new Date()));}//将信息写入到响应输出流中的方法。public void write(byte[] bytes, int off, int len) throws IOException {if (contentLength + len > 8192) {throw new IOException("超过请求头最大长度");}//将写入的东西先保存在自己的byte数组中System.arraycopy(bytes, off, resByteArray, contentLength, len);contentLength += len;}public void write(byte[] bytes, int len) throws IOException {write(bytes, 0, len);}public void write(byte[] bytes) throws IOException {write(bytes, bytes.length);}//格式化响应public void print(String string, Object... args) throws IOException {write(new Formatter().format(string, args).toString().getBytes("utf-8"));}public void println(Object o) throws IOException {print("%s%n", o.toString());}public void flush() throws IOException {headers.put("Content-Length", String.valueOf(contentLength));sendResponseLine();sendResponseHeads();outputStream.write(resByteArray, 0, contentLength);}//将响应行加入到输出流中public void sendResponseLine() throws IOException {String responseLine = String.format("HTTP/1.0 %d %s \r\n", state.getCode(), state.getReason());outputStream.write(responseLine.getBytes());}//将响应头加入到输出流中public void sendResponseHeads() throws IOException {for (Map.Entry<String, String> entry : headers.entrySet()) {String header = String.format("%s:%s\r\n", entry.getKey(), entry.getValue());outputStream.write(header.getBytes("utf-8"));}outputStream.write("\r\n".getBytes("UTF-8"));}@Overridepublic String toString() {return "Response{" +" headers=" + headers +", state=" + state +'}';}
}
package com.github7.response;public enum State {OK(200, "OK"),Temporarily_Moved(302, "Temporarily Moved"),BAD_REQUEST(400, "BAD_REQUEST"),NOT_FOUND(404, "NOT_FOUND"),METHOD_NOT_ALLOWED(405,"Not_Allowed"),INTERNAL_SERVER_ERROR(500, "INTERNAL SERVER ERROR");private int code;private String reason;public int getCode() {return code;}public String getReason() {return reason;}State(int code, String reason) {this.code = code;this.reason = reason;}
}

创建父类Controller控制器

该类有两个方法默认执行的doGet方法

package com.github7.controller;import com.github7.request.Request;
import com.github7.response.Response;
import com.github7.response.State;import java.io.IOException;public class Controller {public void doGet(Request request, Response response) throws IOException {if (request.getProtocol().endsWith("1.0")) {response.setState(State.METHOD_NOT_ALLOWED);response.println("版本号不支持,仅支持1.1");} else {response.setState(State.BAD_REQUEST);response.println("请求错误,仅支持HTTP/1.1");}}public void doPost(Request request, Response response) throws IOException {this.doGet(request, response);}
}

静态页面加载

StaticContraller继承自Controller覆写其方法
编码
1.首先我们根据url获取要链接的静态页面。
2.如果要获取的页面是当前路径/就加载指定静态页面
3.读取文件内容,将文件写到byte数组中
4.根据文件后缀比如.html设置ContentType

package com.github7.controller;import com.github7.request.Request;
import com.github7.response.Response;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;public class StaticController extends Controller {private static final String HOME = System.getenv("LR_HOME");//保存ContentType  支持三种类型用HashMap先保存起来private final Map<String, String> Content_TYPE = new HashMap<String, String>() {{put("html", "text/html");}};@Overridepublic void doPost(Request request, Response response) throws IOException {this.doGet(request, response);}@Overridepublic void doGet(Request request, Response response) throws IOException {//1.获取文件地址 request.getUrl()得到的是/hh.htmlString filename = getFileName(request.getUrl());//2.开始读取文件内容System.out.println(filename);InputStream inputStream = new FileInputStream(filename);//缓冲流 一次读取1024字节内容byte[] buf = new byte[1024];int len;while ((len = inputStream.read(buf)) != -1) {response.write(buf, 0, len);}//3.获取类型content-type,根据文件名的后缀String suffix = getSuffix(filename);String contype = getContentType(suffix);//然后设置响应头里面的contenttyperesponse.setContentType(contype);}private String getContentType(String suffix) {String contentType = Content_TYPE.get(suffix);if (contentType == null) {//说明没有这种类型的文件contentType = "text/html";}return contentType;}private String getSuffix(String filename) {//找到最后一个点,点后面的就是文件类型int index = filename.lastIndexOf('.');if (index == -1) {return null;}//返回文件名后缀return filename.substring(index + 1);}private String getFileName(String url) {if (url.equals("/")) {url = "/index.html";}return "F:\\\\httpProject\\webapps\\"+ url.replace("/", File.separator);}
}

自定义类加载器

首先要定义一个类加载器,我们如果在静态页面找不到页面。就找动态的类进行加载
1.根据传进来的url进行解析得到我们的文件
2.通过继承ClassLoader找到我们所需要的文件.class文件。
3.读取内容返回生成Class对象
4.通过返回的Class对象创建controller实例

package com.github7.classloader;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;public class MyClassLoader extends ClassLoader {@Overridepublic Class<?> findClass(String name) throws ClassNotFoundException {try {return super.findClass(name);} catch (ClassNotFoundException e) {//1.根据类名称找到name对应的.class文件//String fileLocation =  "F:\\\\LRhttp\\webapps\\WEB-INF\\classes\\"+name.replace("/","")+".class";String fileLocation = "F:\\\\httpProject\\target\\classes\\" + name.replace("/", "") + ".class";File file = new File(fileLocation);if (file.exists()) {//2.读取文件内容。byte[] buf = new byte[8192];int len = 0;try {len = new FileInputStream(fileLocation).read(buf);} catch (IOException e1) {throw new ClassNotFoundException("文件出错",e);}//3.调用defineClass 转为Class<?>System.out.println("类名" + name.replaceAll("/", ""));return defineClass(name.replaceAll("/", ""), buf, 0, len);} else {throw new ClassNotFoundException("类没找到");}}}
}

Main类 Server端

1.创建ServerSocket监听端口
创建Socket从网络中读取和写入数据,不同计算机上的两个应用可以通过连接发送和接受字节流。
2.分别创建Request和Response引用指向socket的输入输出流
3.获取url判断调用静态页面还是加载动态类
4.创建实例调用doGet/doPost方法
5.调用flush方法,更新数据

package com.github7.server;import com.github7.classloader.MyClassLoader;
import com.github7.controller.Controller;
import com.github7.controller.StaticController;
import com.github7.request.Request;
import com.github7.response.Response;
import com.github7.response.State;
import org.dom4j.DocumentException;import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Server {public final Controller staticController = new StaticController();public Server() throws DocumentException {}public static void main(String[] args) throws IOException, DocumentException {Server server = new Server();server.run(1234);}public void run(int port) throws IOException {ExecutorService pool = Executors.newFixedThreadPool(20);//监听端口ServerSocket serverSocket = new ServerSocket(port);// 查看端口netstat -anowhile (true) {Socket socket = serverSocket.accept();pool.execute(new Runnable() {@Overridepublic void run() {try {//初始化Request request = Request.parse(socket.getInputStream());Response response = Response.start(socket.getOutputStream());//查找请求url是否存在String filelocation = request.getUrl();String filename = "";if (filelocation.equals("/")) {filename = "F:\\\\httpProject\\webapps\\index.html";}filename = "F:\\\\httpProject\\webapps\\" + filelocation.replace("/", File.separator);//根据 URL 的不同,用不用的 controller 去处理File file = new File(filename);Controller controller = null;if (file.exists()) {System.out.println("静态controller");controller = staticController;} else {System.out.println("动态controller");Class<?> cla = null;String name = request.getUrl().replace("/", "");if (name.equals("article")) {cla = new MyClassLoader().loadClass("ArticleController");} else if (name.equals("postArticle")) {cla = new MyClassLoader().loadClass("PostController");} else {cla = new MyClassLoader().loadClass(name);}if (cla != null) {System.out.println(cla.getName());controller = (Controller) cla.newInstance();}}//动态也找不到 返回错误if (controller == null) {response.setState(State.NOT_FOUND);response.println("<h1>" + State.NOT_FOUND.getCode() + "    " + State.NOT_FOUND.getReason() + " 页面没有找到</h1>");} else {if (request.getMethod().equals("GET")) {controller.doGet(request, response);} else if (request.getMethod().equals("POST")) {controller.doPost(request, response);} else {//不支持的方法response.setState(State.METHOD_NOT_ALLOWED);response.println(State.METHOD_NOT_ALLOWED.getReason());}}response.flush();System.out.println(request.toString());System.out.println(response.toString());System.out.println();socket.close();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}});}}
}

小型博客

博客主要由以下部分构成
post.html博客提交页面
PostController博客提交:获取到html表单内容,往数据库中写入数据
ListController博客列表页面:获取数据库中的所有标题已经作者
ArticleController博客文章详情:点击超链接,连接数据库获取数据信息。

post.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>发表文章</title><script>function getNewDate() {//创建日期对象var date = new Date();//拼接年月日var datestr = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate()+ "&nbsp&nbsp" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();//通过id来获取span对象var span = document.getElementById("span_id");//设置span对象的innerHTML属性span.innerHTML = datestr;}window.setInterval("getNewDate()", 1000);</script>
</head><body>
<center><h1>发表文章</h1><a href='/ListController'>首页</a><h4><span id="span_id"></span></h4><form action="/postArticle" method="get">标题:<input type="text" name="title"  /></br>作者:<input type="text" name="author" /></br></br><textarea name="content" style="width:600px;height:400px;" ></textarea> </br><input type="submit" name="" value="提交"/></form>
</center>
</body>
</html>

获取html表单内容,发表文章

/*Author:linruiDate:2019/8/26Content:
*/import com.github7.controller.Controller;
import com.github7.request.Request;
import com.github7.response.Response;
import com.github7.response.State;import java.io.IOException;
import java.sql.*;
import java.util.UUID;public class PostController extends Controller {@Overridepublic void doGet(Request request, Response response) throws IOException {this.doPost(request, response);}@Overridepublic void doPost(Request request, Response response) throws IOException {//获取url的id 和内容String id = UUID.randomUUID().toString();//随机IDString title = request.getRequestParam().get("title");String author = request.getRequestParam().get("author");String content = request.getRequestParam().get("content");if(title.length()==0){response.println("<center>");response.println("输入标题</br>");response.println("</h4><a href='/post.html'>点击返回发表文章</a></h4></center>");response.println("</center>");return;}if(author.length()==0){response.println("<center>");response.println("对不起,未输入作者姓名</br>");response.println("</h4><a href='/post.html'>点击返回发表文章</a></h4></center>");response.println("/<center>");return;}if(content.length()==0){response.println("<center>");response.println("未输入内容</br>");response.println("</h4><a href='/post.html'>点击返回发表文章</a></h4></center>");response.println("</center>");return;}//然后将所有内容存储到数据库中//连接到数据库Connection connection = null;Statement statement = null;PreparedStatement preparedStatement = null;String url = "jdbc:mysql://localhost:3307/blogs?useSSL=false";String sql = "insert into blog values(?,?,?,?)";try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection(url, "root", "aaaaaa");preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, id);preparedStatement.setString(2, title);preparedStatement.setString(3, author);preparedStatement.setString(4, content);preparedStatement.executeUpdate();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}//重定向首页response.setState(State.Temporarily_Moved);System.out.println("进入到PostController");response.setHeaders("Location", "/article?id=" + id);}
}

文章 title


import com.github7.controller.Controller;
import com.github7.request.Request;
import com.github7.response.Response;import java.io.IOException;
import java.sql.*;public class ListController extends Controller {@Overridepublic void doGet(Request request, Response response) throws IOException {this.doPost(request, response);}@Overridepublic void doPost(Request request, Response response) throws IOException {response.println("<center><h1>所有文章</h1>");response.println("</h4><a href='/post.html'>发表文章</a></h4></center>");Connection connection = null;Statement statement = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;String url = "jdbc:mysql://localhost:3307/blogs?useSSL=false";String sql = "select article_id,article_title,article_author from blog";try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection(url, "root", "aaaaaa");preparedStatement = connection.prepareStatement(sql);resultSet = preparedStatement.executeQuery();while (resultSet.next()) {String id = resultSet.getString(1);String title = resultSet.getString(2);String author=resultSet.getString(3);response.println("<li><a href='/article?id=" + id + "'>" + title + "</a>"+"&nbsp;&nbsp;&nbsp;作者:"+author+"</li>");}} catch (ClassNotFoundException e) {System.out.println(e.getMessage());} catch (SQLException e) {e.printStackTrace();} finally {try {resultSet.close();preparedStatement.close();connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

文章详情页面


import com.github7.controller.Controller;
import com.github7.request.Request;
import com.github7.response.Response;import java.io.IOException;
import java.sql.*;public class ArticleController extends Controller {@Overridepublic void doGet(Request request, Response response) throws IOException {this.doPost(request, response);}@Overridepublic void doPost(Request request, Response response) throws IOException {//从url 获取idString id = request.getRequestParam().get("id");Connection connection = null;Statement statement = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;String url = "jdbc:mysql://localhost:3307/blogs?useSSL=false";String sql = "select article_title,article_author,article_content from blog where article_id='" + id + "'";try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection(url, "root", "aaaaaa");preparedStatement = connection.prepareStatement(sql);resultSet = preparedStatement.executeQuery();response.println("</h6><a href='/ListController'>回到首页</a></h6>");while (resultSet.next()) {String title = resultSet.getString(1);String author = resultSet.getString(2);String content = resultSet.getString(3);response.println("<h3><center>" + title + "</center></h3>");response.println("<h5><center>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" +"作者:" + author + "</center></h5>");response.println(content);}} catch (ClassNotFoundException e) {System.out.println(e.getMessage());} catch (SQLException e) {e.printStackTrace();} finally {try {resultSet.close();preparedStatement.close();connection.close();} catch (SQLException e) {response.println(e.getMessage());}}}
}

首页

文章title页

文章详情页

迷你HTTP服务器+小型博客相关推荐

  1. 阿里云轻量级服务器搭建博客网站教程(入门级别搭建)

    阿里云轻量级服务器搭建博客网站教程 先给大家看一下最后的成果:zhangshuaiqi.xyz 使用宝塔面板部署ssl证书,伪静态设置,一键部署wordpress 服务器类型:阿里云轻量级服务器2核4 ...

  2. 利用django+pycharm开发小型博客项目!!!

    废话不多说,让我王虎剩大将军带领大家利用djang框架开发一个小型的博客项目吧!! 首先,此教程适合的人群为,懂得创建python的虚拟环境,以及拥有少数web前端开发的经验,并且拥有少数的后端编程经 ...

  3. 服务器版博客系统、前后端交互1

    一.准备工作 1). 创建 maven 项目 2). 引入依赖 servlet,jackson,mysql <dependencies><!-- https://mvnreposit ...

  4. 用树莓派做服务器运行博客网页

    文章目录 阅读本文你将了解的知识点: 树莓派做服务器运行Hexo博客网页 1.服务器框架 2.本地Hexo设置 2.1 安装GIT 2.2 安装NodeJs 2.3 安装Hexo 2.4 Hexo生成 ...

  5. 在 ABT 节点上启动 Solid 服务器 | ArcBlock 博客

    作者: Matt McKinney 译者: 陈俊 为了把数据合法所有权归还给每个网络用户以破除当今互联网越来越集中垄断的格局,万维网之父蒂姆·伯纳斯-李从 2015 年开始研发 Solid,并于 20 ...

  6. vue项目如何打包扔向服务器 - Hi-Sen - 博客园

    当我们将 vue 项目完成后,面临的就是如何将项目进行打包上线,放到服务器中.我使用的是 vue-cli(simple) 脚手架,所以就讲一下如何将项目进行打包,并放到 tomcat 上.    如果 ...

  7. 如何搭建NTP时间同步服务器-大萝卜博客网

    安装NTPD服务端 rpm -qa ntp | grep ntpd 检测是否已经安装,如未安装执行yum安装服务 yum install ntp 关闭防火墙 service iptables stop ...

  8. 伪保姆级教程 | 如何使用阿里云服务器搭建博客

    从购买到搭建,一条龙全纪录 阿里云 ECS + Ubuntu18.04 咳咳,老手请绕道,写的不好,见谅见谅!正文开始- 第一话:确定目标 1.服务器 云翼计划 云小站 试用中心 刚入坑,选择了 云翼 ...

  9. 服务器搭建博客(二):服务器LNMP环境搭建

    文章目录 前言 安装Xshell 连接到服务器 安装宝塔面板 安装网站环境 前言 由于全部自己手动安装的话,还是比较麻烦的,我先也是自己手动配,遇到了不少问题,下一篇会总结一下,自己安装遇到的一些问题 ...

  10. 快速搭建一个小型博客网站

    目录 ✨前言

最新文章

  1. 使用VMware Infrastructure Client中的VMware Server 2.0.x的管理
  2. 内存溢出之Tomcat内存配置
  3. Java+大数据开发——HDFS详解
  4. php获取日期中的月份,年份
  5. Java程序员需要掌握的计算机底层知识(三):进程、线程、纤程、中断
  6. 【FFMPEG源码终极解析】 av_packet_alloc 与 av_packet_free
  7. UVA 536——Tree Recovery
  8. Windows GDI和GDI+编程实例剖析(1)
  9. mysql时间相关函数和操作
  10. 假期的游戏陪玩市场,有人挣钱有人被骗
  11. 给萌新的Flexbox简易入门教程
  12. 保存命令行输出信息到log的方法(ubunut下和arm-linux下有效)
  13. matlab练习程序(图像放大/缩小,双立方插值)
  14. springboot(运行原理参考借鉴)
  15. 全链路压测及阿里全链路压测详解
  16. zebradesginer zpl代码_ZebraDesigner Pro 斑马打印机命令 解读
  17. 微软2008年7月「最有价值专家」(MVP)当选名单
  18. 借你的名字,诵念尘世的幸福
  19. 《万历十五年》的读后感作文4000字
  20. 会员测试环境治理之路

热门文章

  1. 高性能diffpatch算法 -- 如何将微信Apk的官方增量包20.4M缩小到7.0M
  2. 外汇交易风险有那些?
  3. Android滑动菜单特效实现,仿人人客户端侧滑效果,史上最简单的侧滑实现
  4. python计算图像面积_利用图像处理计算叶片面积
  5. redmine使用指南_Redmine安装与入门指南
  6. UFS Host Controller工作流程
  7. linux用命令行快速切换目录
  8. c语言round函数作用,if条件函数怎样和round一起用?!,C++中round函数怎么用
  9. JAVA常用工具类汇总
  10. 离散数据:析取范式与合取范式