Android下运行Tomcat、Jetty等Java Web服务器
2019年05月29日


方案一:在android下搭建linux运行环境,然后在linux下运行java web服务器。

方案二:将tomcat或jetty等java web服务器的源码改造,并将class文件转译成android能直接运行的dex格式文件(运行在Dalvik VM上)。


注意,方案二,自己去改造服务器源码,对于一般人显然不现实,但是jetty官方提供了一个叫“i-jetty”的项目,

可以直接在android下运行jetty服务器,然后安装dex转码过的war包。


本文目前主要对方案二进行讲解。


    方案二,有一个很大的缺点,虽然class文件可以转换成dex格式文件运行,而且java反射也可以使用

(因为android下为了使dex能运行,它重写了System ClassLoader,名字叫dalvik.system.DexClassLoader和PathClassLoader),

    但是,java classpath失效了,因为Dalvik VM根本不使用class。而且class打包成dex文件时,不会把classpath下面的资源文件也打包到dev文件中。

    所以,整个System ClassLoader无法获取任何class文件和资源文件。

    如果你的程序或者程序依赖的类库jar包中的代码,有用到classpath及资源文件加载的地方,都会失效,必须得重写这些代码的实现方式。


    举个例子,你把spring的application.properties文件放在classpath下面,肯定是无法使用的,甚至spring框架所依赖的Bean初始化,它会去classpath下面寻找配置的package下面的所有class文件,然后加载class文件中并读取里面的注解等,由于没有class了,所有它找不到class文件,而读取Android的dex文件需要特殊的实现,Spring等几乎所有的传统java框架或库,都没有这个功能。

    附:Spring扫描package下class文件的源码如下:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    try {
    String packageSearchPath = "classpath*:" + 
        resolveBasePackage(basePackage) + "/**/*.class";
    Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    for (Resource resource : resources) {
        logger.trace("Scanning " + resource);
    ...
}
// 代码来源:
// org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

    附:AndroidClassLoader源码解析,描述了从dex文件中查找资源的过程,涉及核心源码包括BaseDexClassLoader,DexPathList,DexFile

参见:https://blog.csdn.net/qq_15274383/article/details/73306332


    值得一提的是,dex文件,是一个纯二进制文件,通常只包含class转换过的内容。你可以把dex文件当做一个map,可以通过标准的class name(比如com.zollty.test.Hello)来读取其二进制内容(类似于字节码),但是你不能通过package去寻找某个package下面有哪些类(它和传统的压缩包不同,传统的压缩包,比如zip,可以通过斜杆(/)分割的路径寻找里面的子文件,但是dex文件貌似不行)。我想从 dex文件查询  com.zollty 包下面的所有类,但是找不到方法。


    另外,注意,i-jetty 这个项目,官方没有怎么维护,实际使用起来问题很多,我也是花了整整2天时间,把i-jetty的源码,以及Android各个版本DexClassloader相关的源码,都分析阅读了之后,才把项目弄好。

    我重写了i-jetty的AndroidClassLoder,让它可以读取jar包中的资源文件同时配合 maven  ant plugin自定义打包,将必要的java class和资源文件打包到 i-jetty的lib jar包中同时配合我专用的zollty-mvc框架(能替代SpringMVC的绝大多数常用功能),以及android下专用的jdbc驱动,才把一个完整的项目跑起来,这里面的每个环节都不能少。


    源码已传到GitHub上:https://github.com/zollty/i-jetty

    如果不想直接写原生Servlet,强烈推荐配合“超轻量级MVC框架-ZolltyMVC”使用:https://github.com/zollty-org/zollty-mvc

    ZolltyMVC的代码量连SpringMVC的1%不到,但是却具备SpringMVC的80%常用功能。