Gradle提供了开箱即用的插件,用来组装WAR文件和将web应用部署到本地Servlet容器中。Gradle对构建和运行web应用都提供了扩展性支持。这里我们学习使用两个web应用程序部署插件:War和Jetty。War插件扩展自Java插件,为web应用部署和组装War包添加了约定和支持。Jetty是一个流行的轻量级开源web容器,它通过将一个HTTP模块添加到应用中来提供一个嵌入式实现。Gradle的Jetty插件扩展了War插件,为部署一个web应用到嵌入式容器和运行web应用提供了对应的任务。
War插件
我们之前提到过War插件扩展自Java插件。实际上,这意味着你不需要在构建脚本中应用Java插件。它会自动由War插件引入。不过即便你也应用了Java插件,这也不会对你的项目带来其他影响。应用插件是一个幂等操作,因为某一个指定的插件只会执行一次。当创建build.gradle文件中,使用插件只需要像这样:
apply plugin: 'war'
web应用默认约定的源代码目录是 src/main/webapp 。
另外,实现web应用所需要的类不可能完全是java标准api,很多可能是第三方库里的api。在运行构建之前,你需要确保声明了外部依赖。War插件引入了两个新的依赖配置项。例如,Servlet依赖使用到的配置项是 providedCompile。它表示该依赖在编译时需要,但是运行时由环境提供。这里的运行时环境是Jetty,tomcat这样的Servlet容器。结果就是,被标记为providedCompile的依赖不会打包到WAR文件中。像JSTL库这样的依赖,在编译时不需要,但是运行时需要。它就要声明为runtime,它就会成为WAR文件的一部分。示例:
dependencies { providedCompile 'javax.servlet.servlet-api:2.5' runtime 'javax.servlet:jstl:1.1.2' }
构建项目
在Gradle中构建一个web应用就和构建一个独立运行的Java应用程序一样。运行:
$ gradle build
命令后,组装的WAR文件可以在 build/libs 目录下找到。
War插件确保组装的WAR文件遵循由Java EE规范定义的标准结构。war任务将web应用源代码目录 src/main/webapp 的内容原封不动地拷贝到WAR文件的根目录。编译的class文件最终会放置在 WEB-INF/classes 下,通过依赖闭包定义的运行时类库会放置在 WEB-INF/lib 下。注:默认情况下,WAR文件的名字会继承自项目的目录名字。
定制War插件
即便你的项目没有遵循Gradle的标准约定,该插件也依然可以构建WAR文件。假设所有的静态文件都放置在static目录下(例如:css,js,jmg),而且所有web应用的内容都放置在webfiles目录下(如:jsp,web.xml)。
下面的代码片段显示了如何配置约定属性。War插件暴露了 webAppDirName 约定属性,默认值是 src/main/webapp,重新赋值就可以轻松地切换到webfiles。通过触发from方法就可以有选择性地将需要的目录添加到WAR文件中,如下:
webAppDirName = "webfiles' //改变web应用的源代码目录 war { from 'static' //将静态资源文件的目录(js目录,css目录等)添加到WAR文件的根目录 }
之前的例子仅仅显示了War插件配置选项的一部分。如果你要找某个配置参数,那么查看War插件的DSL指南是第一选择。
在嵌入式web容器中运行
现在我们来将文件部署到Servlet容器(Jetty)中。因为War插件暴露了所有的信息,Jetty插件可以在运行时访问它们。这是Gradle中一个典型的例子,通过Gradle的API,一个插件可以访问另一个插件的配置。在你的构建脚本中,像这样使用插件:
apply plugin: 'jetty'
运行web应用使用的任务是 jettyRun 。即使没有WAR文件,它也会启动Jetty容器:
$ gradle jettyRun
在输出结果的最后一行,插件告诉你Jetty所监听的请求URL。Gradle会一直让应用程序运行,直接你按“Ctrl + C”键。Jetty是如何知道在什么端口和上下文中运行应用的呢?还是约定。Jetty插件运行一个web应用的默认端口是 8080 。上下文路径 abc 是从项目名字继承的。当然,这些都是可配置的。
注:每次改变项目代码都需要重新启动容器是非常麻烦和耗时的。Jetty插件允许你在不重启容器的情况下,改变静态资源和JSP文件。另外,还针对class文件的改变配置像Jrebel这样的字节码交换技术来执行热部署。
定制Jetty插件
假设你不满意Jetty插件提供的默认值。比如,已经有一个应用使用了8080端口,而且你也讨厌输入那么长的上下文路径。下面的配置可以解决你的问题 :
jettyRun { httpPort = 9090 contextPath = 'a' }
用这个配置启动应用,将暴露:http://localhost:9090/a 。Jetty插件还提供了更多的配置选项,查看插件的API文档是最好的选择。