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应用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!