使用Spring 3构建RESTful Web服务

使用表示状态传输(REST)样式体系结构,围绕资源表示的传输构建请求和响应。 资源由通常使用统一资源标识符(URI)的全局ID标识。 客户端应用程序使用HTTP方法(例如GET,POST,PUT或DELETE)来操纵资源或资源集合。 通常,GET方法用于获取或列出资源或资源集合,POST用于创建资源,PUT用于更新或替换,DELETE用于删除资源。

例如, GET http://host/context/employees/12345获取ID为GET http://host/context/employees/12345的员工的表示形式 。响应表示形式可以是包含详细员工信息的XML或ATOM,也可以是JSP / HTML提供更好UI的页面。 您将看到哪种表示形式取决于服务器端实现和客户端请求的MIME类型。

RESTful Web服务是使用HTTP和REST原理实现的Web服务。 通常,RESTful Web服务将定义基本资源URI,其支持的表示/响应MIME类型以及其支持的操作。

在本文中,学习如何使用Spring来构建Java服务器端RESTful Web服务。 该示例将为发出请求的客户端使用浏览器,curl和Firefox插件RESTClient 。 您可以下载本文中使用的源代码。

本文假定您熟悉REST基础。

Spring 3 REST支持

在Spring框架支持REST之前,人们使用其他几种实现(例如Restlet,RestEasy和Jersey)来帮助在Java世界中构建RESTful Web服务。 在组中最重要的泽西岛是JAX-RS(JSR 311)的参考实现。

Spring是一个广泛使用的Java EE框架,在发行版3中增加了对构建RESTful Web服务的支持。尽管REST支持不是JAX-RS的实现,但它具有的功能比规范定义的更多。 REST支持无缝集成到Spring的MVC层中,并且可以由使用Spring构建的应用程序轻松采用。

Spring REST支持的主要功能包括:

  • 注释,例如@RequestMapping@PathVariable ,以支持资源标识和URI映射
  • ContentNegotiatingViewResolver以支持具有不同MIME /内容类型的不同表示形式
  • 通过类似的编程模型无缝集成到原始MVC层中

构建示例RESTful Web服务

本节中的示例将介绍如何设置Spring 3环境并创建可以集成到Tomcat中的“ Hello world”应用程序,然后我们通过一个更复杂的应用程序来介绍Spring 3 REST支持的要点,例如多个MIME。类型表示支持和JAXB支持。代码段帮助说明概念。您可以下载本文的所有示例代码。

Hello World:使用Spring 3 REST支持

要设置示例的开发环境,您需要:

  • 一个IDE:适用于JEE的Eclipse IDE(v3.4 +)
  • Java SE5或以上
  • 一个Web容器:Apache Tomcat 6.0(Jetty和其他容器也可以使用)
  • Spring 3框架(v3.0.3是撰写本文时的最新版本)
  • 其他库:JAXB 2,JSTL,commons-logging

在Eclipse中创建一个动态Web应用程序,并将Tomcat 6设置为其运行时。 然后,您需要设置web.xml文件以启用Spring WebApplicationContext。 该示例将Spring bean配置分发到两个文件中:rest-servlet.xml将处理与MVC / REST相关的配置,rest-context.xml处理服务级配置(例如数据源bean)。 清单1显示了web.xml中的Spring配置代码段。

清单1.在web.xml中启用Spring WebApplicationContext
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
	/WEB-INF/rest-context.xml
</param-value>
</context-param>
	
<!-- This listener will load other application context file in addition to 
            rest-servlet.xml -->
<listener>
<listener-class>
	org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
	
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
	org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>

在rest-servlet.xml文件中设置与Spring MVC相关的配置(Controller,View,View Resolver)。 清单2显示了最重要的代码段。

清单2.在rest-servlet.xml中设置Spring MVC配置
<context:component-scan base-package="dw.spring3.rest.controller" />

<!--To enable @RequestMapping process on type level and method level-->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<!--Use JAXB OXM marshaller to marshall/unmarshall following class-->
<bean id="jaxbMarshaller"
class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
	<list>
	    <value>dw.spring3.rest.bean.Employee</value>
	    <value>dw.spring3.rest.bean.EmployeeList</value>
	</list>
</property>
</bean>

<bean id="employees" class=
	"org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg ref="jaxbMarshaller" />
</bean>

<bean id="viewResolver" class=
"org.springframework.web.servlet.view.BeanNameViewResolver" />

在上面的代码中:

Component-scan
对具有Spring批注的类启用自动扫描
实际上,它用于检测在控制器类中定义的@Controller批注。
DefaultAnnotationHanlderMappingsAnnotationMethodHandlerAdapter
Bean将在要由Spring处理的类或方法上进行@ReqeustMapping批注
下一节将详细讨论该注释。
Jaxb2Mashaller
定义使用JAXB 2进行对象XML映射(OXM)的编组器/解组器
MashallingView
定义一个利用Jaxb2Mashaller的XML表示view
BeanNameViewResolver
使用用户指定的Bean名称定义视图解析器
该示例将使用MarshallingView名称“ employees”。

这样就完成了与Spring相关的配置。 下一步是编写一个处理用户请求的控制器。 清单3显示了控制器类。

清单3. dw.spring3.rest.controller包中的EmployeeController
@Controller
publicclass EmployeeController {
@RequestMapping(method=RequestMethod.GET, value="/employee/{id}")
public ModelAndView getEmployee(@PathVariable String id) {
	Employee e = employeeDS.get(Long.parseLong(id));
	returnnew ModelAndView(XML_VIEW_NAME, "object", e);
}
}

@RequestMapping注释是Spring REST功能的关键。 它指定带注释的方法应处理哪个HTTP方法( RequestMethod.GET )和哪个URI( /employee/{id} )。 注意:

  • 对于{id}占位符,可以使用@PathVariable批注将{}中的值注入到方法参数中。
  • XML_VIEW_NAME等于employees ,这是rest-servlet.xml中定义的视图名称。
  • employeeDS是一个基于内存的简单数据源,其实现不在本文讨论范围之内。

将Web应用程序发布到Tomcat。 此时,您可以打开浏览器并输入http://<host>:<port>/<appcontext>/service/employee/1 。 浏览器应显示ID为1的员工的XML视图。

继续阅读以了解有关Spring REST支持的更多功能。

方法

使用诸如GET,POST,PUT和DELETE之类的HTTP方法来操纵资源。 以前,您学习了如何使用GET方法检索员工信息。 现在,我们将进行POST,PUT和DELETE。

使用@RequestMapping批注的功能,用于处理不同方法的代码非常相似。 清单4显示了EmployeeController类的代码片段。

清单4. dw.spring3.rest.controller中的EmployeeController
@RequestMapping(method=RequestMethod.POST, value="/employee")
public ModelAndView addEmployee(@RequestBody String body) {
	Source source = new StreamSource(new StringReader(body));
	Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
	employeeDS.add(e);
	returnnew ModelAndView(XML_VIEW_NAME, "object", e);
}

@RequestMapping(method=RequestMethod.PUT, value="/employee/{id}")
public ModelAndView updateEmployee(@RequestBody String body) {
	Source source = new StreamSource(new StringReader(body));
	Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
	employeeDS.update(e);
	returnnew ModelAndView(XML_VIEW_NAME, "object", e);
}

@RequestMapping(method=RequestMethod.DELETE, value="/employee/{id}")
public ModelAndView removeEmployee(@PathVariable String id) {
	employeeDS.remove(Long.parseLong(id));
	List<Employee> employees = employeeDS.getAll();
	EmployeeList list = new EmployeeList(employees);
	returnnew ModelAndView(XML_VIEW_NAME, "employees", list);
}

在上面的代码中:

  • RequestMethod.<Method>值标识带注释的方法应处理的HTTP方法。
  • 使用@RequestBody ,可以将HTTP请求的正文内容作为参数注入。

    在示例中,主体是代表员工的XML数据。 我们使用JAXB 2将XML解组到Java bean,然后将其持久化。 样本请求正文可以是:

    <employee><id>3</id><name>guest</name></employee>
  • 可以注入到方法参数中的其他有用的注释是@PathVariable@RequestParm @PathVariable等。 Spring文档提供了注释的完整列表(请参阅参考资料 )。

资源收集

通常,您还需要操纵一组资源。 例如,您可能希望获取所有员工信息,而不是仅获取个人信息。 这可以与先前的情况类似地实现; 您需要更改的只是从/ employee到/ employees的URI。 员工的复数形式适合集合语义。 清单5显示了实现。

清单5. EmployeeController中的getAllEmployees
@RequestMapping(method=RequestMethod.GET, value="/employees")
public ModelAndView getEmployees() {
	List<Employee> employees = employeeDS.getAll();
	EmployeeList list = new EmployeeList(employees);
	returnnew ModelAndView(XML_VIEW_NAME, "employees", list);
}

您需要为Employee集合声明包装器类。 JAXB 2需要包装器类,因为它无法正确编组java.util.List类。 清单6显示了EmployeeList类。

清单6. dw.spring3.rest.bean中的EmployeeList类
@XmlRootElement(name="employees")
publicclass EmployeeList {
	privateint count;
	private List<Employee> employees;

	public EmployeeList() {}
	
	public EmployeeList(List<Employee> employees) {
		this.employees = employees;
		this.count = employees.size();
	}

	publicint getCount() {
		return count;
	}
	publicvoid setCount(int count) {
		this.count = count;
	}
	
	@XmlElement(name="employee")
	public List<Employee> getEmployees() {
		return employees;
	}
	publicvoid setEmployees(List<Employee> employees) {
		this.employees = employees;
	}
	
}

内容协商

REST服务的另一个共同特征是,它们可以根据请求生成不同的表示形式。 例如,如果客户端请求所有员工HTML /文本表示,则服务器应为用户生成格式正确HTML页面。 如果客户端请求员工的应用程序/ XML表示,则服务器应改为生成XML结果。 其他流行的表示类型是ATOM和PDF。

Spring 3引入了一个新的名为ContentNegotiatingViewResolver视图解析器。 它可以根据请求内容类型(请求标头中的Accept属性)或URI后缀切换视图解析器。 以下示例使用ContentNegotiatingViewResolver来实现多表示支持。

在rest-servlet.xml文件中,注释掉已定义的原始viewResolver 。 改为使用ContentNegotiatingViewResolver ,如清单7所示。

清单7.定义内容协商
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
	<map>
	<entry key="xml" value="application/xml"/>
	<entry key="html" value="text/html"/>
	</map>
</property>
<property name="viewResolvers">
	<list>
	<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
	<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<property name="viewClass" value=
		"org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	</list>
</property>
</bean>

该定义显示了对处理两种请求内容类型的支持: application/xmltext/html 。 该代码还定义了两个视图解析器:一个用于处理application / xml的BeanNameViewResolver和一个用于处理text / html的UrlBasedViewResolver

实际上,当您在浏览器中输入http://<host>:<port>/<appcontext>/service/employees时,它会为员工请求text/html 。 然后UrlBasedViewResolver将生效,Spring将选择/WEB-INF/jsp/employees.jsp作为其视图。 当您添加请求标头Accept:application/xml并调用请求时, BeanNameViewResolver将生效。 根据清单5中的代码,它将使用名为employees的视图来表示,这是已定义的JAXB 2 marshaller视图。

getAllEmployees()的控制器代码不会更改。 employee.jsp页面将使用名为employees的模型对象来呈现自身。 清单8显示了employee.jsp的代码片段。

清单8. / WEB-INF / jsp中的employees.jsp
<table border=1>
	<thead><tr>
		<th>ID</th>
		<th>Name</th>
		<th>Email</th>
	</tr></thead>
	<c:forEach var="employee" items="${employees.employees}">
	<tr>
		<td>${employee.id}</td>
		<td>${employee.name}</td>
		<td>${employee.email}</td>
	</tr>
	</c:forEach>
</table>

与REST服务通信的客户端

到目前为止,您已经开发了一个简单的RESTful Web服务,该服务支持员工的CRUD(创建,读取,更新和删除)操作。 本节探讨如何与服务进行通信。 您将使用curl测试REST服务。

您还可以使用名为RESTClient的Firefox插件来测试REST服务。 它易于使用并且具有良好的UI。 请参阅参考资料以获取下载信息。

使用卷曲

Curl是一种流行的命令行工具,可以使用HTTP和HTTPS协议将请求发送到服务器。 这是与RESTful Web服务进行通信的有用工具,因为它可以通过任何HTTP方法发送内容。 Curl是Linux®和Mac®上的内置实用程序。 对于Windows®平台,您可以下载该工具(请参阅参考资料 )。

要初始化将获取所有雇员的第一个curl命令,请输入:

curl –HAccept:application/xml 
http://localhost:8080/rest/service/employees

响应将采用XML格式,并将包含所有员工,如图1所示。

图1.所有员工的XML表示
员工姓名,ID和电子邮件的XML输出

您也可以在浏览器中尝试相同的URL。 在这种情况下,Accept标头指定text / html,因此将显示employee.jsp中定义的表。 图2显示了一个示例。

图2.所有员工HTML表示
与图1相同的数据,但以表格格式

要将新员工过帐到服务器,请使用以下代码。 清单4中addEmployee()代码将使用请求正文并将其解组到Employee对象。

curl -X POST -HContent-type:application/xml --data
"<employee><id>3</id><name>guest</name><email>guest@ibm.com</email></employee>"
http://localhost:8080/rest/service/employee

添加了新员工。 您可以使用第一个示例来验证员工列表。

PUT方法类似于POST。

curl -X PUT -HContent-type:application/xml --data
"<employee><id>3</id><name>guest3</name><email>guest3@ibm.com</email></employee>" 
http://localhost:8080/rest/service/employee/3

上面的代码更新ID为3的员工数据。

摘要

现在,Spring 3在其MVC层中支持REST,您可以使用Spring API和注释来构建RESTful Web服务。 在本文中,示例向您展示了如何使用Spring 3的一些新功能,这些功能将帮助您轻松构建Java服务器端RESTful Web服务。


翻译自: https://www.ibm.com/developerworks/web/library/wa-spring3webserv/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值