- Java RESTful Web Service实战
- 韩陆
- 2641字
- 2023-07-14 20:49:20
2.2 第一个Servlet容器服务
上一节讲述的REST服务是基于Java SE环境的,本节将介绍Java EE环境下的REST服务,即REST式的Web服务。接下来介绍基于Servlet环境的Jersey官方示例simple-service-webapp,并演示这个Web服务如何在Maven插件、Servlet容器和Java EE容器中运行该示例。
阅读指南
2.2节示例所在目录是jax-rs2-guide\sample\2\0simple-service-webapp-jetty。
源代码地址:https://github.com/feuyeux/jax-rs2-guide/tree/master/sample/2/0simple-service-webapp-jetty。
2.2.1 创建和分析Web服务
simple-service-webapp项目也是Jersey提供的官方文档中的例子,同样是一个Maven原型。在控制台执行如下命令来生成Maven原型项目simple-service-webapp,项目的目标存储路径由读者自行选择。执行生成的命令如下所示:
mvn archetype:generate-DarchetypeArtifactId=jersey-quickstart-webapp-DarchetypeGroupId=org.glassfish.jersey.archetypes-DinteractiveMode=false-DgroupId=com.example-DartifactId=simple-service-webapp-Dpackage=com.example-DarchetypeVersion=2.9
获取源代码后,通过“tree/f”命令纵览simple-service-webapp项目,如图2-3所示。对比simple-service项目可以发现,这个Servlet容器内的版本没有用于服务器处理的入口类,多出来Web工程中两个典型的文件index.jsp和web.xml。下面通过分析文件来了解Web RESTful服务。
图2-3 simple-service-webapp项目源代码组织结构
1.Servlet依赖
如图2-3所示,位于项目的根目录下的pom.xml文件是Maven项目的配置文件。在pom.xml文件中,示例默认使用的是支持向下兼容Servlet 2.x的包jersey-container-servlet-core。如果读者需要使用Servlet 3版本,那么应当首先修改这个配置,再进行编译、测试和调试。关于Servlet容器的依赖包说明,见1.4节的详述。pom.xml中的相关配置如下所示。
<!--servlet 2.x--> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> </dependency> <!--servlet 3.x--> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> </dependency>
2.资源类分析
使用读者熟悉的编辑器打开这个资源文件,这里以文本编辑器为例,示例如下。
notepad src\main\java\com\example\MyResource.java
从该类的实现中可以发现,REST的资源类的定义在Java SE环境和Servlet容器内是一样的。由此可以理解,REST服务的资源路径是由服务器路径和资源的相对路径组成。一个项目的相对路径是固定的,因此资源类及其子资源类的定义并不关心所处的容器环境,即服务器路径,而只关心其相对的资源路径。
3.Web服务首页分析
index.jsp是该示例的首页,需要指出的是该示例其实是一个纯HTML实现,虽然扩展名是jsp,但其实现中并无JSP脚本。使用文本编辑器打开index.jsp文件:notepad src\main\webapp\index.jsp,示例如下。
<html> <body> <h2>Jersey RESTful Web Application!</h2> // 关注点1:资源路径链接 <p><a href="webapi/myresource">Jersey resource</a> <p>Visit <a href="http://jersey.java.net">Project Jersey Website</a> for more information on Jersey! </body> </html>
在这个简单的首页文件中,关键的一行是指向webapi/myresource这个资源路径的链接,见关注点1。当用户单击这个链接时,浏览器发起GET请求,资源路径为webapi/myresource,流程进入资源类MyResource的getIt()方法。
4.Web服务配置
配置文件web.xml中定义了Web服务的信息。使用文本编辑器打开web.xml文件:
notepad src\main\webapp\WEB-INF\web.xml
该文件可以分成3块进行阅读,示例如下。
第一块:定义Servlet版本。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/Java EE" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/Java EE http://java.sun.com/ xml/ns/Java EE/web-app_2_5.xsd">
在这段代码中,列出了对Servlet版本的定义,本示例默认使用的版本是2.5。需要说明的是,如果使用Servlet 3.0,那么web.xml文件并不是必要的,我们将在本章稍后详述。
第二块:定义Servlet。
<servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.example</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
在这段代码中,对Servlet进行了定义,包括servlet-name、servlet-class和init-param。对于2.5版本,servlet-class是不可或缺的。初始化参数指定了加载服务时要扫描的包名,这里定义的是com.example包。
第三块:定义servlet-mapping,即Servlet的作用域。
<servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping>
在这段代码中,列出了servlet-mapping的定义,将上述定义的Servlet的作用域匹配到/webapi/*的路径上。
在分析了simple-service-webapp项目的内容后,我们来测试这个Servlet项目在容器内的运行情况。在接下来的3个小节中,我们将simple-service-webapp项目分别运行在三种不同的容器环境中,为不同需求的读者提供参考,分别是Maven插件Jetty、Servlet容器Tomcat和Jave EE容器GlassFish。
2.2.2 Jetty插件与REST服务
首先,我们使用Maven+Jetty这种经典组合来运行REST服务,即通过执行Maven命令启动用于测试REST服务的Servlet容器Jetty插件。图2-4展示了Maven的生命周期,结合启动和停止Jetty的配置文件,读者可以清楚地了解Jetty插件在Maven工程的生命周期中所处的位置。
图2-4 Maven生命周期示意图
在Maven生命周期的每个阶段中,如果失败,则流程结束于该阶段,否则执行至Maven命令中定义的阶段,并成功结束。例如,执行了如下命令。
mvn clean install
如果成功执行至install阶段,流程将在install结束后,成功结束,不再执行后面的deploy。如果在中间某个阶段失败,比如在test阶段失败,那么流程结束于test,后面的package等阶段将不会再执行。
小白讲堂
如果读者对Maven的生命周期的各个阶段的含义并不了解,那么建议阅读许晓斌所著的《Maven实战》(机械工业出版社出版)。
1.插件配置
在图2-4中,integration-test阶段的前后各有一个扩展点pre和post,Jetty插件就是在这两个点启动和停止内置的Jetty服务器的。插件配置(这是Jetty插件早期的配置,接下来会说明)如下。
<plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.26</version> <executions> <execution> <id>start-jetty</id> // 关注点1:在Maven的pre-integration-test生命周期执行run <phase>pre-integration-test</phase> <goals> <goal>run</goal> </goals> </execution> <execution> <id>stop-jetty</id> // 关注点2:在Maven的post-integration-test生命周期执行stop <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin>
Jetty的运行发生在pre-integration-test阶段,见关注点1;Jetty的结束发生在post-integration-test阶段,见关注点2。
读者在使用Jetty插件时,应注意该插件的版本信息。从Jetty 7开始,Jetty的Maven插件更改了命名方式以适应Maven插件的统一命名规则,相应的配置文件如下。
<plugin> <groupId>org.eclipse.jetty</groupId> // 关注点1:Jetty插件artifactId命名 <artifactId>jetty-maven-plugin</artifactId> <version>9.1.0.RC0</version> <executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>start</goal> </goals> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin>
从关注点1可以看到,Jetty插件的名称从老版本的maven-jetty-plugin改为jetty-maven-plugin。
2.运行插件
可以进入命令行,在项目根目录下执行如下命令,或者在IDE中配置Maven使用如下命令启动:
mvn jetty:run
Jetty服务器启动后,若要终止当前测试用的Jetty服务器,在命令行可以执行<Ctrl+C>操作,在IDE中可以停止Maven服务的运行。
Jetty服务器启动后,打开浏览器,输入地址:http://localhost:8080/simple-service-webapp,访问Web服务首页,如图2-5所示。
图2-5 simple-service-webapp首页
在图2-5中有上下两个链接,上面的链接就是本示例Web服务的资源地址:http://localhost:8080/simple-service-webapp/webapi/myresource,单击该链接会得到资源类GET对应方法,该方法返回的字符串信息是“Got it!”。本示例的WADL地址是http://localhost:8080/simple-service-webapp/webapi/application.wadl,关于WADL的详细信息,参见2.4节。
2.2.3 运行在Servlet容器
Jetty插件多用于Web服务的调试和集成测试,在该阶段通过以后,通常会将该项目部署到以Tomcat为代表的Servlet容器来搭建测试环境和运行环境。Tomcat的安装、配置和部署实现步骤如下。
1)从Tomcat的官方网址http://tomcat.apache.org下载Tomcat,并解压缩到D盘根目录。注意,读者可以自行选择下载版本和本地存储路径。本例使用的是Tomcat 7.0.42,解压缩后的目录为:D:\apache-tomcat-7.0.42。
2)使用Maven命令编译打包(clean是清除target目录,package是打包,-D是为Maven命令设置运行时参数,skipTests参数是忽略测试生命周期)。
mvn clean package –D skipTests=true
3)复制WAR包到Tomcat应用目录。
cp target\simple-service-webapp.war D:\apache-tomcat-7.0.42\webapps\simple-service.war
4)运行Tomcat服务器。若要结束运行Tomcat服务器,则可以按<Ctrl+C>组合键。
cd D:\apache-tomcat-7.0.42\bin catalina.bat run
5)打开浏览器,输入地址:http://localhost:8080/simple-service-webapp访问Web服务首页。
其他Servlet容器的部署和运行类似Tomcat,可参考相关容器的文档,这里不再列举。
2.2.4 运行在Java EE容器
同时,Web服务可以部署到以GlassFish为代表的Java EE容器来搭建运行环境。GlassFish的安装、配置和部署实现步骤如下。
1)GlassFish的官方网址是https://glassfish.java.net,读者可以自行选择下载版本。本例使用的是GlassFish 4.0,解压缩后的目录为:D:\glassfish4。下载地址参考如下:
http://dlc.sun.com.edgesuite.net/glassfish/4.0/release/glassfish-4.0.zip。
2)使用Maven命令编译打包,如下所示:
mvn clean package –D skipTests=true
3)复制WAR包到GlassFish默认domain目录。
cp target\simple-service-webapp.war D:\glassfish4\glassfish\domains\domain1\autodeploy\simple-service.war
4)运行GlassFish服务器。
cd D:\glassfish4\bin asadmin start-domain
5)打开浏览器,输入http://localhost:4848进入GlassFish的管理界面,如图2-6所示。
图2-6 GlassFish管理界面
在图2-6中,REST服务出现在GlassFish管理界面的应用列表中。单击“Launch”启动应用,页面自动跳转到“http://主机名:8080/simple-service”页面。
其他Jave EE容器的配置和部署类似GlassFish,可参考相关容器的文档。
到此,读者已经掌握了开发基于JAX-RS 2.0的Java SE应用和REST式Web服务的基本方法。接下来的一节将讲述如何实现和部署不同形式的JAX-RS 2.0服务,通过这一节的知识介绍,读者将掌握灵活实现一个REST式Web服务的技能。