企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 简介 * `@Controller`:修饰class,用来创建处理http请求的对象 * `@RestController`:Spring4之后加入的注解,原来在`@Controller`中返回json需要`@ResponseBody`来配合,如果直接用`@RestController`替代`@Controller`就不需要再配置`@ResponseBody`,默认返回json格式 * `@RequestMapping`:配置url映射 下面我们尝试使用Spring MVC来实现一组对User对象操作的RESTful API,配合注释详细说明在Spring MVC中如何映射HTTP请求、如何传参、如何编写单元测试。 **RESTful API具体设计如下:** ![](https://img.kancloud.cn/55/17/55170ebc73da78ee94064ca74c25cb09_1700x740.png) `patch /users/text 修改users的text字段` put是更新整个资源的,patch是表述更新部分字段 * @GetMapping,处理理 Get 请求 * @PostMapping,处理理 Post 请求 * @PutMapping,用于更更新资源 * @DeleteMapping,处理理删除请求 * @PatchMapping,用于更更新部分资源 ~~~ @GetMapping(value="/xxx") 等价于 @RequestMapping(value = "/xxx",method = RequestMethod.GET) @PostMapping(value="/xxx") 等价于 @RequestMapping(value = "/xxx",method = RequestMethod.POST) @PutMapping(value="/xxx") 等价于 @RequestMapping(value = "/xxx",method = RequestMethod.PUT) @DeleteMapping(value="/xxx") 等价于 @RequestMapping(value = "/xxx",method = RequestMethod.DELETE) @PatchMapping(value="/xxx") 等价于 @RequestMapping(value = "/xxx",method = RequestMethod.PATCH) ~~~ # 案例 定义一个实体 ~~~ @Data public class Message { private Long id; private String text; private String summary; private Calendar created = Calendar.getInstance(); } ~~~ ## Repository **定义接口** ~~~ public interface MessageRepository { List<Message> findAll(); Message save(Message message); Message update(Message message); Message updateText(Message message); Message findMessage(Long id); void deleteMessage(Long id); } ~~~ 用ConcurrentHashMap来模拟存储Message对象的增删改查. AtomicLong作为消息的自增主键来使用,并发场景下获得唯一Long值 **InMemoryMessageRepository** ~~~ @Service("messageRepository") public class InMemoryMessageRepository implements MessageRepository { private static AtomicLong counter = new AtomicLong(); private final ConcurrentMap<Long, Message> messages = new ConcurrentHashMap<>(); @Override public List<Message> findAll() { List<Message> messages = new ArrayList<>(this.messages.values()); return messages; } //保存消息的时候,先判断是否存在id,没有,可以用AtomicLong取一个 @Override public Message save(Message message) { Long id = message.getId(); if (id == null) { id = counter.incrementAndGet(); message.setId(id); } this.messages.put(id, message); return message; } @Override public Message update(Message message) { this.messages.put(message.getId(), message); return message; } //更新Text字段 @Override public Message updateText(Message message) { Message msg = this.messages.get(message.getId()); msg.setText(message.getText()); this.messages.put(msg.getId(), msg); return msg; } @Override public Message findMessage(Long id) { return this.messages.get(id); } @Override public void deleteMessage(Long id) { this.messages.remove(id); } } ~~~ ## 控制器 将封装好的MessageRepository注入到Controller中,调用增删改查 ~~~ @RestController @RequestMapping("/") public class MessageController { @Autowired private MessageRepository messageRepository; //获取所有消息体 @GetMapping(value = "message") public List<Message> list() { List<Message> messages = this.messageRepository.findAll(); return messages; } //创建消息体 @PostMapping(value = "message") public Message create(Message message) { return this.messageRepository.save(message); } //使用Put请求进行修改 @PatchMapping(value = "/message/text") public Message patch(Message message) { return this.messageRepository.updateText(message); } @GetMapping(value = "message/{id}") public Message get(@PathVariable Long id) { return this.messageRepository.findMessage(id); } @DeleteMapping(value = "message/{id}") public void delete(@PathVariable("id") Long id) { this.messageRepository.deleteMessage(id); } } ~~~ ## 测试 * MultiValueMap ⽤用来存储需要发送的请求参数。 * MockMvcRequestBuilders.post 代表使⽤用 post 请求 ~~~ //运行一个spring容器 @RunWith(SpringRunner.class) //用于测试的注解 @SpringBootTest public class MessageControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; public void setup() { //提前加载MVC环境 this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); //一开始就保存一些数据 saveMessages(); } //创建一个消息体 @Test public void saveMessage() throws Exception { final MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("text", "text"); params.add("summary", "summary"); String mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/message") .params(params)).andReturn().getResponse().getContentAsString(); System.out.println("Result === " + mvcResult); } //批量添加消息请求 private void saveMessages() { for (int i = 0; i < 10; i++) { final MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("text", "text" + i); params.add("summary", "summary" + i); try { MvcResult mvcResult = mockMvc.perform( MockMvcRequestBuilders.post("/message") .params(params)).andReturn(); }catch (Exception e) { e.printStackTrace(); } } } //获取所有消息 @Test public void getAllMessages() throws Exception { String mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/message")) .andReturn().getResponse().getContentAsString(); System.out.println("Result === " + mvcResult); } //获取单个消息 @Test public void getMessage() throws Exception { String mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/message/6")) .andReturn().getResponse().getContentAsString(); System.out.println("Result === " + mvcResult); } //修改 @Test public void modifyMessage() throws Exception { LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("id", "6"); params.add("text", "text"); params.add("summary", "summary"); String mvcResult = mockMvc.perform(MockMvcRequestBuilders.put("/message") .params(params)).andReturn().getResponse().getContentAsString(); System.out.println("Result === " + mvcResult); } //测试局部修改 @Test public void patchMessage() throws Exception { LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("id", "6"); params.add("text", "text"); String mvcResult = mockMvc.perform(MockMvcRequestBuilders.patch("/message/text") .params(params)).andReturn().getResponse().getContentAsString(); System.out.println("Result === " + mvcResult); } @Test public void deleteMessage() throws Exception { mockMvc.perform(MockMvcRequestBuilders.delete("/message/6")) .andReturn(); String mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/message")) .andReturn().getResponse().getContentAsString(); System.out.println("Result === " + mvcResult); } } ~~~