• springboot2.04+mybatis-plus+swagger2+CodeGenerator


    @author zhangyh

    SpringBoot技术栈搭建个人博客【项目准备】

     RESTful API就是一套协议来规范多种形式的前端和同一个后台的交互方式

     


     


    原型设计

    事实上,我是直接先去找的原型,去参考了一下大概我需要做成什么样子...

    前端原型参考

    在这里先给大家推荐一个设计网站吧,找素材啊之类的还挺方便的:

    站酷:http://www.zcool.com.cn/

    所以我在里面找到了我想要的前端原型,大概就像这个样子:

     


    项目搭建

    先来介绍一下这次想要使用的一些技术:

    • SpringBoot2.04 来编写后台
    • Vue 来写页面,准备抛弃一下JSP,虽然现在Vue还啥都不懂,学呗
    • MyBatis 用于ORM,喜欢这玩意儿的逆向工程
    • RESTful API / JSON 交互
    • Redis 可能还会使用这个来缓存一下md转换之后的html源码

    SpringBoot 工程搭建

    SpringBoot 项目搭建过程就不再赘述了,不熟悉的童鞋戳这边:https://www.jianshu.com/p/70963ab49f8c,这里就简单给一下配置信息:

    后台肯定是需要加安全验证的,要简单点我可以搞一个拦截器来简单弄弄,也可以用现有的安全框架,这里暂时就不加入这方面的东西了,把基本的弄进来就OK,然后它默认加入的东西不能够支持我们的业务,所以还需要手动添加进一些包:

    step 1  项目结构如下:

    热部署还是要的呀,然后再在【resrouces】下新建一个【banner.txt】文件,修改一下SpringBoot启动的提示信息:

     __      __                                 __                        
    /   __/                                /                        
      /       ___ ___    __  __     ____  /'    __  _  ____    
            /' __` __` / /    /',__\  , <   / /'/\_ ,`  
        \_/ \_ / / / \  \_  /\__, `\  \` />  <//_/  /_ 
        `\___x___/ \_ \_ \_\/`____ \/\____/  \_ \_/\_/\_ /\____
        '/__//__/  /_//_//_/ `/___/> \/___/   /_//_////_/ /____/
                                    /\___/                                
                                    /__/                                 

    下面对这些目录进行一些简要的说明:

    • controller:控制器
    • dao:实际上这个包可以改名叫mapper,因为里面放的应该是MyBatis逆向工程自动生成之后的mapper类,还是叫dao吧,传统...
    • entity:实体类,还会有一些MyBatis生成的example
    • generator:MyBatis逆向工程生成类
    • interceptor:SpringBoot 拦截器
    • service:Service层,里面还有一层impl目录
    • util:一些工具类可以放在里面
    • mapper:用于存放MyBatis逆向工程生成的.xml映射文件
    • static:这个目录存放一些静态文件,简单了解了一下Vue的前后端分离,前台文件以后也需要放在这个目录下面

    Step2 然后我使用application.yml文件代替了application.yml,这个东西结构清晰一点儿,反正用哪个都无所谓,配置好就OK了:

    
    
    ################设置服务端口号##############################
    server:
    port: 8888
    ################### spring配置 ###################
    spring:
    profiles:
    active: dev
    http:
    converters:
    preferred-json-mapper: fastjson
    devtools:
    restart:
    enabled: false #是否开启开发者工具(true/false)
    additional-paths: src/main/java
    aop:
    proxy-target-class: true #false为启用jdk默认动态代理,true为cglib动态代理
    ---

    spring:
    profiles: dev
    datasource:
    url: jdbc:mysql://127.0.0.1:3306/net_car?characterEncoding=UTF-8
    username: root
    password: 1
    driver-class-name: com.mysql.jdbc.Driver
    #Druid连接池配置相关
    druid:
    # 初始大小,最大,最小
    initial-size: 5
    min-idle: 5
    max-active: 200
    # 配置获取连接等待超时的时间
    max-wait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    time-between-eviction-runs-millis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    min-evictable-idle-time-millis: 300000

    ## 该配置节点为独立的节点,有很多同学容易将这个配置放在spring的节点下,导致配置无法被识别
    #mybatis:
    # mapper-locations: classpath:/mapper/**/*Mapper.xml #注意:一定要对应mapper映射xml文件的所在路径
    # type-aliases-package: com.springbootblog.entity # 注意:对应实体类的路径

    #mybatis
    mybatis-plus:
    mapper-locations: classpath:/mapper/**/*Mapper.xml
    #实体扫描,多个package用逗号或者分号分隔
    typeAliasesPackage: com.springbootblog.entity
    typeEnumsPackage: com.springbootblog.entity.enums
    global-config:
    # 数据库相关配置
    db-config:
    #主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
    id-type: id_worker
    #字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
    field-strategy: not_empty
    #驼峰下划线转换
    column-underline: true
    #数据库大写下划线转换
    #capital-mode: true
    #逻辑删除配置
    logic-delete-value: 0
    logic-not-delete-value: 1
    db-type: mysql
    #刷新mapper 调试神器
    refresh: true
    # 原生配置
    configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
    ---
    ##########################################################
    ################### 开发环境的profile ###################
    ##########################################################
    spring:
    profiles: dev
    logging:
    level.root: info
    path: logs/
    file: springboot.log
    level.com.springbootroot: info
    logging.level.org.springframework.web: trace
    logging.level.org.apache: trace
    ####################读取配置文件信息#####################
    jdbc.pwd: test
    my-props: #自定义的属性和值
    simpleProp: simplePropValue
    arrayProps: 1,2,3,4,5
    listProp1:
    - name: abc
    value: abcValue
    - name: efg
    value: efgValue
    listProp2:
    - config2Value1
    - config2Vavlue2
    mapProps:
    key1: value1
    key2: value2

    step 3 主要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.springbootblog</groupId>
    <artifactId>blog</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>blog</name>
    <description>Demo project for Spring Boot</description>

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


    <!--版本配置参数start-->
    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <swagger.version>2.9.2</swagger.version>
    <mybatis-plus-boot-starter.version>3.0-RC1</mybatis-plus-boot-starter.version>
    <druid.version>1.1.10</druid.version>
    <mysql-connector-java.version>5.1.38</mysql-connector-java.version>
    </properties>
    <!--版本配置参数end-->

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

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    <!-- 支持 @ConfigurationProperties 注解 -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
    </dependency>

    <!--MyBatis-->
    <!--MyBatis逆向工程-->
    <!-- 模板引擎 -->
    <!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity-engine-core -->
    <dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
    </dependency>
    <!-- 模板引擎,需要指定 mpg.setTemplateEngine(new FreemarkerTemplateEngine()); -->
    <!--<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.9</version>
    </dependency>-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>

    <!--SpringBoot测试支持-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>

    <!--MySQL-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql-connector-java.version}</version>
    </dependency>
    <!--mysql end-->
    <!--<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>-->

    <!-- druid阿里巴巴数据库连接池 -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
    </dependency>
    <!--SpringBoot热部署-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
    </dependency>


    <!--Swagger2支持-->
    <!--swagger start-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${swagger.version}</version>
    </dependency>
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${swagger.version}</version>
    </dependency>
    <!--swagger end-->

    <!--mybatis-plus 集成 -->

    <!-- mybatis-plus begin -->

    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus-boot-starter.version}</version>
    </dependency>
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus-boot-starter.version}</version>
    </dependency>
    <!--<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <scope>test</scope>
    </dependency>-->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.8.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-test</artifactId>
    </dependency>
    <!-- mybatis-plus end -->

    <!--<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.2.2</version>
    </dependency>
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.2.2</version>
    </dependency>-->
    <!--<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
    </dependency>-->
    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>


    </project>

     

    MyBatis 逆向工程   Generator    工具类生成代码

    step4 

    package com.springbootblog.generator;


    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.generator.AutoGenerator;
    import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
    import com.baomidou.mybatisplus.generator.config.GlobalConfig;
    import com.baomidou.mybatisplus.generator.config.PackageConfig;
    import com.baomidou.mybatisplus.generator.config.StrategyConfig;
    import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
    import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
    import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
    import org.junit.Test;

    /**
    *代码生成器
    * @author zhangyh
    * @date 2018/9/2 11:02
    * @param
    * @return
    *
    */

    public class MpGenerator {
    /**
    * 测试 run 执行
    * <p>
    * </p>
    */
    @Test
    public void generateCode() {
    String packageName = "com.springbootblog";
    boolean serviceNameStartWithI = false;//user -> UserService, 设置成true: user -> IUserService
    generateByTables(serviceNameStartWithI, packageName, "l_sys_user");
    }
    private void generateByTables(boolean serviceNameStartWithI, String packageName, String... tableNames) {
    GlobalConfig config = new GlobalConfig();
    String dbUrl = "jdbc:mysql://127.0.0.1:3306/net_car?characterEncoding=utf8";
    DataSourceConfig dataSourceConfig = new DataSourceConfig();

    dataSourceConfig.setTypeConvert(new MySqlTypeConvert(){
    // 自定义数据库表字段类型转换【可选】
    @Override
    public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
    String t = fieldType.toLowerCase();
    //如果是datetime类型,转换成Date字段类型
    if(t.contains("datetime")){
    return DbColumnType.DATE;
    }
    return super.processTypeConvert(globalConfig,fieldType);
    }
    });
    dataSourceConfig.setDbType(DbType.MYSQL)
    .setUrl(dbUrl)
    .setUsername("root")
    .setPassword("1")
    .setDriverName("com.mysql.jdbc.Driver");
    StrategyConfig strategyConfig = new StrategyConfig();
    strategyConfig
    .setCapitalMode(true)
    .setEntityLombokModel(false)
    .setDbColumnUnderline(true)
    .setNaming(NamingStrategy.underline_to_camel)
    .setInclude(tableNames);//修改替换成你需要的表名,多个表名传数组
    config.setActiveRecord(false)
    .setAuthor("zhangyh@")
    .setOutputDir("d:\TestCodeGen")
    .setFileOverride(true);
    if (!serviceNameStartWithI) {
    config.setServiceName("%sService");
    }
    new AutoGenerator().setGlobalConfig(config)
    .setDataSource(dataSourceConfig)
    .setStrategy(strategyConfig)
    .setPackageInfo(
    new PackageConfig()
    .setParent(packageName)
    .setController("controller")
    .setEntity("entity")
    ).execute();
    }
    private void generateByTables(String packageName, String... tableNames) {
    generateByTables(true, packageName, tableNames);
    }
    }

    RESTful API 设计

    为了实现前后端分离,好的RESTful API是离不开的,正好前一段时间学习了这方面的知识,所以决定先来设计一套RESTful API,之前学习的文章链接在这里:https://www.jianshu.com/p/91600da4df95

    1)引入Swagger2来构造RESTful API:

    既然想弄一下前后端分离,那就彻底一点儿,写后台完全不管前台,前后台的交互靠一套RESTful API和JSON数据来弄,所以需要一个文档来瞅瞅,首先在pox.xml添加相关依赖:

    <!--Swagger2支持-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.2.2</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.2.2</version>
    </dependency>

    2)创建Swagger2配置类:

    在SpringBoot启动类的同级目录下创建Swagger2的配置类【Swagger2】:

    /**
     * Swagger2 配置类
     *
     * @author:wmyskxz
     * @create:2018-06-14-上午 10:40
     */
    @Configuration
    @EnableSwagger2
    public class Swagger2 {
    
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("cn.wmyskxz.blog"))
                    .paths(PathSelectors.any())
                    .build();
        }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("zhangyh个人博客RESTful APIs")
                    .description("原文地址链接:http://blog.didispace.com/springbootswagger2/")
                    .termsOfServiceUrl("http://blog.didispace.com/")
                    .contact("@zhangyh")
                    .version("1.0")
                    .build();
        }
    
    }

    这样,就可以在我们启动项目之后,访问http://localhost:8888/swagger-ui.html地址来查看当前项目中的RESTful风格的API:

    
    
    package com.springbootblog.controller;

    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.metadata.IPage;
    import com.baomidou.mybatisplus.extension.api.ApiController;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.springbootblog.entity.LSysUser;
    import com.springbootblog.service.UserService;
    import io.swagger.annotations.Api;
    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.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    /**
    *@title : JavaClass
    *@author:zyh
    *@createDate:2018/8/31 22:31
    *
    **/
    @Api(value = "RESTful API ", description = "RESTful API ")
    @RestController
    @RequestMapping(value = "/api")
    public class UserController extends ApiController {
    @Autowired
    UserService userService;

    @ApiOperation(value = "RESTful API info", produces = "application/json")
    @ApiImplicitParams({
    @ApiImplicitParam(name = "name", value = "用户名", required = false,
    dataType = "String", defaultValue = "zyh")
    })
    @RequestMapping(value = "userTest", method = RequestMethod.POST)
    @ResponseBody
    public Object userTest(String name) {
    LSysUser lSysUser = userService.selectByPrimaryKey(1L);
    return success(lSysUser);
    }

    /**
    *执行 userList 分页查询操作
    * @author zhangyh
    * @date 2018/9/1 21:57
    * @param
    * @return
    *
    */
    @ApiOperation(value = "用户分页列表", produces = "application/json")
    @ApiImplicitParams({
    @ApiImplicitParam(name = "pageNum", value = "页码", required = false,
    dataType = "long", defaultValue = "1"),
    @ApiImplicitParam(name = "pageSize", value = "页面大小", required = false,
    dataType = "long", defaultValue = "10")
    })
    @PostMapping(value = "/userList")
    public Object findUserPageList(
    HttpServletRequest request
    , HttpServletResponse response
    , Long pageNum
    , Long pageSize) {
    System.out.println("");
    logger.info("");
    Page page = new Page(pageNum, pageSize);
    Page<LSysUser> pages = new Page<LSysUser>();
    pages = userService.findUserPageList(page);
    IPage<LSysUser> userListPage = userService.page(new Page<LSysUser>(1, 5), new QueryWrapper<LSysUser>());
    System.err.println("total=" + userListPage.getTotal() + ", current list size=" + userListPage.getRecords().size());
    userListPage = userService.page(new Page<LSysUser>(1, 5), new QueryWrapper<LSysUser>().orderByDesc("name"));
    System.err.println("total=" + userListPage.getTotal() + ", current list size=" + userListPage.getRecords().size());
    return success(userListPage);
    }
    /**
    *
    * @author zhangyh
    * @date 2018/9/1 23:05
    * @param []
    * @return java.lang.Object
    *
    */
    @ApiOperation(value = "用户信息保存", produces = "application/json")
    @PostMapping(value = "/saveSysUser")
    public Object ssaveSysUser() {
    LSysUser lSysUser = new LSysUser();
    lSysUser = userService.selectByPrimaryKey(1L);
    lSysUser.setUserId(null);
    userService.saveSysUser(lSysUser);
    return success(lSysUser);
    }
    }
     

    简单介绍一下这些Swagger2的注解吧:

    • @ApiOperation:用于给API设置提示信息,就上图中右边显示的那些,默认不写的情况下是value属性,还可以多写一个notes属性,用于详细的描述API,这里就不需要了,都还比较简单;
    • @ApiImplicaitParam:用于说明API的参数信息,加了s的注解同理,写了这个之后呢,我们就可以利用Swagger2给我们的信息页面进行测试了,当然这里没有具体实现,也可以来看一下(下图);

    这里没有具体实现所以就不足以完成测试,等到后台编写的时候再进行测试吧...


    总结

    至此呢,我们项目所需要的准备就差不多完成了,想要去做一个东西必须要清楚的知道要的是一个什么东西,这样才能更加好的完成我们的产品,这也是我喜欢和坚信的事情:方向永远比努力重要!(强行有联系..hhhh)

    另外一个问题: 我在想文章信息和内容分成了两个表的问题,这样的设计我觉得是没有问题的,但是作为前端并不关心这些数据库的设计,他只要能拿到对象就可以了,在设计 API 的时候,就发现获得一篇文章,需要从三个表(文章信息/文章内容/评论)去获取信息并封装返回前端,这就需要自己在后台另外写一个实体类去封装这些信息,这无疑增加了我们的代码工作量,有没有什么好的方法解决呢?

  • 相关阅读:
    玲珑oj 1129 ST
    HDU 3397 线段树区间修改
    bzoj 1798 双标记区间修改线段树
    HDU 4417 BIT or ST
    HDU 2492 BIT/逆序数/排列组合
    uva 12086 线段树or树状数组练习
    cf 833 A 数论
    wcf的DataContractAttribute与DataMenmberAttribute
    wcf服务查看工具
    git学习-综合性文章
  • 原文地址:https://www.cnblogs.com/javajetty/p/9575421.html
Copyright © 2020-2023  润新知