在上一个博客中,我说过我将谈论Spring,Ajax和JSON,但是没有。 原因是我想使用(很少)可信的购物网站场景来设置场景。 在这种情况下,当用户单击“电子商务”页面链接时,服务器应用程序将加载目录中的某些项目并将其显示在页面上。 然后,用户检查多个项目并按“确认购买”。 现在,这就是Ajax和JSON的来源,在按“确认购买”时,浏览器向向其发送项目ID的服务器发出Ajax请求。 然后,服务器从数据库中检索项目,并将它们作为JSON返回到浏览器。 然后,浏览器处理JSON,并在屏幕上显示项目。
我的最后一个博客涉及创建并显示一个显示项目列表的表单
从虚构目录到用户。 该博客介绍了该项目的下一步:创建一些JSON。
在过去的几年中,Spring的家伙们一直在忙于Ajax和JSON的开发,并且,正如您所期望的,他们在后台为您做了很多工作。 这意味着您要做的就是定义一个简单的bean类,Spring可以将其转换为JSON并编写一些控制器代码。 在这种情况下,Spring将转换为JSON的类是OrderForm
类:
public class OrderForm { private final List<Item> items; private final String purchaseId; public OrderForm(List<Item> items, String purchaseId) { super(); this.items = items; this.purchaseId = purchaseId; } public List<Item> getItems() { return items; } public String getPurchaseId() { return purchaseId; }
}
OrderForm
类包含Item
对象的列表和用于定义订单的唯一订单ID。
创建OrderForm
,下一步是整理Spring控制器代码:
public @ResponseBody OrderForm confirmPurchases(@ModelAttribute("userSelections") UserSelections userSelections) { logger.debug("Confirming purchases..."); OrderForm orderForm = createOrderForm(userSelections.getSelection()); return orderForm; } private OrderForm createOrderForm(List<String> selections) { List<Item> items = findItemsInCatalogue(selections); String purchaseId = getPurchaseId(); OrderForm orderForm = new OrderForm(items, purchaseId); return orderForm; } private List<Item> findItemsInCatalogue(List<String> selections) { List<Item> items = new ArrayList<Item>(); for (String selection : selections) { Item item = catalogue.findItem(Integer.valueOf(selection)); items.add(item); } return items; } private String getPurchaseId() { return UUID.randomUUID().toString(); }
上面的代码是向浏览器返回JSON所需要的全部,您可以看到它并没有那么多。 首先,该方法的@RequestMapping
批注(使用confirm
和RequestMethod.POST
值)映射我的表单属性
以前的博客对此方法进行了介绍。
<form:form modelAttribute="userSelections" action="confirm" method="post">
modelAttribute
批注告诉Spring从表单发布的数据创建并映射userSelections
对象,并将其注入confirmPurchases(...)
方法的userSelections
参数。 UserSelections
类是一个便捷类,它包装String
的列表。 尽管是Lazy Class反模式的示例,但该类用于轻松地与Spring的<form:checkbox>
标记集成,并且在实际应用中将包含更多属性。
public class UserSelections { private List<String> selection = Collections.emptyList(); public List<String> getSelection() { return selection; } public void setSelection(List<String> selection) { this.selection = selection; } @Override public String toString() { StringBuilder sb = new StringBuilder("Selections are: "); for (String str : selection) { sb.append(str); sb.append(", "); } return sb.toString(); }
}
confirmPurchases(...)
方法将UserSelections
输入对象转换为OrderForm
输出对象,该对象将作为JSON传递回浏览器。 通过遍历OrderForm
对象中包含的Item
ID列表并使用伪catalogue
服务查找相应的Item
来创建UserSelection
对象。 一旦有了Item
的列表,它便使用Java的UUID
类创建唯一的购买ID。 然后,它将Item
的列表和购买ID传递给OrderForm
的构造函数,然后将订单表单传递回Spring。 不要忘记@ResposeBody
批注,它告诉Spring使用合适的HttpMessageConverter
将OrderForm
绑定到HTTP响应主体。 这就是神奇的地方。您可能会猜到,HTTP响应正文需要包含具有正确媒体类型的数据才能通过Internet发送,而OrderForm
绝对不适合该账单。 为了解决该问题,Spring似乎在项目配置中查看了转换OrderForm
对象的合适方法,在该方法中,它找到了在上一个博客中添加到项目中的jackson-core
和jackson-databind
库。
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.0.4</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.0.4</version></dependency>
在没有其他合适的候选人的情况下,请使用这些库将OrderForm
对象转换为JSON。 所有这些都意味着您和我实际上不必做任何真正的编码即可生成我们的JSON输出。 相当聪明吧!
显然,在后台进行的所有这些神奇的拼图游戏都隐藏了实际的JSON输出,因此,我发现创建一个类似于以下所示的简单单元测试很有用:
@Test public void testDemonstrateJSON() throws JsonGenerationException, JsonMappingException, IOException { UserSelections userSelection = new UserSelections(); String[] selections = { "1", "2" }; userSelection.setSelection(Arrays.asList(selections)); Item item1 = Item.getInstance(1, "name", "description", new BigDecimal("1.00")); when(catalogue.findItem(1)).thenReturn(item1); Item item2 = Item.getInstance(2, "name2", "description2", new BigDecimal("2.00")); when(catalogue.findItem(2)).thenReturn(item2); OrderForm orderForm = instance.confirmPurchases(userSelection); ObjectMapper mapper = new ObjectMapper(); String result = mapper.writeValueAsString(orderForm); System.out.println(result); }
您可能会认为这不是真正的测试,因为它没有声明任何内容。 该测试的价值在于直观地显示JSON输出,并确保杰克逊解析器可以将您附加到HTTP响应主体的对象转换为JSON。 如果不能,那么在运行此测试时,您将获得一个异常。
因此,这就是服务器端代码。 在这个简短的系列文章中,下一个(也可能是最后一个)博客将介绍客户端代码。 有关此博客的完整源代码,请参见GitHub – https://github.com/roghughe/captaindebug/tree/master/ajax-json
翻译自: https://www.javacodegeeks.com/2013/05/spring-mvc-ajax-and-json-part-2-the-server-side-code.html