使用 Spring 的 REST 支持向应用程序添加 Atom 视图

工程 | Alef Arendsen | 2009 年 3 月 16 日 | ...

在 Spring 3.0 中,Spring MVC 将通过 REST 支持进行增强。 这篇文章描述了如何使用 REST 支持在简单的示例应用程序之上实现 AtomView。 按照此分步过程,了解使用 Spring MVC 中的新 REST 支持在简单应用程序之上实现 AtomView 是多么容易。

步骤 1:下载应用程序框架

在此博客文章的底部附近,您会找到一个简单的下载,其中包含 Web 应用程序的框架。 在内部,您会找到此应用程序所需的所有 Spring 3.0 二进制文件,以及 Atom 功能所需的一些额外文件。 Spring 二进制文件基于每晚构建,一旦 Spring 3.0 完成,可能会替换为最终版本。

接下来,使用“导入 > 将现有项目导入工作空间”向导(从“文件”菜单中)在 Eclipse 中加载项目。 该应用程序是一个简单的 Eclipse 动态 Web 项目,其中包含 Spring MVC 设置的所有基础结构。 因此,如果您熟悉 Spring MVC,这应该不是什么大问题。

步骤 2:查看应用程序的设置

在 /WEB-INF/web.xml 中,您将找到定义的 Spring MVC DispatcherServlet。 它从 /WEB-INF/rest-servlet.xml 文件加载应用程序上下文。 反过来,此文件包含一个组件扫描器,该扫描器在 com.springsource.samples.rest 包中扫描 @Components(也是 @Controllers)。

接下来,在 com.springsource.samples.rest 包中,您将找到一个包含两个控制器方法的 ContentController。


@Controller
public class ContentController {
	
	private List<SampleContent> contentList = new ArrayList<SampleContent>();
	
	@RequestMapping(value="/content.*", method=RequestMethod.GET)
	public ModelAndView getContent() {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("content");
		mav.addObject("sampleContentList", contentList);
		return mav;
	}
	
	@RequestMapping(value="/content.html", method=RequestMethod.POST)
	public String addContent() {
		contentList.add(SampleContent.generateContent("Alef Arendsen", new Date()));
		return "redirect:content.html";
	}
}

第一个处理程序返回 SampleContent 项目的列表。 第二个处理程序通过使用 SampleContent.generateContent() 方法添加新的 SampleContent 项目。 第一个处理程序响应 GET 请求,第二个处理程序响应 POST 请求。 这些方法本身已使用 @RequestMapping 注释进行注释以执行此操作。

在 rest-servlet.xml 应用程序上下文文件中,除了组件扫描器之外,您还将找到一个 ViewResolver,在本例中为 InternalResourceViewResolver。 它将负责视图名称(getContent() 处理程序中的“content”情况)和 JSP 页面之间的转换。

在将此部署到例如 Tomcat 之后,您应该能够转到 http://localhost:8080/spring-rest/rest。 这会将您重定向到 /rest/content,该 URL 由处理程序选取。

步骤 3:实现 AtomView

为了实现 AtomView,我们将使用 Rome 项目,可从 https://rome.dev.java.net/ 获得。 在应用程序的原始设置中,视图名称由视图解析器转换为 InternalResourceView 的实例,在本例中将呈现 JSP。 我们将创建自己的 View 接口的专用实例,而是呈现 Atom 提要。

在 com.springsource.samples.rest 包中创建一个名为 SampleContentAtomView 的类,然后粘贴以下代码。 该代码使用 Spring MVC 中的 Atom 支持类和来自 Rome 项目的 Atom 提要的文档对象模型。


public class SampleContentAtomView extends AbstractAtomFeedView {

	@Override
	protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
		feed.setId("tag:springsource.com");
		feed.setTitle("Sample Content");
		@SuppressWarnings("unchecked")
		List<SampleContent> contentList = (List<SampleContent>)model.get("sampleContentList");
		for (SampleContent content : contentList) {
			Date date = content.getPublicationDate();
			if (feed.getUpdated() == null || date.compareTo(feed.getUpdated()) > 0) {
				feed.setUpdated(date);
			}
		}
	}

	@Override
	protected List<Entry> buildFeedEntries(Map<String, Object> model,
			HttpServletRequest request, HttpServletResponse response) throws Exception {

		@SuppressWarnings("unchecked")
		List<SampleContent> contentList = (List<SampleContent>)model.get("sampleContentList");
		List<Entry> entries = new ArrayList<Entry>(contentList.size());

		for (SampleContent content : contentList) {
			Entry entry = new Entry();
			String date = String.format("%1$tY-%1$tm-%1$td", content.getPublicationDate());
			// see http://diveintomark.org/archives/2004/05/28/howto-atom-id#other
			 entry.setId(String.format("tag:springsource.com,%s:%d", date, content.getId()));
			entry.setTitle(String.format("On %s, %s wrote", date, content.getAuthor()));
			entry.setUpdated(content.getPublicationDate());

			Content summary = new Content();
			summary.setValue(content.getText());
			entry.setSummary(summary);
			
			entries.add(entry);
		}

		return entries;

	}
}

步骤 4:设置内容协商

框架 Web 应用程序已经提供了 HTML 视图,现在我们也实现了生成 Atom 提要的视图。 我们需要做的最后一件事是确保对 Atom 提要的请求实际上将使用 SampleContentAtomView 呈现,并且在请求 HTML 视图时将呈现 JSP。

在一个完美的世界中,客户端会要求使用 Accept HTTP 标头首选的特定表示形式。 Accept HTTP 标头(由 HTTP 规范定义)可以采用一个或多个媒体类型,并且应由浏览器(或任何 HTTP 客户端)发送,以指示它首选哪种表示形式。 例如,Atom 提要的适当媒体类型为“application/atom+xml”,而 HTML 视图可能仅发送“text/html”或“text/xhtml”作为 Accept 标头。 然而,这存在一个小问题。 浏览器通常具有一组固定的媒体类型,它们作为 Accept HTTP 标头发送,并且没有办法(除了使用 JavaScript)来修改浏览器发送的 Accept 标头。 这就是文件扩展名是向服务器指示您想要什么表示形式的一个很好的替代方法的原因。

Spring 3.0 具有 ContentNegotiatingViewResolver,它可以与扩展以及 Accept 标头一起使用。 在确定了适当的媒体类型之后,它会委派给一组其他视图解析器来为我们执行此操作。 需要将以下内容粘贴到 rest-servlet.xml 中才能使其工作。 如您所见,ContentNegotiatingViewResolver 将委派给 BeanNameViewResolver(如果需要,解析为 SampleContentAtomView)或 InternalResourceViewResolver。 顺便说一句,下面的代码段应替换已经在您的 rest-servlet.xml 文件中配置的 InternalResourceViewResolver。

ContentNegotiatingViewResolver 首先查看文件扩展名,然后使用 Accept 标头(顺便说一句,这在一定程度上是可定制的)。 我们必须将适当的扩展名映射到适当的媒体类型。 在此示例中,我们将 .html 映射到媒体类型 text/html,并将 .atom 映射到 application/atom+xml。 这将确保呈现适当的视图。

如果传入 .atom 请求,ContentNegotiatingViewResolver 将查找与 application/atom+xml 媒体类型匹配的视图。 视图解析器将查找一个视图,该视图呈现带有媒体类型 text/html 的内容,如果传入 .html 请求。


<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
	<property name="mediaTypes">
		<map>
			<entry key="atom" value="application/atom+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.InternalResourceViewResolver">
				<property name="prefix" value="/WEB-INF/jsp/"/>
				<property name="suffix" value=".jsp"/>
			</bean>
		</list>
	</property>
</bean>

<bean id="content" class="com.springsource.samples.rest.SampleContentAtomView"/>

在将此放入您的应用程序上下文中之后,重新启动服务器应该可以解决问题。 转到 http://localhost:8080/spring-rest/rest/content.html 以查看所有内容项目并生成新的内容项目。 转到 http://localhost:8080/spring-rest/rest/content.atom 以订阅 Atom 提要。

我希望这篇小博客文章向您展示了向您的应用程序添加 Atom 提要是多么简单。 除了 Atom 之外,Spring 还具有用于呈现 PDF 和 Excel 文件、JSON 表示形式和 XML 文档的视图支持类。 检查它们,让我们知道您的想法!

下载

正如承诺的那样,这是下载。 请注意,这些项目基于 Spring 的每晚构建。 对于更新的版本,请确保 Spring 3.0 检查 www.springsource.org

获取 Spring 新闻稿

通过 Spring 新闻稿保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部