现在前后端分离这么流行,后端采用Restful API来设计也是大势所趋吧。下面介绍一下在Spring boot中使用RestFul API的基本方式吧。
PS:不去说什么是Restful服务,只是说说它在代码中的实际使用。
首先,定义两个model:
其一:User实体类
package com.baiding.security.model;
import com.fasterxml.jackson.annotation.JsonView;
import java.util.Date;
/**
* @Author: BaiDing
* @Date: 2018/10/10 21:08
* @Email: liujiabaiding@foxmail.com
*/
public class User {
public interface UserSimpleView {};
public interface UserDetailView extends UserSimpleView {};
private long id;
private String userName;
private String password;
private Date birthday;
// JsonView根据视图控制字段的输出
@JsonView(UserSimpleView.class)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@JsonView(UserDetailView.class)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@JsonView(UserSimpleView.class)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@JsonView(UserSimpleView.class)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
其二:UserQueryCondition实体类
package com.baiding.security.model;
/**
* @Author: BaiDing
* @Date: 2018/10/10 21:10
* @Email: liujiabaiding@foxmail.com
*/
public class UserQueryCondition {
private String username;
private int age;
private int ageTo;
private String xxx;
// getter、setter
}
之后,定义一个controller:
package com.baiding.security.web.controller;
import com.baiding.security.model.User;
import com.baiding.security.model.UserQueryCondition;
import com.fasterxml.jackson.annotation.JsonView;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: BaiDing
* @Date: 2018/10/10 21:07
* @Email: liujiabaiding@foxmail.com
*/
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping
@JsonView(User.UserSimpleView.class)
public List<User> query(UserQueryCondition condition,
@PageableDefault(page = 2, size = 17, sort = "username,asc") Pageable pageable) {
System.out.println(ReflectionToStringBuilder.toString(condition, ToStringStyle.MULTI_LINE_STYLE));
System.out.println(pageable.getPageSize());
System.out.println(pageable.getPageNumber());
System.out.println(pageable.getSort());
List<User> users = new ArrayList<>();
users.add(new User());
users.add(new User());
users.add(new User());
return users;
}
@GetMapping("/{id:\\d+}")
@JsonView(User.UserDetailView.class)
public User getInfo(@PathVariable String id) {
User user = new User();
user.setUserName("tom");
return user;
}
@PostMapping
public User create(@RequestBody User user) {
System.out.println(user.getId());
System.out.println(user.getUserName());
System.out.println(user.getPassword());
System.out.println(user.getBirthday());
user.setId(1);
return user;
}
@PutMapping
public User update(@RequestBody User user) {
System.out.println(user.getId());
System.out.println(user.getUserName());
System.out.println(user.getPassword());
System.out.println(user.getBirthday());
user.setId(1);
return user;
}
@DeleteMapping("/{id:\\d+}")
public void delete(@PathVariable String id) {
System.out.println(id);
}
}
上面分别是使用Restful API来进行增删改查,这里简单说明一下其中的一些代码:
- @PostMapping、@DeleteMapping、@PutMapping、@GetMapping这四个注解分别代表着增删改查了
- Pageable 是Spring Data库中定义的一个接口,该接口是所有分页相关信息的一个抽象,通过该接口,我们可以得到和分页相关所有信息,当然你可以自己自定义一个类似的实体类来保存这些数据。
- @JsonView 可以过滤序列化对象的字段属性,可以使你有选择的序列化对象。具体怎么使用就不做介绍了
- /{id:\\d+} 冒号后面接正则表达式是对参数做匹配约束
下面就可以设计测试类来做测试了,如下:
package com.baiding.security.test;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.Date;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @Author: BaiDing
* @Date: 2018/10/10 21:03
* @Email: liujiabaiding@foxmail.com
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class WebTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void whenQuerySuccess() throws Exception {
String result = mockMvc.perform(
get("/user").param("username", "jojo").param("age", "18").param("ageTo", "60").param("xxx", "yyy")
// .param("size", "15")
// .param("page", "3")
// .param("sort", "age,desc")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk()).andExpect(jsonPath("$.length()").value(3))
.andReturn().getResponse().getContentAsString();
System.out.println(result);
}
@Test
public void whenGetInfoSuccess() throws Exception {
String result = mockMvc.perform(get("/user/1")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.userName").value("tom"))
.andReturn().getResponse().getContentAsString();
System.out.println(result);
}
@Test
public void whenGetInfoFail() throws Exception {
mockMvc.perform(get("/user/a")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().is4xxClientError());
}
@Test
public void whenCreateSuccess() throws Exception {
Date date = new Date();
System.out.println(date.getTime());
String content = "{\"userName\":\"tom\",\"password\":\"as11\",\"birthday\":"+date.getTime()+"}";
String reuslt = mockMvc.perform(post("/user").contentType(MediaType.APPLICATION_JSON_UTF8)
.content(content))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("1"))
.andReturn().getResponse().getContentAsString();
System.out.println(reuslt);
}
@Test
public void whenUpdateSuccess() throws Exception {
// Date date = new Date(LocalDateTime.now().plusYears(1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
Date date = new Date();
System.out.println(date.getTime());
String content = "{\"id\":1, \"userName\":\"tom\",\"password\":\"pwd123\",\"birthday\":"+date.getTime()+"}";
String reuslt = mockMvc.perform(put("/user").contentType(MediaType.APPLICATION_JSON_UTF8)
.content(content))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("1"))
.andReturn().getResponse().getContentAsString();
System.out.println(reuslt);
}
@Test
public void whenDeleteSuccess() throws Exception {
mockMvc.perform(delete("/user/1")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
}
}
关于如何使用MockMvc做单元测试,这里不再赘述。
这里的Before注解是在执行测试方法前先执行其标注的方法。
关于jsonPath的使用推荐学一下。
上面基本就是全部的代码了,欢迎指正。