Jetty系列: 01- 基本使用和简单介绍
2017-11-15 14:57
555 查看
为什么要写这个系列
故事的开头要从博主两年前做的一个需求开始. 当时我在公司的Android项目组做开发, app要加一个免流量分享应用的功能. 应用场景是这样: 我手机上装了一个app, 现在要传给你, 不耗费双方的上网流量. 怎么做呢? 过程是这样:我在手机上开一个WiFi热点, app内部起一个web服务, 把web服务的地址生成二维码.
你扫这个二维码, 得到一个网址, 如:http://192.168.x.xx:8080/
你在手机浏览器里打开这个网址, 看到的是一个介绍页面, 点击一个免流量下载按钮, 访问链接是:http://192.168.x.xx:8080/download
我这边app内部的web服务器将apk文件通过http发送给你, 对你来说, 跟平时在网页上下载是一样的, 下载完成后, 直接安装. 整个过程不访问外网, 所有通信都通过我的WiFi热点完成, 达到免流量的目的.
当时从技术上来拆分, 主要有以下三点:
WiFi热点的控制 -> 通过系统api调用可以轻松完成
二维码生成 -> 通过zxing库可以做到
在手机里起web服务 -> 看起来有点麻烦
http这一块Android的客户端支持是很完善的, 像apache的HttpClient, java自带的UrlConnection都可以用, 但对于服务器这一块, 还真没接触过, 毕竟 像Tomcat, nginx这种web服务器一般来说都部署在专用服务器主机上的. 这该咋办呢?
基于当时的认知情况, 博主采用了一种最原始的方法: 基于Java的原生socket, 手动写一个简单的web服务器. 大体实现如下:
1.绑定tcp socket到8080端口, 接受连接请求
2. 收到连接请求后, 读取客户端发来的数据
3. 按行解析这些数据, 分析Request-Line, 得到访问的路径, 如果是”/”, 则读取index.html文件, 写入连接socket. 当然了, 在写文件数据前, 需要按照http规范发送Response-Header, 像Content-Length, Content-Type这些字段; 如果是”/download”, 则按照文件的格式发送Response-Header, 跟上apk文件的数据; 其他路径就直接返回404错误.
最后按这种方式实现了目标功能. 但是一眼看来这样实现是有缺点的, 稍微复杂一点的功能都要手动在这个基础上添加, 而很多功能其实都是在HTTP规范里面定义好的, 只要是一个规范的http服务器, 都会实现这些功能, 手动写服务器其实是重复造轮子的动作. 当时在想, 要是有一个可以方便嵌入到手机的web服务器该多好啊!
后来, 由于博主的兴趣在服务端, 正好公司有这个契机, 我就转去做服务器了. Android端也有一部分工作, 主要是给业务团队提供SDK, 封装一部分JNI.
又过了一段时间, 博主遇到一个需求, 手机客户端的日志, 存储到后台做分析. 这里又遇到http服务器了, 当然这次运行的目标机器是服务器, 可选择的就很多了, 当时的决策如下:
nginx - 一般用来做负载均衡, 或者处理一些静态请求, 如果要做业务处理的话, 需要写C来扩展, 不是很方便.
Tomcat - 能完成需求, 但是太重了. 跟当时的app需求一样, 我只要轻量的http功能, 最好是集成到应用代码里的
nginx+php, 可以实现, 不过在接受完http请求后, 还需要和其他java组件做交互, 这点不是很方便; 其次, 博主对php不熟悉.
Jetty, 当时查了一些资料后发现了它, 可以内嵌到应用内部, 并且性能也不错, 于是决定就它了.
Netty, 高性能的java异步IO框架. 说实话当时博主以为Jetty的底层用的就是Netty框架呢, 而且当时看到Jetty的http服务器的例子就几行代码(后面可以看到), 就决定用了.
有的同学一定会疑问怎么没使用Netty呢, 至少我身边的人对Netty提到的机会比jetty是高很多的. 老实说, 如果当时没有误以为Jetty底层就是Netty的话, 我当时可能会考虑使用Netty来做开发. 不过到现在这个时候来说, 我觉得一点也不后悔. 主要有以下几点:
Jetty的上手代码非常简洁, 好用的东西就是要用起来方便直接的; Netty的例子代码也不多, 但是会看到很多陌生的概念, Future, Channel等, 对博主来说, 除非对一个东西对原理了解透彻, 不然基本是不会放心用的. 而Netty的这些概念对当是的博主造成了一定的思想压力.
最近仔细看了Jetty的部分实现代码, 结构还是非常清晰的. Netty非常好, Jetty也不错, 所有的功能无非都是基于原始的操作系统Socket和线程概念组合起来的, 不一定非要用最好的, 了解你所用的组件, 发生问题的时候快速定位找到问题, 才是最重要的.
说了这么多, 其实是因为博主和大多数工程师一样, 都有些强迫症情节, 用东西都追求最好的, 性能要最高的. 这在很多时候其实是不好的, 高性能的东西, 可能用起来不顺手, 或者开发和部署需要比较多的时间, 或者发挥高性能的前提是要对它有足够的认知. 作为工程师的天职, 是为解决生活中的问题而存在的. 一味地追求高端, 只会迷失在茫茫多的组件当中. 而从这么多功能相近的组件同时存在也可以看出, 每个组件都有自己的立足之地, 一定是因为它很好的满足了一部分人的需求. 选择合适自己的, 了解它, 改进它!!!
Jetty简单介绍
Jetty是Eclipse基金会下面的一个开源项目, 是一个Web服务器和Servlet容器, 同时支持HTTP/2, WebSocket, OSGi, JMX, JNDI, JAAS功能. Jetty可以作为web服务器非常容易的嵌入到应用代码中, 包括Android的app.Jetty除了嵌入到应用代码中外, 也可以像Tomcat那样独立运行, 通过部署WAR包的方式提供服务. 理论上来说, Tomcat下面运行的WAR包可以直接在Jetty下运行, 这一点我没有验证过. 有需要的同学可以自行验证. 接下来的博客中主要介绍嵌入运行方式.
接下来通过一个简单的例子来看看Jetty是如何开发的.
package com.lqp.test; import org.apache.logging.log4j.LogManager; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ResourceHandler; public class TestJettyServer { public static void main(String[] args) { Server server = new Server(8080); ResourceHandler resource_handler = new ResourceHandler(); resource_handler.setDirectoriesListed(true); ContextHandler resHanler = new ContextHandler(); resHanler.setHandler(resource_handler); resHanler.setResourceBase("."); resHanler.setContextPath("/"); server.setHandler(resHanler); try { server.start(); } catch (Exception e) { LogManager.getLogger().catching(e); } } }
启动一个JettyWeb服务器就是这么简单. 启动后, 就可以在浏览器里浏览和查看当前目录下的文件了. 效果如下图:
Handler是Jetty服务器的业务功能实现地, 如果要扩展web服务器的功能, 只需要添加自己实现的handler就行, 还是很容易理解的.
如何引用jetty的jar包
下载jar包, 添加jar引用, 这里是下载地址Maven依赖引用, 推荐这种方式.
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.4.2.v20170220</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>9.4.2.v20170220</version> </dependency>
后面的系列中, 主要围绕9.4.2.v20170220版本的代码来做分析.
相关文章推荐
- RxJava系列2(基本概念及使用介绍)
- [Android]RxJava的简单介绍和基本使用(一)
- 简单介绍STM32F3系列单片机中片内运算放大器的使用——以STM32F303DISCOVERY板为例
- CAShapeLayer的简单介绍以及基本使用
- 图片加载框架简单介绍<一> ImageLoader 的基本使用
- 使用react-native做一个简单的应用-01项目介绍
- 图片加载框架简单介绍<三> Glide的基本使用
- webstorm简单介绍,web 4000 strom基本使用
- [Android]RxJava的简单介绍和基本使用(二):retrofit2的简单介绍
- 01.JavaScript介绍和基本使用
- 01_Java基础_数组的定义、基本使用和简单应用
- Android WebView系列文章1-关于WebView基本使用介绍
- 正則表達式基本使用方法简单介绍
- 【scikit-learn】01:使用案例对sklearn库进行简单介绍
- 01 JS基本介绍与使用
- awk基本使用方法简单介绍
- Elasticsearch简单使用系列--详细介绍ES的核心概念
- Retrofit基本介绍和简单的使用方式
- leveldb研究系列一 .leveldb的简单介绍和简单使用