说明
通过实现订单的增删改查,初步了解web相关的构建和使用
REStful API规划
请求类型 | URL | 说明 |
---|---|---|
GET | /orders | 查询所有订单 |
POST | /orders/add | 创建一个订单 |
GET | /orders/id | 查询一个订单 |
POST | /orders/update/id | 更新订单 |
DELETE | /orders/delete/id | 删除订单 |
常用注解说明
- @Controller:修饰class,用来创建处理http请求的对象
- @RestController:Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。
- @RequestMapping:配置url映射
- @PathVariable:通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。
- @ModelAttribute:
①绑定请求参数到命令对象:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用;
②暴露表单引用对象为模型数据:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用;
③暴露@RequestMapping方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。 - @RequestParam:获取url中的参数,用于将请求参数区数据映射到功能处理方法的参数上。
代码参考
实体类order
package com.sunld.domain;
public class Order {
/**
* 订单id
*/
private Integer id;
/**
* 订单名称
*/
private String orderName;
/**
* 订单类型
*/
private String orderType;
/**
* get、set方法
*/
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
@Override
public String toString() {
return "Order [id=" + id + ", orderName=" + orderName + ", orderType=" + orderType + "]";
}
}
Controller:OrderController
package com.sunld;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.sunld.domain.Order;
@RestController
//定义统一的入口,通过这里配置使下面的映射都在/orders下
@RequestMapping("/orders")
public class OrderController {
//定义线程安全的map用来存储订单信息
private static final Map<Integer , Order> staticOrderMap =
Collections.synchronizedMap(new HashMap<Integer, Order>());
/**
* 查询所有订单
* url地址:http://127.0.0.1:8080/orders/
* 还可以通过@RequestParam从页面中传递参数来进行查询条件或者翻页信息的传递
* @return
*/
@RequestMapping(value = "/" , method = RequestMethod.GET)
public List<Order> getOrders(){
List<Order> orderList = new ArrayList<Order>(staticOrderMap.values());
return orderList;
}
/**
* 添加订单
* url地址:http://127.0.0.1:8080/orders/add
* @ModelAttribute:用来接收form中的订单信息
* 除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数
* @param order
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addOrder(@ModelAttribute Order order) {
if(order != null) {
staticOrderMap.put(order.getId(), order);
return "success";
}
return "failure";
}
/**
* 根据订单id获取订单信息
* url地址:http://127.0.0.1:8080/orders/1234
* url中的id可通过@PathVariable绑定到函数的参数中
* @return
*/
@RequestMapping(value = "/{id}" , method = RequestMethod.GET)
public Order getOrderById(@PathVariable Integer id) {
return staticOrderMap.get(id);
}
/**
* 根据订单id更新订单信息
* url地址:http://127.0.0.1:8080/orders/update/1234
* @param id
* @param order
* @return
*/
@RequestMapping(value = "/update/{id}" , method = RequestMethod.POST)
public String updateOrderById(@PathVariable Integer id, @ModelAttribute Order order) {
Order o = staticOrderMap.get(id);
if(o != null && order != null) {
o.setOrderName(order.getOrderName());
o.setOrderType(order.getOrderType());
staticOrderMap.put(id, o);
return "success";
}else {
return "failure";
}
}
/**
* 根据订单ID删除订单信息
* url地址:http://127.0.0.1:8080/orders/delete/1234
* @param id
* @return
*/
@RequestMapping(value="/delete/{id}", method=RequestMethod.DELETE)
public String deleteOrderById(@PathVariable Integer id) {
staticOrderMap.remove(id);
return "success";
}
}
测试类:OrderControllerTest
package com.sunld.controller;
import static org.hamcrest.CoreMatchers.equalTo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.sunld.OrderController;
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderControllerTest {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new OrderController()).build();
}
@Test
public void testOrderController() throws Exception {
//1.创建查询所有订单,结果返回为空
System.out.println("=====================初次查询所有订单信息start=====================");
getOrders()
.andExpect(MockMvcResultMatchers.content().string(equalTo("[]")))
.andReturn();
System.out.println("=====================初次查询所有订单信息end=======================");
System.out.println("=====================第一次添加订单start=========================");
// 2、post提交一个订单
mvc.perform(MockMvcRequestBuilders.post("/orders/add")
.param("id", "1234")
.param("orderName", "购买平板电脑")
.param("orderType", "在线付款")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.content().string(equalTo("success")))
.andReturn();
//2.1、查询所有订单
/**
* 结果应该为"[{\"id\":1234,\"orderName\":\"购买平板电脑\",\"orderType\":\"在线付款\"}]"
*/
getOrders()
.andExpect(MockMvcResultMatchers.content().string(equalTo("[{\"id\":1234,\"orderName\":\"购买平板电脑\",\"orderType\":\"在线付款\"}]")))
.andReturn();
System.out.println("=====================第一次添加订单end===========================");
System.out.println("=====================再次添加订单start===========================");
//3、再添加一个订单
mvc.perform(MockMvcRequestBuilders.post("/orders/add")
.param("id", "3456")
.param("orderName", "购买奶粉")
.param("orderType", "货到付款")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.content().string(equalTo("success")))
.andReturn();
//3.1、查看所有订单信息
/**
* 订单信息:
* [{"id":3456,"orderName":"购买奶粉","orderType":"货到付款"},{"id":1234,"orderName":"购买平板电脑","orderType":"在线付款"}]
*/
getOrders();
System.out.println("=====================再次添加订单end=============================");
System.out.println("=====================修改存在编号的订单start============================");
//4、修改编号为1234的订单:该订单存在
mvc.perform(MockMvcRequestBuilders.post("/orders/update/1234")
.param("orderName", "订单名称由【购买平板电脑】修改为【再次购买平板电脑】")
.param("orderType", "在线付款")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
//4.1查询订单1234
getOrdersById("1234");
System.out.println("=====================修改存在编号的订单end==============================");
System.out.println("=====================修改订单编号不存在的订单start==============================");
//5、修改编号为1的订单、该订单不存在,直接返回failure
mvc.perform(MockMvcRequestBuilders.post("/orders/update/1")
.param("orderName", "订单名称由【购买平板电脑】修改为【再次购买平板电脑】")
.param("orderType", "在线付款")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.content().string(equalTo("failure")))
.andReturn();
System.out.println("=====================修改订单编号不存在的订单end==============================");
//6、删除订单1234
mvc.perform(MockMvcRequestBuilders.delete("/orders/delete/1234").accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.content().string(equalTo("success")))
.andReturn();
//6、1查看所有订单
getOrders();
}
private ResultActions getOrders() throws Exception {
return mvc.perform(MockMvcRequestBuilders.get("/orders/").accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
// .andReturn();
}
private ResultActions getOrdersById(String id) throws Exception {
return mvc.perform(MockMvcRequestBuilders.get("/orders/" + id).accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
// .andReturn();
}
}
总结
参考
spring学习之@ModelAttribute运用详解
@RequestParam详解
Spring Boot构建RESTful API与单元测试
代码
https://github.com/sld880311/springboot-learning/tree/master/springboot_simpleweb