使用Java技术构建Web应用时, 我们通常离不开tomcat和jetty之类的servlet容器,这些Web服务器功能强大,性能强劲,深受欢迎,是运行大型Web应用的必备神器。

虽然Java的设计初衷就是用来开发大型应用的,然而有时候我们开发的程序只是简单的小型应用,对于功能的需求和性能的要求并不高, 可能仅仅就几百行甚至几十行代码,这个时候使用tomcat之类的Web服务器去运行就显得有点大材小用了。 比如说只是将数据库中的数据读出来转换成JSON,以Web服务的形式吐给调用方这样的阉割型Web应用。 如下图所示

二、最简单的Java Http服务器

其实在jdk中已经内置了用于此类简单Web应用构建需求的类库了,sun公司提供的 com.sun.net.httpserver 包就是用来帮助我们解决这类问题的

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer; import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress; public class Main { public static void main(String[] arg) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8001), 0);
server.createContext("/test", new TestHandler());
server.start();
} static class TestHandler implements HttpHandler{
@Override
public void handle(HttpExchange exchange) throws IOException {
String response = "hello world";
exchange.sendResponseHeaders(200, 0);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}

如上代码清单所示, 仅仅几行代码就可以构建一个五脏俱全的Web应用了。执行代码,在浏览器地址栏里代开链接

http://localhost:8001/test

就能运行这个段程序,输入的结果为helloworld

三、获得外部数据

那在这个程序中如何获取到外部传递过来的数据呢?比如说URL上的查询字符串,POST提交的数据等,其实也很简单

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import org.apache.commons.io.IOUtils; import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map; public class Main { public static void main(String[] arg) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8001), 0);
server.createContext("/test", new TestHandler());
server.start();
} static class TestHandler implements HttpHandler{
@Override
public void handle(HttpExchange exchange) {
String response = "hello world"; try{
//获得查询字符串(get)
String queryString = exchange.getRequestURI().getQuery();
Map<String,String> queryStringInfo = formData2Dic(queryString);
//获得表单提交数据(post)
String postString = IOUtils.toString(exchange.getRequestBody());
Map<String,String> postInfo = formData2Dic(postString); exchange.sendResponseHeaders(200,0);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}catch (IOException ie) { } catch (Exception e) { }
}
} public static Map<String,String> formData2Dic(String formData ) {
Map<String,String> result = new HashMap<>();
if(formData== null || formData.trim().length() == 0) {
return result;
}
final String[] items = formData.split("&");
Arrays.stream(items).forEach(item ->{
final String[] keyAndVal = item.split("=");
if( keyAndVal.length == 2) {
try{
final String key = URLDecoder.decode( keyAndVal[0],"utf8");
final String val = URLDecoder.decode( keyAndVal[1],"utf8");
result.put(key,val);
}catch (UnsupportedEncodingException e) {}
}
});
return result;
}
}

上面的代码清单标识了实现的方法。

注意,要保证上面代码编译通过, 需要引入commons-io.jar,此包中提供将InputStream转换成String的方法。

四、并发处理

com.sun.net.httpserver似乎默认不支持同时处理多个请求,一旦有并行的请求涌入,需要排队等待程序处理,导致Web程序响应卡顿。自定义实现的方法也很简单,为每个请求开一个新的线程处理即可, 如下代码清单所示

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import org.apache.commons.io.IOUtils; import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map; public class Main { public static void main(String[] arg) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8001), 0);
server.createContext("/test", new TestHandler());
server.start();
} static class TestHandler implements HttpHandler{
@Override
public void handle(HttpExchange exchange) {
new Thread(new Runnable() {
@Override
public void run() {
try{
String response = "hello world";
//获得查询字符串(get)
String queryString = exchange.getRequestURI().getQuery();
Map<String,String> queryStringInfo = formData2Dic(queryString);
//获得表单提交数据(post)
String postString = IOUtils.toString(exchange.getRequestBody());
Map<String,String> postInfo = formData2Dic(postString); exchange.sendResponseHeaders(200,0);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}catch (IOException ie) {
ie.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
} public static Map<String,String> formData2Dic(String formData ) {
Map<String,String> result = new HashMap<>();
if(formData== null || formData.trim().length() == 0) {
return result;
}
final String[] items = formData.split("&");
Arrays.stream(items).forEach(item ->{
final String[] keyAndVal = item.split("=");
if( keyAndVal.length == 2) {
try{
final String key = URLDecoder.decode( keyAndVal[0],"utf8");
final String val = URLDecoder.decode( keyAndVal[1],"utf8");
result.put(key,val);
}catch (UnsupportedEncodingException e) {}
}
});
return result;
}
}

五、优点

Java内置Web服务器在功能、性能、稳定等方面是无法和tomcat和jetty之类的专业Web服务器相比的, 它的优点主要是开发和部署方便简单, 把程序代码编译成jar包后,丢到装有jvm的服务器上, 直接运行就可以了,省去了安装相关的软件、依赖, 配置复杂的环境等工作量。

但是, 在一些各方面要求都比较高的生产环境下,还是建议使用专门的Web服务器,毕竟它们久经考验,能满足所有功能需求,并且出问题的几率低。

知乎:https://www.zhihu.com/people/aspwebchh

github:https://github.com/aspwebchh

email: aspwebchh@gmail.com

java构建简单的HTTP服务器的更多相关文章

  1. JAVA 实现 简单的 HTTP服务器

    关于JAVA的HTTP服务器的简单实现,还望大家给出宝贵建议,谢谢. 1.首先来说下HTTP所有的状态碼,相信对于网页开发的博友们,肯定不陌生. 状态码 状态码英文名称 中文描述 100 Contin ...

  2. 用Java实现简单的web服务器

    运行结果: 1.WebServer.java文件 package webserver; import java.io.*; import java.net.*; public class WebSer ...

  3. 使用Java实现简单的Http服务器

    在Java中可以使用HttpServer类来实现Http服务器,该类位于com.sun.net包下(rt.jar).实现代码如下: 主程序类 package bg.httpserver; import ...

  4. java实现一个简单的Web服务器

    注:本段内容来源于<JAVA 实现 简单的 HTTP服务器> 1. HTTP所有状态码 状态码 状态码英文名称 中文描述 100 Continue 继续.客户端应继续其请求 101 Swi ...

  5. 计算机网络(13)-----java nio手动实现简单的http服务器

    java nio手动实现简单的http服务器  需求分析 最近在学习HTTP协议,还是希望动手去做一做,所以就自己实现了一个http服务器,主要功能是将http请求封装httpRequest,通过解析 ...

  6. 三、使用Maven构建简单的java项目

    前边,我刚搭建了Maven环境,还有给大家推荐了学习资源,这个小节,我们来就来,,简单的玩玩maven. 1.所需工具: 1.Eclipse     2.apache-maven-3.3.9   3. ...

  7. java实现简单web服务器(分析+源代码)

    在日常的开发中,我们用过很多开源的web服务器,例如tomcat.apache等等.现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器.为了简 ...

  8. 基于 Java NIO 实现简单的 HTTP 服务器

    1.简介 本文是上一篇文章实践篇,在上一篇文章中,我分析了选择器 Selector 的原理.本篇文章,我们来说说 Selector 的应用,如标题所示,这里我基于 Java NIO 实现了一个简单的 ...

  9. Ant—使用Ant构建简单Java项目(三)

    博客<Ant-使用Ant构建简单Java项目(二)>我们简化了运行Test类中main方法须要运行的命令,本博客来介绍一下如何使build.xml文件和当中使用property标签定义的属 ...

随机推荐

  1. 翻书shader

    //把下面的shader挂载到plane上,调节_Angle Shader "Unlit/PageTurning"{ Properties { _Color ("Colo ...

  2. mac下php配置

    打开/关闭服务 sudo apachectl start sudo apachectl stop 查看apche版本 apacectl -v 修改项目默认路径: 打开配置文件目录/private/et ...

  3. JavaSE面试题:类初始化和实例初始化等

    类初始化过程 1.一个类要创建实例需要先加载并初始化该类 main方法所在的类需要先加载和初始化 2.一个子类要初始化需要先初始化父类 3.一个类初始化就是执行<clinit>()方法 & ...

  4. c++项目经验分享

    1.C++的const比C语言#define更好的原因? 首先,它能够明确指定类型,有类型检查功能. 其次,可以使用C++的作用域规则将定义限制在特定的函数[常函数]或文件中. 第三,可以将const ...

  5. OracleVM桥接网卡无法获取本地连接网卡

    问题现象 VM虚拟机采用桥接网卡时,界面名称为"未指定",无法获取本地连接对应网卡信息: 处理方式: 进入本地连接,选择本地连接右键进入属性设置窗口; 选择安装,单击服务选项后点击 ...

  6. jQuery格式化显示json数据

    一.概述 JSONView 在gitlab上面,有一个jQuery JSONView插件,地址为:https://github.com/yesmeck/jquery-jsonview demo地址:h ...

  7. 关于使用KubeSphere中的docker配置Harbor仓库http访问docker login登陆报错的解决办法

    # 先进入harbor目录中,停止harbor docker-compose stop # 然后修改docker相关文件 # 第一种方式:修改/etc/docker/daemon.json { &qu ...

  8. 2019 盛趣游戏java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.盛趣游戏等公司offer,岗位是Java后端开发,因为发展原因最终选择去了盛趣游戏,入职一年时间了,也成为了面 ...

  9. P1018 乘积最大(DP)

    题目 P1018 乘积最大 解析 区间DP 设\(f[i][j]\)表示选\(i\)个数,插入\(j\)个乘号时的最大值 设\(num[i][j]\)是\(s[i,j]\)里的数字 转移方程就是\(f ...

  10. js删除对象里的某一个属性

    var a={"id":1,"name":"danlis"}; //添加属性 a.age=18; console.log(a); //结果: ...