diff --git a/README.md b/README.md index d423f9d7..8188e8b4 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,20 @@ ### 作业描述 -#### 切换到课程对应的分支查看每节课的作业要求 -* Routing: routing -* Data Binding: data-binding -* Validation: validation -* Customised Response: customize-response -* Error Handling: error-handling - - 注意:最终需要将改动合并到master分支 +根据课堂上的demo,完成下面需求 +1. 提供获取某一条热搜事件的接口 +2. 提供能够根据起始参数,获取对应范围内的热搜事件列表的接口 +3. 提供添加热搜事件的接口(事件包含两个字段:事件名称和关键字) +4. 提供修改某条热搜事件的接口(demo没有展示,请大家自己完成) +5. 提供删除某条热搜事件的接口(demo没有展示,请大家自己完成) + +#### 需求4、5详细描述 + +* 需求4: 修改某条事件时(通过参数传递的序号,修改列表中对应的事件数据),如果RequestBody只传了eventName没有传keyword那么仅仅只修改eventName + 如果只传了keyword没有传eventName,那么只修改keyword字段 + 如果两个字段都传了,那么都进行修改 + +* 需求5: 通过参数传递的序号,删除列表中对应的某条事件数据 + + + 注意:所有的需求都请先写测试再写实现 diff --git a/src/main/java/com/thoughtworks/rslist/api/RsController.java b/src/main/java/com/thoughtworks/rslist/api/RsController.java index 6899e4de..ea546478 100644 --- a/src/main/java/com/thoughtworks/rslist/api/RsController.java +++ b/src/main/java/com/thoughtworks/rslist/api/RsController.java @@ -1,11 +1,53 @@ package com.thoughtworks.rslist.api; -import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.thoughtworks.rslist.domain.RsEvent; +import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.UnaryOperator; @RestController public class RsController { - private List rsList = Arrays.asList("第一条事件", "第二条事件", "第三条事件"); + private List rsList = initRsEventList(); + private List initRsEventList(){ + List rsEventList = new ArrayList<>(); + rsEventList.add(new RsEvent("第一条事件","无标签")); + rsEventList.add(new RsEvent("第二条事件","无标签")); + rsEventList.add(new RsEvent("第三条事件","无标签")); + return rsEventList; + } + + @GetMapping("/rs/{index}") + public RsEvent getOneRsEvent(@PathVariable int index){ + return rsList.get(index -1); + } + + @GetMapping("/rs/list") + public List getRsEventBetween(@RequestParam(required = false) Integer start,@RequestParam(required = false) Integer end){ + if(start == null || end == null){ + return rsList; + } + return rsList.subList(start-1,end); + } + + @PostMapping("/rs/event") + public void addRsEvent(@RequestBody String rsEvent) throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + RsEvent event = objectMapper.readValue(rsEvent,RsEvent.class); + rsList.add(event); + } + + @DeleteMapping ("/rs/{index}") + public void deleteRsEvent(@PathVariable int index) { + rsList.remove(index-1); + } + + @PatchMapping("/rs/{index}") + public void modifyRsEvent(@PathVariable int index,@RequestBody RsEvent rsEvent ) { + rsList.set(index - 1,rsEvent); + } } diff --git a/src/main/java/com/thoughtworks/rslist/api/UserController.java b/src/main/java/com/thoughtworks/rslist/api/UserController.java new file mode 100644 index 00000000..6d161428 --- /dev/null +++ b/src/main/java/com/thoughtworks/rslist/api/UserController.java @@ -0,0 +1,27 @@ +package com.thoughtworks.rslist.api; + +import com.thoughtworks.rslist.domain.User; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +@RestController +public class UserController{ + List userList = new ArrayList<>(); + + @PostMapping("/user") + public void addUser(@RequestBody @Valid User user){ + userList.add(user); + } + + @GetMapping("/user") + public List getUserList(){ + return userList; + } + +} \ No newline at end of file diff --git a/src/main/java/com/thoughtworks/rslist/domain/RsEvent.java b/src/main/java/com/thoughtworks/rslist/domain/RsEvent.java new file mode 100644 index 00000000..79d18026 --- /dev/null +++ b/src/main/java/com/thoughtworks/rslist/domain/RsEvent.java @@ -0,0 +1,31 @@ +package com.thoughtworks.rslist.domain; + +public class RsEvent { + private String eventName; + private String keyWord; + + public RsEvent(String eventName,String keyWord){ + this.eventName = eventName; + this.keyWord = keyWord; + } + + public RsEvent(){ + + } + + public String getKeyWord() { + return keyWord; + } + + public void setKeyWord(String keyWord) { + this.keyWord = keyWord; + } + + public String getEventName() { + return eventName; + } + + public void setEventName(String eventName) { + this.eventName = eventName; + } +} diff --git a/src/main/java/com/thoughtworks/rslist/domain/User.java b/src/main/java/com/thoughtworks/rslist/domain/User.java new file mode 100644 index 00000000..ca0e65a8 --- /dev/null +++ b/src/main/java/com/thoughtworks/rslist/domain/User.java @@ -0,0 +1,76 @@ +package com.thoughtworks.rslist.domain; + +import javax.validation.constraints.*; + +public class User { + @NotNull + @Size(max = 8) + private String name; + @NotNull + private String gender; + @NotNull + @Min(18) + @Max(100) + private int age; + @Email + private String email; + @Pattern(regexp = "1\\d{10}") + private String phone; + private int voteNum = 10; + + public User(String name, String gender, int age, String email, String phone) { + this.name = name; + this.gender = gender; + this.age = age; + this.email = email; + this.phone = phone; + } + + public String getName() { + return name; + } + + public void setName() { + this.name = name; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public int getVoteNum() { + return voteNum; + } + + public void setVoteNum(int voteNum) { + this.voteNum = voteNum; + } +} diff --git a/src/test/java/com/thoughtworks/rslist/api/RsControllerTest.java b/src/test/java/com/thoughtworks/rslist/api/RsControllerTest.java new file mode 100644 index 00000000..a9de3371 --- /dev/null +++ b/src/test/java/com/thoughtworks/rslist/api/RsControllerTest.java @@ -0,0 +1,126 @@ +package com.thoughtworks.rslist.api; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.thoughtworks.rslist.domain.RsEvent; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.Matchers.hasSize; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.hamcrest.Matchers.is; + +@SpringBootTest +@AutoConfigureMockMvc +public class RsControllerTest { + @Autowired + MockMvc mockMvc; + @Test + public void should_get_rs_event_list() throws Exception{ + mockMvc.perform(get("/rs/list")).andExpect(jsonPath("$",hasSize(3))) + .andExpect(jsonPath("$[0].eventName",is("第一条事件"))) + .andExpect(jsonPath("$[0].keyWord",is("无标签"))) + .andExpect(jsonPath("$[1].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[1].keyWord",is("无标签"))) + .andExpect(jsonPath("$[2].eventName",is("第三条事件"))) + .andExpect(jsonPath("$[2].keyWord",is("无标签"))) + .andExpect(status().isOk()); + } + + @Test + public void should_get_one_rs_event() throws Exception{ + mockMvc.perform(get("/rs/1")) + .andExpect(jsonPath("$.eventName",is("第一条事件"))) + .andExpect(jsonPath("$.keyWord",is("无标签"))) + .andExpect(status().isOk()); + mockMvc.perform(get("/rs/2")) + .andExpect(jsonPath("$.eventName",is("第二条事件"))) + .andExpect(jsonPath("$.keyWord",is("无标签"))) + .andExpect(status().isOk()); + mockMvc.perform(get("/rs/3")) + .andExpect(jsonPath("$.eventName",is("第三条事件"))) + .andExpect(jsonPath("$.keyWord",is("无标签"))) + .andExpect(status().isOk()); + } + @Test + public void should_get_rs_event_between() throws Exception{ + mockMvc.perform(get("/rs/list?start=1&end=2")) + .andExpect(jsonPath("$",hasSize(2))) + .andExpect(jsonPath("$[0].eventName",is("第一条事件"))) + .andExpect(jsonPath("$[0].keyWord",is("无标签"))) + .andExpect(jsonPath("$[1].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[1】.keyWord",is("无标签"))) + .andExpect(status().isOk()); + mockMvc.perform(get("/rs/list?start=2&end=3")) + .andExpect(jsonPath("$",hasSize(2))) + .andExpect(jsonPath("$[0].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[0].keyWord",is("无标签"))) + .andExpect(jsonPath("$[1].eventName",is("第三条事件"))) + .andExpect(jsonPath("$[1】.keyWord",is("无标签"))) + .andExpect(status().isOk()); + mockMvc.perform(get("/rs/list?start=1&end=3")) + .andExpect(jsonPath("$",hasSize(3))) + .andExpect(jsonPath("$[0].eventName",is("第一条事件"))) + .andExpect(jsonPath("$[0].keyWord",is("无标签"))) + .andExpect(jsonPath("$[1].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[1】.keyWord",is("无标签"))) + .andExpect(jsonPath("$[2].eventName",is("第三条事件"))) + .andExpect(jsonPath("$[2】.keyWord",is("无标签"))) + .andExpect(status().isOk()); + } + @Test + public void should_add_rs_event() throws Exception{ + RsEvent rsEvent = new RsEvent("猪肉涨价了","经济"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(rsEvent); + mockMvc.perform(post("/rs/event").content(jsonString).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + + mockMvc.perform(get("/rs/list")).andExpect(jsonPath("$",hasSize(4))) + .andExpect(jsonPath("$[0].eventName",is("第一条事件"))) + .andExpect(jsonPath("$[0].keyWord",is("无标签"))) + .andExpect(jsonPath("$[1].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[1].keyWord",is("无标签"))) + .andExpect(jsonPath("$[2].eventName",is("第三条事件"))) + .andExpect(jsonPath("$[2].keyWord",is("无标签"))) + .andExpect(jsonPath("$[3].eventName",is("猪肉涨价了"))) + .andExpect(jsonPath("$[3].keyWord",is("经济"))) + .andExpect(status().isOk()); + } + + @Test + public void should_modify_rs_event_eventName_and_keyWord() throws Exception { + RsEvent rsEvent = new RsEvent("猪肉涨价了","经济"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(rsEvent); + + mockMvc.perform(patch("/rs/1").content(jsonString).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + + mockMvc.perform(get("/rs/list")).andExpect(jsonPath("$",hasSize(3))) + .andExpect(jsonPath("$[0].eventName",is("猪肉涨价了"))) + .andExpect(jsonPath("$[0].keyWord",is("经济"))) + .andExpect(jsonPath("$[1].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[1].keyWord",is("无标签"))) + .andExpect(jsonPath("$[2].eventName",is("第三条事件"))) + .andExpect(jsonPath("$[2].keyWord",is("无标签"))) + .andExpect(status().isOk()); + } + + @Test + public void should_delete_rs_event() throws Exception { + mockMvc.perform(delete("/rs/1")).andExpect(status().isOk()); + + mockMvc.perform(get("/rs/list")).andExpect(jsonPath("$",hasSize(2))) + .andExpect(jsonPath("$[0].eventName",is("第二条事件"))) + .andExpect(jsonPath("$[0].keyWord",is("无标签"))) + .andExpect(jsonPath("$[1].eventName",is("第三条事件"))) + .andExpect(jsonPath("$[1].keyWord",is("无标签"))) + .andExpect(status().isOk()); + } + +} diff --git a/src/test/java/com/thoughtworks/rslist/api/UserControllerTest.java b/src/test/java/com/thoughtworks/rslist/api/UserControllerTest.java new file mode 100644 index 00000000..c848049e --- /dev/null +++ b/src/test/java/com/thoughtworks/rslist/api/UserControllerTest.java @@ -0,0 +1,89 @@ +package com.thoughtworks.rslist.api; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.thoughtworks.rslist.domain.RsEvent; +import com.thoughtworks.rslist.domain.User; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.Matchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest +@AutoConfigureMockMvc +public class UserControllerTest { + @Autowired + MockMvc mockMvc; + + @Test + public void should_register_user() throws Exception { + User user = new User("lyx","female",18,"1@2.com","12222222222"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(user); + mockMvc.perform(post("/user") + .content(jsonString) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + + mockMvc.perform(get("/user")) + .andExpect(jsonPath("$",hasSize(1))) + .andExpect(jsonPath("$[0].name",is("lyx"))) + .andExpect(jsonPath("$[0].gender",is("female"))) + .andExpect(jsonPath("$[0].age",is(18))) + .andExpect(jsonPath("$[0].email",is("1@2.com"))) + .andExpect(jsonPath("$[0].phone",is("12222222222"))) + .andExpect(status().isOk()); + } + + + @Test + public void name_should_less_than_8() throws Exception{ + User user = new User("lyx111111","female",18,"1@2.com","12222222222"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(user); + mockMvc.perform(post("/user") + .content(jsonString) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + public void age_should_between_18_and_100() throws Exception{ + User user = new User("lyx","female",118,"1@2.com","12222222222"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(user); + mockMvc.perform(post("/user") + .content(jsonString) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + public void email_should_right() throws Exception{ + User user = new User("lyx","female",28,".com","12222222222"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(user); + mockMvc.perform(post("/user") + .content(jsonString) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + public void phone_should_right() throws Exception{ + User user = new User("lyx","female",28,".com","3312222222222"); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(user); + mockMvc.perform(post("/user") + .content(jsonString) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } +} \ No newline at end of file