zoukankan      html  css  js  c++  java
  • SpringBoot系列

    REST,即Representational State Transfer的缩写,对这个词组的翻译是表现层状态转化

    RESTful是一种软件设计风格,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

    SpringMVC对RESTful风格的接口有着天然的支持,本篇将讲述如何在SpringBoot中怎样写。

    几个注解

    在讲述使用之前,想要理解SpringMVC的几个常用注解:

    1. @Controller:修饰class,用来创建处理http请求的对象
    2. @RestController:Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。
    3. @RequestMapping:配置url映射
    4. @PostMapping: 这个是@RequestMapping+POST方法的简写
    5. @RequestHeader: 请求Header参数
    6. @PathVariable: URL路径参数,比如/user/{id}中的id参数
    7. @RequestParam: URL请求参数,比如/user?id=1中的id参数
    8. @RequestBody: 请求Body参数

    下面我们尝试使用Spring MVC来实现一组对User对象操作的RESTful API,配合注释详细说明在Spring MVC中如何映射HTTP请求、如何传参、如何编写单元测试。

    API设计

    RESTful API具体设计如下:

    请求类型URL功能说明
    GET /users 查询用户列表
    POST /users 创建一个用户
    GET /users/{id} 根据id查询用户
    PUT /users/{id} 根据id更新用户
    DELTE /users/{id} 更加id删除用户

    RESTful架构有一些典型的设计误区,就是URI包含动词。因为”资源”表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中。 上面设计的API的URI中都是名词。

    实体定义

    1
    2
    3
    4
    5
    6
    public class User {
    private Long id;
    private String name;
    private Integer age;
    // 下面省略getter/setter
    }

    Controller实现

    接下来就可以编写RestController了,这里为了演示,会将数据保存到内存Map中,实际使用肯定是保存到数据库中。

    /**
    * 接口类
    */
    @RestController
    @RequestMapping(value = "/users")
    public class UserController {

    private static final Logger _logger = LoggerFactory.getLogger(UserController.class);

    // 创建线程安全的Map
    private static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public BaseResponse<List<User>> getUserList() {
    // 处理"/users/"的GET请求,用来获取用户列表
    // 还可以通过@RequestParam从页面中传递参数来进行查询条件或者翻页信息的传递
    List<User> r = new ArrayList<>(users.values());
    return new BaseResponse<>(true, "查询列表成功", r);
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public BaseResponse<String> postUser(@ModelAttribute User user) {
    // 处理"/users/"的POST请求,用来创建User
    // 除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数
    users.put(user.getId(), user);
    return new BaseResponse<>(true, "新增成功", "");
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public BaseResponse<User> getUser(@PathVariable Long id) {
    // 处理"/users/{id}"的GET请求,用来获取url中id值的User信息
    // url中的id可通过@PathVariable绑定到函数的参数中
    return new BaseResponse<>(true, "查询成功", users.get(id));
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public BaseResponse<String> putUser(@PathVariable Long id, @ModelAttribute User user) {
    // 处理"/users/{id}"的PUT请求,用来更新User信息
    User u = users.get(id);
    u.setName(user.getName());
    u.setAge(user.getAge());
    users.put(id, u);
    return new BaseResponse<>(true, "更新成功", "");
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public BaseResponse<String> deleteUser(@PathVariable Long id) {
    // 处理"/users/{id}"的DELETE请求,用来删除User
    users.remove(id);
    return new BaseResponse<>(true, "删除成功", "");
    }

    }

    测试

    接下来就是写一个测试来测一下,SpringMVC的内置测试支持非常方便。

    先写一个json和对象之间相互转化的工具类,使用Jackson库:

    public class JacksonUtil {
    private static ObjectMapper mapper = new ObjectMapper();

    public static String bean2Json(Object obj) {
    try {
    return mapper.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
    e.printStackTrace();
    return null;
    }
    }

    public static <T> T json2Bean(String jsonStr, TypeReference<T> typeReference) {
    try {
    return mapper.readValue(jsonStr, typeReference);
    } catch (IOException e) {
    e.printStackTrace();
    return null;
    }
    }
    }

    然后再编写单元测试:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    @AutoConfigureMockMvc
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class ApplicationTests {
    @Autowired
    private MockMvc mvc;

    @Test
    public void testUserController() throws Exception {
    // 测试UserController
    RequestBuilder request;

    // 1、get查一下user列表,应该为空
    request = get("/users/");
    MvcResult result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    String content = result.getResponse().getContentAsString();
    BaseResponse<List<User>> response = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<List<User>>>() {});
    assertThat(response.isSuccess(), is(true));
    assertThat(response.getMsg(), is("查询列表成功"));
    assertThat(((List) response.getData()).size(), is(0));

    // 2、post提交一个user
    request = post("/users/")
    .param("id", "1")
    .param("name", "测试大师")
    .param("age", "20");
    result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    content = result.getResponse().getContentAsString();
    BaseResponse<String> response1 = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<String>>() {});
    assertThat(response1.isSuccess(), is(true));
    assertThat(response1.getMsg(), is("新增成功"));

    // 3、get获取user列表,应该有刚才插入的数据
    request = get("/users/");
    result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    content = result.getResponse().getContentAsString();
    BaseResponse<List<User>> response2 = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<List<User>>>() {});
    assertThat(response2.isSuccess(), is(true));
    assertThat(response2.getMsg(), is("查询列表成功"));
    assertThat((response2.getData()).size(), is(1));

    // 4、put修改id为1的user
    request = put("/users/1")
    .param("name", "测试终极大师")
    .param("age", "30");
    result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    content = result.getResponse().getContentAsString();
    BaseResponse<String> response3 = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<String>>() {});
    assertThat(response3.isSuccess(), is(true));
    assertThat(response3.getMsg(), is("更新成功"));

    // 5、get一个id为1的user
    request = get("/users/1");
    result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    content = result.getResponse().getContentAsString();
    BaseResponse<User> response4 = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<User>>() {});
    assertThat(response4.isSuccess(), is(true));
    assertThat(response4.getMsg(), is("查询成功"));
    User user = response4.getData();
    assertThat(user.getId(), is(1L));
    assertThat(user.getName(), is("测试终极大师"));

    // 6、del删除id为1的user
    request = delete("/users/1");
    result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    content = result.getResponse().getContentAsString();
    BaseResponse<String> response5 = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<String>>() {});
    assertThat(response5.isSuccess(), is(true));
    assertThat(response5.getMsg(), is("删除成功"));

    // 7、get查一下user列表,应该为空
    request = get("/users/");
    result = mvc.perform(request)
    .andExpect(status().isOk())
    .andReturn();
    content = result.getResponse().getContentAsString();
    BaseResponse<List<User>> response6 = JacksonUtil.json2Bean(content, new TypeReference<BaseResponse<List<User>>>() {});
    assertThat(response6.isSuccess(), is(true));
    assertThat(response6.getMsg(), is("查询列表成功"));
    assertThat((response6.getData()).size(), is(0));
    }

    }
  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/xiaohuizhenyoucai/p/14447215.html
Copyright © 2011-2022 走看看