1. 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.2.2.RELEASE</version>        <relativePath/>    </parent>    <groupId>cn.itcast</groupId>    <artifactId>knife4j_demo</artifactId>    <version>1.0-SNAPSHOT</version>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>com.github.xiaoymin</groupId>            <artifactId>knife4j-spring-boot-starter</artifactId>            <version>2.0.1</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>        </dependency>    </dependencies></project>

2.application.yml

server:  port: 8081niewj:  swagger:    enabled: true #是否启用swagger    base-package: com.niewj.controller#    docket:#      user:#        title: 用户模块#        base-package: com.niewj.controller.user#      menu:#        title: 菜单模块#        base-package: com.niewj.controller.menu

3. 配置读取属性类SwaggerProperties

package com.niewj.config;import lombok.*;import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/**配置属性类,用于封装接口文档相干属性,从配置文件读取信息封装成以后对象*/@Data@ConfigurationProperties(prefix = "niewj.swagger")public class SwaggerProperties {    private String title = "在线文档"; //题目    private String group = ""; //自定义组名    private String description = "在线文档"; //形容    private String version = "1.0"; //版本    private Contact contact = new Contact(); //联系人    private String basePackage = "com.niewj"; //swagger会解析的包门路    private List<String> basePath = new ArrayList<>(); //swagger会解析的url规定    private List<String> excludePath = new ArrayList<>();//在basePath根底上须要排除的url规定    private Map<String, DocketInfo> docket = new LinkedHashMap<>(); //分组文档    public String getGroup() {        if (group == null || "".equals(group)) {            return title;        }        return group;    }    @Data    public static class DocketInfo {        private String title = "在线文档"; //题目        private String group = ""; //自定义组名        private String description = "在线文档"; //形容        private String version = "1.0"; //版本        private Contact contact = new Contact(); //联系人        private String basePackage = ""; //swagger会解析的包门路        private List<String> basePath = new ArrayList<>(); //swagger会解析的url规定        private List<String> excludePath = new ArrayList<>();//在basePath根底上须要排除的url        public String getGroup() {            if (group == null || "".equals(group)) {                return title;            }            return group;        }    }    @Data    public static class Contact {        private String name = "niewj"; //联系人        private String url = ""; //联系人url        private String email = ""; //联系人email    }}

4. SwaggerConfig

package com.niewj.config;import com.google.common.base.Predicate;import com.google.common.base.Predicates;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;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.service.Contact;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;@Configuration@ConditionalOnProperty(name = "niewj.swagger.enabled", havingValue = "true", matchIfMissing = true)@EnableSwagger2@EnableConfigurationProperties(SwaggerProperties.class)public class SwaggerConfig implements BeanFactoryAware {    @Autowired    SwaggerProperties swaggerProperties;    private BeanFactory beanFactory;    @Bean    @ConditionalOnMissingBean    public List<Docket> createRestApi() {        ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;        List<Docket> docketList = new LinkedList<>();        // 没有分组        if (swaggerProperties.getDocket().isEmpty()) {            Docket docket = createDocket(swaggerProperties);            configurableBeanFactory.registerSingleton(swaggerProperties.getTitle(), docket);            docketList.add(docket);            return docketList;        }        // 分组创立        for (String groupName : swaggerProperties.getDocket().keySet()) {            SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);            ApiInfo apiInfo = new ApiInfoBuilder()                    //页面题目                    .title(docketInfo.getTitle())                    //创建人                    .contact(new Contact(docketInfo.getContact().getName(),                            docketInfo.getContact().getUrl(),                            docketInfo.getContact().getEmail()))                    //版本号                    .version(docketInfo.getVersion())                    //形容                    .description(docketInfo.getDescription())                    .build();            // base-path解决            // 当没有配置任何path的时候,解析/**            if (docketInfo.getBasePath().isEmpty()) {                docketInfo.getBasePath().add("/**");            }            List<Predicate<String>> basePath = new ArrayList<>();            for (String path : docketInfo.getBasePath()) {                basePath.add(PathSelectors.ant(path));            }            // exclude-path解决            List<Predicate<String>> excludePath = new ArrayList<>();            for (String path : docketInfo.getExcludePath()) {                excludePath.add(PathSelectors.ant(path));            }            Docket docket = new Docket(DocumentationType.SWAGGER_2)                    .apiInfo(apiInfo)                    .groupName(docketInfo.getGroup())                    .select()                    //为以后包门路                    .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))                    .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath)))                    .build();            configurableBeanFactory.registerSingleton(groupName, docket);            docketList.add(docket);        }        return docketList;    }    //构建 api文档的详细信息    private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {        return new ApiInfoBuilder()                //页面题目                .title(swaggerProperties.getTitle())                //创建人                .contact(new Contact(swaggerProperties.getContact().getName(),                        swaggerProperties.getContact().getUrl(),                        swaggerProperties.getContact().getEmail()))                //版本号                .version(swaggerProperties.getVersion())                //形容                .description(swaggerProperties.getDescription())                .build();    }    //创立接口文档对象    private Docket createDocket(SwaggerProperties swaggerProperties) {        //API 根底信息        ApiInfo apiInfo = apiInfo(swaggerProperties);        // base-path解决        // 当没有配置任何path的时候,解析/**        if (swaggerProperties.getBasePath().isEmpty()) {            swaggerProperties.getBasePath().add("/**");        }        List<Predicate<String>> basePath = new ArrayList<>();        for (String path : swaggerProperties.getBasePath()) {            basePath.add(PathSelectors.ant(path));        }        // exclude-path解决        List<Predicate<String>> excludePath = new ArrayList<>();        for (String path : swaggerProperties.getExcludePath()) {            excludePath.add(PathSelectors.ant(path));        }        return new Docket(DocumentationType.SWAGGER_2)                .apiInfo(apiInfo)                .groupName(swaggerProperties.getGroup())                .select()                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))                .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)), Predicates.or(basePath)))                .build();    }    @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        this.beanFactory = beanFactory;    }}

5. 业务相干类

5.1 返回后果格局封装Result

package com.niewj.common.response;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.util.ArrayList;/** * 返回后果格局封装 * * @author nieweijun * @since 2021/6/29 18:43 */@NoArgsConstructor@AllArgsConstructor@Data@ApiModel(description = "返回后果数据封装")public class Result<T> {    @ApiModelProperty(value = "返回后果code码")    private Integer code;    @ApiModelProperty(value = "返回后果信息形容")    private String msg;    @ApiModelProperty(value = "返回数据胜利标识")    private Boolean success;    @ApiModelProperty(value = "返回数据详情")    private T data;    /**     * 用枚举来结构     *     * @param responseEnum 应用枚举值的code和msg填充Result     * @param data         数据对象     * @param ifSuccess    是否申请胜利     */    public Result(ResponseEnum responseEnum, T data, Boolean ifSuccess) {        this.setCode(responseEnum.getCode());        this.setMsg(responseEnum.getMsg());        this.setData(data);        this.setSuccess(ifSuccess);    }    /**     * success={"code":200,"msg":"胜利","data":"xxx","success":true}     *     * @param data     * @return     */    public static <T> Result<T> success(T data) {        return new Result<>(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getMsg(), Boolean.TRUE, data);    }    /**     * success={"code":200,"msg":"胜利","data": null,"success":true}     *     * @return     */    public static <T> Result<T> successWithNull() {        return new Result<>(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getMsg(), Boolean.TRUE, null);    }    /**     * success={"code":200,"msg":"胜利","data": [],"success":true}     *     * @return     */    public static <T> Result<T> successWithEmptyList() {        return (Result<T>) Result.success(new ArrayList<T>());    }    /**     * success=除了返回true指定, 其余的都由参数指定     *     * @param code     * @param msg     * @param data     * @param <T>     * @return     */    public static <T> Result<T> success(Integer code, String msg, T data) {        return new Result<>(code, msg, Boolean.TRUE, data);    }    /**     * success等价于new Result(ResponseEnum, T, true)     *     * @param responseEnum     * @param data     * @param <T>     * @return     */    public static <T> Result<T> success(ResponseEnum responseEnum, T data) {        return new Result<>(responseEnum, data, Boolean.TRUE);    }    /**     * fail-除了返回false, 其余的参数指定     * 例如: {"code":xxx,"msg":"xxx", "data": "指定的谬误", "success":false}     *     * @param data     * @param <T>     * @return     */    public static <T> Result<T> fail(Integer code, String msg, T data) {        return new Result<>(code, msg, Boolean.FALSE, data);    }    /**     * fail-除了返回false, 其余的参数指定-由枚举类指定     * 例如: {"code":xxx,"msg":"xxx", "data": "指定的谬误", "success":false}     *     * @param responseEnum     * @param <T>     * @return     */    public static <T> Result<T> fail(ResponseEnum responseEnum, T data) {        return new Result<>(responseEnum.getCode(), responseEnum.getMsg(), Boolean.FALSE, data);    }}

5.2 响应枚举

package com.niewj.common.response;/** * 响应枚举:code和message的封装(留神: code申明为int不便比拟; Integer的话须要equals!) * * @author nieweijun * @since 2021/6/29 18:51 */public enum ResponseEnum {    SUCCESS(200, "胜利"),    REPEAT(201, "反复操作"),    BAD_REQUEST(400, "申请参数不合规"),    ERROR(500, "服务器异样"),    RPC_ERROR(501, "RPC服务器异样"),    //=========================业务编码=========================    NO_LOGIN(1001, "未登录"),    RISK(1002, "零碎忙碌"),    RECODE_REPEAT(1003, "有反复数据"),    DATA_LACK(1004, "申请数据缺失或超时"),    NO_PERMISSION(1005, "用户无权限"),    // ========================RPC服务问题========================    RPC_INVOKE_ERROR(2001, "依赖服务产生异样"),    RPC_DATA_INVALID(2002, "依赖服务数据有效"),    RPC_INVOKE_TIMEOUT(2003, "依赖服务申请超时"),    UNDER_REVIEW(2004, "预计10分钟内审核结束,请稍后再从新进入小程序"),    RPC_DISASSEMBLY_FAIL(2008, "提交旧机拆解失败"),    OTHER(-1, "其余");    // 申明为简略类型是为了不便用==比拟;    // 200 == Integer(200) ->true    // 200 == 200 -> true    // Integer(200) == Integer(200) -> false    private int code;    private String msg;    ResponseEnum(int code, String msg) {        this.code = code;        this.msg = msg;    }    public String getMsg() {        return msg;    }    public int getCode() {        return code;    }    public static ResponseEnum getByCode(int code) {        for (ResponseEnum responseCode : ResponseEnum.values()) {            if (responseCode.getCode() == code) {                return responseCode;            }        }        return ERROR;    }}

5.3 model-1: Menu

package com.niewj.model;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@AllArgsConstructor@NoArgsConstructor@Data@ApiModel(description = "菜单实体")public class Menu {    @ApiModelProperty(value = "主键")    private int id;    @ApiModelProperty(value = "菜单名称")    private String name;}

5.3 model-2: User

package com.niewj.model;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@AllArgsConstructor@NoArgsConstructor@Data@ApiModel(description = "用户实体")public class User {    @ApiModelProperty(value = "主键")    private int id;    @ApiModelProperty(value = "姓名")    private String name;    @ApiModelProperty(value = "年龄")    private int age;    @ApiModelProperty(value = "地址")    private String address;}

5.4 MenuController

package com.niewj.controller;import com.niewj.common.response.Result;import com.niewj.model.Menu;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;@RestController@RequestMapping("/menu")@Api(tags = "菜单控制器")@Slf4jpublic class MenuController {    @GetMapping("/getMenus")    @ApiOperation(value = "查问所有菜单", notes = "查问所有菜单信息")    public Result<List<Menu>> getMenus() {        log.info("getMenus success!");        List<Menu> list = new ArrayList<>();        list.add(new Menu(100, "menu100"));        list.add(new Menu(101, "menu101"));        list.add(new Menu(102, "menu102"));        return Result.success(list);    }    @PostMapping("/save")    @ApiOperation(value = "新增菜单", notes = "新增菜单信息")    public Result<Boolean> save(@RequestBody Menu menu) {        log.info("save success!");        return Result.success(Boolean.TRUE);    }    @PutMapping("/update")    @ApiOperation(value = "批改菜单", notes = "批改菜单信息")    public Result<Boolean> update(@RequestBody Menu menu) {        log.info("update success!");        return Result.success(Boolean.TRUE);    }    @DeleteMapping("/delete")    @ApiOperation(value = "删除菜单", notes = "删除菜单信息")    public Result<Boolean> delete(int id) {        log.info("update success!");        return Result.success(Boolean.TRUE);    }    @ApiImplicitParams({            @ApiImplicitParam(name = "pageNum", value = "页码", required = true, type = "Integer"),            @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, type = "Integer"),    })    @ApiOperation(value = "分页查问菜单信息")    @GetMapping(value = "page/{pageNum}/{pageSize}")    public String findByPage(@PathVariable Integer pageNum,                             @PathVariable Integer pageSize) {        List<Menu> list = new ArrayList<>();        list.add(new Menu(100, "menu100"));        list.add(new Menu(101, "menu101"));        list.add(new Menu(102, "menu102"));        return "OK";    }}

5.5 UserController

package com.niewj.controller;import com.niewj.common.response.Result;import com.niewj.model.User;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;@RestController@RequestMapping("/user")@Api(tags = "用户控制器")public class UserController {    @GetMapping("/getUsers")    @ApiOperation(value = "查问所有用户", notes = "查问所有用户信息")    public Result<List<User>> getAllUsers() {        List<User> list = new ArrayList<>();        list.add(new User(100, "小0", 20, "北京"));        list.add(new User(101, "小1", 30, "北京"));        list.add(new User(102, "小2", 23, "西安"));        return Result.success(list);    }    @PostMapping("/save")    @ApiOperation(value = "新增用户", notes = "新增用户信息")    public Result<Boolean> save(@RequestBody User user) {        return Result.success(Boolean.TRUE);    }    @PutMapping("/update")    @ApiOperation(value = "批改用户", notes = "批改用户信息")    public Result<Boolean> update(@RequestBody User user) {        return Result.success(Boolean.TRUE);    }    @DeleteMapping("/delete")    @ApiOperation(value = "删除用户", notes = "删除用户信息")    public Result<Boolean> delete(int id) {        return Result.success(Boolean.TRUE);    }    @ApiImplicitParams({            @ApiImplicitParam(name = "pageNum", value = "页码", required = true, type = "Integer"),            @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, type = "Integer"),    })    @ApiOperation(value = "分页查问用户信息")    @GetMapping(value = "page/{pageNum}/{pageSize}")    public Result<List<User>> findByPage(@PathVariable Integer pageNum,                                         @PathVariable Integer pageSize) {        List<User> list = new ArrayList<>();        list.add(new User(100, "小0", 20, "北京"));        list.add(new User(101, "小1", 30, "北京"));        list.add(new User(102, "小2", 23, "西安"));        return Result.success(list);    }}

5.6 启动类

package com.niewj;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import springfox.documentation.swagger2.annotations.EnableSwagger2;@SpringBootApplicationpublic class DemoApplication {    public static void main(String[] args) {        SpringApplication.run(DemoApplication.class, args);    }}

5.7 启动后拜访

拜访地址: http://localhost:8081/doc.html
即可