Java 内置Http Server构建web应用案例详解

一、概述

使用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服务器,毕竟它们久经考验,能满足所有功能需求,并且出问题的几率低。 

到此这篇关于Java 内置Http Server构建web应用案例详解的文章就介绍到这了,更多相关Java 内置Http Server构建web应用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java修改eclipse中web项目的server部署路径问题

    和MyEclipse不一样,在Eclipse中做的Web项目默认是不支持将项目发布到Web服务器上的,会发布到工作空间的某个目录,因此无法在外部启动Tomcat来运行Web项目,只有打开Eclipse中的服务器,才能运行Web项目.所以要对Eclipse进行修改,才能将做好的项目,发布到Tomcat服务器上,发布到服务器上的Webapps文件夹下. 在Eclipse中,默认会把Web项目放到Eclipse的工作空间下的.metadata\.plugins\org.eclipse.wst.serv

  • JavaWeb入门:HttpResponse和HttpRequest详解

    目录 HttpResponse 讲解 HttpServletResponse概述: Response运行流程 设置响应行 设置响应头 一个小demo 实现刷新 页面累加 设置字符编码 解决中文乱码问题 重定向 redirect request转发 重定向和转发的区别 文件下载 HttpRequest 讲解 HttpServletRequest概述 Request 运行流程 获取请求携带的参数 获取多个参数的值 获得请求行的信息 request实现转发 request是一个域对象 ServletC

  • Java设计模式之观察者模式(Observer模式)

    一.观察者模式是什么? 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern).当一个对象被修改时,则会自动通知依赖它的对象.观察者模式属于行为型模式. 人话: 就像微信公众号推送消息,订阅的人能收到,没订阅的收不到,还可以取消/添加订阅 二.模式分析 2.1 四个角色 抽象主题(抽象被观察者角色):也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者.抽象主题提供一个接口,可以增加和删除观察者角色.一般用一个抽象类和接口来实现

  • Java网络通信中ServerSocket的设计优化方案

    前言:在java的网络通信中,两个不同节点的主机想要进行通信则可以通过建立Socket对象(相当于客户端主机,向服务端请求发送信息)和ServerSocket对象(相当于服务端主机,接收客户端的连接请求并回复信息)实现. 1:创建一个Socket对象 Socket socket = new Socket("IP",port); 指定将要连接的服务端的ip地址和端口号来创建一个Socket对象,在创建结束之后便可对其进行输出.输入操作. 2:创建一个ServerSocket对象 Serv

  • Java使用httpRequest+Jsoup爬取红蓝球号码

    目录 1.Jsoup介绍 1.1.简介 1.2.Jsoup的主要功能 2.源网站及页面元素分析 2.1.号码源 2.2.dom元素分析 3.代码实现 1.Jsoup介绍 1.1.简介 jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据. 1.2.Jsoup的主要功能 1.从一个URL,文件或字符串中解析HTML 2.使用DOM或CSS选择器来查找.取出数据 3

  • Java通过SSLEngine与NIO实现HTTPS访问的操作方法

    目录 一.连接服务器之前先初始化SSLContext并设置证书相关的操作. 1.1 基于公钥CA 1.2 加载Java KeyStore 二.连接服务器成功后,需要创建SSLEngine对象,并进行相关设置与握手处理. 三.进行握手操作 3.1 握手相关状态(来自getHandshakeStatus方法) 3.2处理握手的方法 四.数据的发送与接收 4.1加密操作(SelectionKey.OP_WRITE) 4.2 解密操作(SelectionKey.OP_READ) Java使用NIO进行H

  • Java 内置Http Server构建web应用案例详解

    一.概述 使用Java技术构建Web应用时, 我们通常离不开tomcat和jetty之类的servlet容器,这些Web服务器功能强大,性能强劲,深受欢迎,是运行大型Web应用的必备神器. 虽然Java的设计初衷就是用来开发大型应用的,然而有时候我们开发的程序只是简单的小型应用,对于功能的需求和性能的要求并不高, 可能仅仅就几百行甚至几十行代码,这个时候使用tomcat之类的Web服务器去运行就显得有点大材小用了. 比如说只是将数据库中的数据读出来转换成JSON,以Web服务的形式吐给调用方这样

  • Vue3 构建 Web Components使用详解

    目录 引言 构建 Web Components 属性 事件 插槽 子组件样式问题 方法 总结 引言 有时候想写一个无关框架组件,又不想用原生或者 Jquery 那套去写,而且还要避免样式冲突,用 Web Components 去做刚觉就挺合适的.但是现在 Web Components 使用起来还是不够灵活,很多地方还是不太方便的,如果能和 MVVM 搭配使用就好了. 早在之前 Angular 就支持将组件构建成 Web Components,Vue3 3.2+ 开始终于支持将组建构建成 Web

  • Python内置函数zip map filter的使用详解

    并行遍历zip zip会取得一个或多个序理为参数,然后返回元组的列表,将这些序列中的并排的元素配成对. L1=[1,2,3,4] L2=[5,6,7,8] L3=zip(L1,L2) print(L3,type(L3)) <zip object at 0x7feb81b17f08> <class 'zip'> zip在python3中是一个可迭代对象,我们可以将其包含在list调用中以例一次性显示所有结果 list(L3) [(1, 5), (2, 6), (3, 7), (4,

  • Java 处理高并发负载类优化方法案例详解

    java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF.尤其是Web2.0的应用,数据库的响应是首先要解决的. 一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降.常用的优化措施是M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作.我推荐的是M-M-Slaves

  • Js类的构建与继承案例详解

    JS里类的定义和继承实在五花八门,所以单独开一个笔记本记录. 定义 派生于Object的方式 1.new Object:在创建对象后动态定义属性.方法 var Car = new Object; Car.color = "red"; Car.showColor = function(){ console.log(this.color); } //想要继承就要先构造空对象然后用__proto__原型链来继承 var Car1 = new Object; //或者 = {} Car1.__

  • SQL Server批量插入数据案例详解

    在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters),高效插入数据. 新建数据库: --Create DataBase create database BulkTestDB; go use BulkTestDB; go --Create Table Create tab

  • Java list与set中contains()方法效率案例详解

    list.contains(o) :遍历集合所有元素,用每个元素和传入的元素进行 equals 比较,如果集合元素有 n 个,则会比较 n 次,所以时间复杂度为 O(n) .方法源码如下: // ArrayList 中的方法 public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size;

  • Java ThreadLocal原理解析以及应用场景分析案例详解

    目录 ThreadLocal的定义 ThreadLocal的应用场景 ThreadLocal的demo TheadLocal的源码解析 ThreadLocal的set方法 ThreadLocal的get方法 ThreadLocalMap的结构 ThreadLocalMap的set方法 ThreadLocalMap的getEntry方法 ThreadLocal的内存泄露 如何避免内存泄露呢 应用实例 实际应用二 总结 ThreadLocal的定义 JDK对ThreadLocal的定义如下: The

  • Java解析XML(4种方式)案例详解

    目录 1.DOM方式 2.SAX方式 3.JDOM方式 4.DOM4J方式 总结 xml文件 <?xml version="1.0" encoding="utf-8" ?> <class> <student> <firstname>cxx1</firstname> <lastname>Bob1</lastname> <nickname>stars1</nicknam

  • Java基于装饰者模式实现的染色馒头案例详解

    本文实例讲述了Java基于装饰者模式实现的染色馒头案例.分享给大家供大家参考,具体如下: 一.模式定义 装饰者模式,是在不改变原类文件和使用继承的情况下,动态扩展一个对象功能,它是通过创建一个包装对象,也就是装饰来包装真实的对象. 装饰对象和真实对象有相同接口,这样客户端对象就可以和真实对象相同方式和装饰对象交互. 装饰对象包含一个真实对象的引用. 二.模式举例 1. 模式分析 我们借用黑心商贩制做染色馒头案例说明这一模式. 2. 装饰者模式静态类图 3. 代码示例 3.1 创建馒头接口--IB

随机推荐