1. 程式人生 > >spring boot?Swagger2文檔構建及單元測試

spring boot?Swagger2文檔構建及單元測試

int 5.6 n) post 參數 odin mat ace 關註

首先,回顧並詳細說明一下在快速入門中使用的@Controller@RestController@RequestMapping註解。如果您對Spring MVC不熟悉並且還沒有嘗試過快速入門案例,建議先看一下快速入門的內容。

  • @Controller:修飾class,用來創建處理http請求的對象
  • @RestController:Spring4之後加入的註解,原來在@Controller中返回json需要@ResponseBody來配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默認返回json格式。
  • @RequestMapping
    :配置url映射

下面我們嘗試使用Spring MVC來實現一組對User對象操作的RESTful API,配合註釋詳細說明在Spring MVC中如何映射HTTP請求、如何傳參、如何編寫單元測試。

RESTful API具體設計如下:

技術分享

POM.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wls</groupId>
    <artifactId>project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>project</name>
    <description>project</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- mybatis依賴 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- MySql驅動 -->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!--<version>5.1.21</version>-->
        </dependency>
        <!--Json庫的依賴 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.1.43</version>
        </dependency>
        <!--    jpa     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--    devtools        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!--    mysql        -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--    aop        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>


        <!--    redis       -->
        <!--<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <!--        activemq        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

        <!--        thymeleaf       -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>


        <!--        mail        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <!--       swagger2     -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>

        </plugins>

    </build>


</project>

  

實體

package com.wls.integrateplugs.jpa.primary.model;

/**
 * Created by wls on 2017/8/24.
 */
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    private Long id;
    @Column(nullable = false, unique = true)
    private String userName;
    @Column(nullable = false)
    private String passWord;
    @Column(nullable = false, unique = true)
    private String email;
    @Column(nullable = true, unique = true)
    private String nickName;
    @Column(nullable = false)
    private String regTime;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private Integer age;

    public User() {
        super();
    }

    public User(String userName, String passWord, String email, String nickName, String regTime, String name, Integer age) {
        this.userName = userName;
        this.passWord = passWord;
        this.email = email;
        this.nickName = nickName;
        this.regTime = regTime;
        this.name = name;
        this.age = age;
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    public String getRegTime() {
        return regTime;
    }
    public void setRegTime(String regTime) {
        this.regTime = regTime;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

  Controller

package com.wls.integrateplugs.swagger;

/**
 * Created by wls on 2017/8/24.
 */
import java.util.*;

import com.wls.integrateplugs.jpa.primary.repository.IUserRepository;
import com.wls.integrateplugs.jpa.primary.model.User;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping(value="/users")     // 通過這裏配置使下面的映射都在/users下,可去除
public class UserController {

    @Autowired
    private IUserRepository iUserRepository;

    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());

    /*@RequestMapping("/getUser")
    @Cacheable(value="user-key")
    public User getUser() {
        User user=iUserRepository.findByUserName("aa");
        System.out.println("若下面沒出現“無緩存的時候調用”字樣且能打印出數據表示測試成功");
        return user;
    }

    @RequestMapping("/getUsers")
    @Cacheable(value="key-Users")
    public List<User> getUsers() {
        List<User> users=iUserRepository.findAll();
        System.out.println("若下面沒出現“無緩存的時候調用”字樣且能打印出數據表示測試成功");
        return users;
    }*/



    @ApiOperation(value="獲取用戶列表", notes="獲取用戶列表")
    @RequestMapping(value={"/"}, method=RequestMethod.GET)
    public List<User> getUserList() {
        // 處理"/users/"的GET請求,用來獲取用戶列表
        // 還可以通過@RequestParam從頁面中傳遞參數來進行查詢條件或者翻頁信息的傳遞
        List<User> r = new ArrayList<User>(users.values());
        return r;
    }

    @ApiOperation(value="創建用戶", notes="根據User對象創建用戶")
    @ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
    @RequestMapping(value="/", method=RequestMethod.POST)
//    public String postUser(@RequestBody User user) {
    public String postUser(@ModelAttribute User user) {
        // 處理"/users/"的POST請求,用來創建User
        // 除了@ModelAttribute綁定參數之外,還可以通過@RequestParam從頁面中傳遞參數
        users.put(user.getId(), user);
        return "success";
    }

    @ApiOperation(value="獲取用戶詳細信息", notes="根據url的id來獲取用戶詳細信息")
    @ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long")
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public User getUser(@PathVariable Long id) {
        // 處理"/users/{id}"的GET請求,用來獲取url中id值的User信息
        // url中的id可通過@PathVariable綁定到函數的參數中
        return users.get(id);
    }

    @ApiOperation(value="更新用戶詳細信息", notes="根據url的id來指定更新對象,並根據傳過來的user信息來更新用戶詳細信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long"),
        @ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
    })
    @RequestMapping(value="/{id}", method= RequestMethod.PUT)
//    public String putUser(@PathVariable Long id, @RequestBody User user) {
    public 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 "success";
    }

    @ApiOperation(value="刪除用戶", notes="根據url的id來指定刪除對象")
    @ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "Long")
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public String deleteUser(@PathVariable Long id) {
        // 處理"/users/{id}"的DELETE請求,用來刪除User
        users.remove(id);
        return "success";
    }
}

  

package com.wls.integrateplugs.hello.controller;

/**
 * Created by wls on 2017/8/24.
 */
import java.util.Locale;
import java.util.UUID;

import javax.servlet.http.HttpSession;

import com.sun.org.apache.regexp.internal.RE;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.annotations.ApiIgnore;

@RestController
public class HelloController {

    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String hello(Locale locale, Model model) {
        return "hello world";
    }

    @RequestMapping("/helloWorld")
    public String index() {
        return "Hello World";
    }

    /**
     * 使用@RestController時,則使用ModelAndView顯示頁面
     * @param map
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/helloThymeleaf",method = RequestMethod.GET)
    public ModelAndView index(ModelMap map) {
        ModelAndView mv = new ModelAndView("index");
        map.addAttribute("host", "http://blog.didispace.com");
        return mv;
    }

    /**
     * 共享session
     * @param session
     * @return
     */
    @RequestMapping(value = "/uid",method = RequestMethod.GET)
    String uid(HttpSession session) {
        UUID uid = (UUID) session.getAttribute("uid");
        if (uid == null) {
            uid = UUID.randomUUID();
        }
        session.setAttribute("uid", uid);
        return session.getId();
    }

}

  單元測試

package com.wls.test.integrateplugs.swagger;

import com.wls.integrateplugs.hello.controller.HelloController;
import com.wls.integrateplugs.swagger.UserController;
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.mock.web.MockServletContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class SwaggerTest {

    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.standaloneSetup(
                new HelloController(),
                new UserController()).build();
    }

    @Test
    public void getHello() throws Exception {
        mvc.perform(get("/hello").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("hello world")));
    }

    @Test
    public void testUserController() throws Exception {
//  	測試UserController
        RequestBuilder request = null;

        // 1、get查一下user列表,應該為空
        request = get("/users/");
        mvc.perform(request)
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("[]")));

        // 2、post提交一個user
        request = post("/users/")
                .param("id", "1")
                .param("name", "測試大師")
                .param("age", "20");
        mvc.perform(request)
				.andDo(MockMvcResultHandlers.print())
                .andExpect(content().string(equalTo("success")));

        // 3、get獲取user列表,應該有剛才插入的數據
        request = get("/users/");
        mvc.perform(request)
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("[{\"id\":1,\"userName\":null,\"passWord\":null,\"email\":null,\"nickName\":null,\"regTime\":null,\"name\":\"測試大師\",\"age\":20}]")));

        // 4、put修改id為1的user
        request = put("/users/1")
                .param("name", "測試終極大師")
                .param("age", "30");
        mvc.perform(request)
                .andExpect(content().string(equalTo("success")));

        // 5、get一個id為1的user
        request = get("/users/1");
        mvc.perform(request)
                .andExpect(content().string(equalTo("{\"id\":1,\"userName\":null,\"passWord\":null,\"email\":null,\"nickName\":null,\"regTime\":null,\"name\":\"測試終極大師\",\"age\":30}")));

        // 6、del刪除id為1的user
        request = delete("/users/1");
        mvc.perform(request)
                .andExpect(content().string(equalTo("success")));

        // 7、get查一下user列表,應該為空
        request = get("/users/");
        mvc.perform(request)
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("[]")));

    }
}
Swagger2配置類

  

package com.wls.integrateplugs.swagger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author 程序猿DD
 * @version 1.0.0
 * @date 16/4/18 下午12:02.
 * @blog http://blog.didispace.com
 */
@Configuration
@EnableSwagger2
public class Swagger2 {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.wls"))
            .paths(PathSelectors.any())
            .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("Spring Boot中使用Swagger2構建RESTful APIs")
            .description("更多Spring Boot相關文章請關註:http://blog.didispace.com/")
            .termsOfServiceUrl("http://blog.didispace.com/")
            .contact("程序猿DD")
            .version("1.0")
            .build();
    }

}

  

訪問地址:localhost:8081/project/swagger-ui.html技術分享

spring boot?Swagger2文檔構建及單元測試