本篇作为SpringBoot2.1版本的个人开发框架 子章节,请先阅读 SpringBoot2.1版本的个人开发框架 再次阅读本篇文章
项目地址: SpringBoot2.1版本的个人应用开发框架
我们先对core模块进行规划,core模块主要用来编写业务代码,能把一些公用的方法或者类最好都提出去放到common模块下,修改以上文件后,我们对core模块中创建我们写代码以及配置的一些package在core模块下com,ywh.core右键点击 New->package创建包名,这里以我自己的习惯来创建的,可以按照自己的习惯来命名。
core是项目的核心模块,结构初步规划如下:
创建数据库连接是一个很耗时的操作,也很容易对数据库造成安全隐患。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响程序的性能指标。
Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQLParser。Druid支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQLServer、H2等等。 Druid针对Oracle和MySql做了特别优化,比如Oracle的PSCache内存占用优化,MySql的ping检测优化。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等等。
参考:
Druid的GitHub
Druid常见问题集锦
我选择用mysql数据库,在配置Druid之前先要引入mysql的依赖以及Druid的依赖,在core子模块pom.xml文件中引入依赖 ,然后配置 core 下 application-dev.yml 文件,yml文件中大多数是默认配置并且我写了注释很好理解,如果想自定义配置可以参考 Druid的GitHub官方文档 。这里添加JDBC的依赖是因为要连接数库,需要驱动来进行连接,后面添加了MyBatisPlus后就可以去掉了。
<!-- druid连接池的依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!-- mysql驱动依赖 不加版本号会获取最新的 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency> <!-- jdbc驱动依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> <version>2.1.1.RELEASE</version> </dependency> 复制代码
application-dev.yml文件内容,以下内容有省略,具体内容可查看 application-dev.yml
#在这里我没有写driver-class-name: com.mysql.jdbc.Driver这个驱动被弃用了 使用新版com.mysql.cj.jdbc.Driver #控制台提示说自动帮我们找相应的驱动,一般无需手动加载,所以我注释掉了 spring: datasource: type: com.alibaba.druid.pool.DruidDataSource # 初始化Druid druid: # mysql数据库接地址 url: jdbc:mysql://127.0.0.1:3306/ywh_code?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 #driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 # 监控页面的用户名和密码 以及页面地址 stat-view-servlet: login-username: admin login-password: admin enabled: true url-pattern: /druid/* 复制代码
配置好Durid后,我们就可以访问 http://localhost:8082/core/druid/login.html 了。我的端口号是 8082 ,因为我在 application.yml 配置了 context-path: /core ,所以我的访问地址是上面的地址,如果没有配置的话,默认就是 http://localhost:8080/druid/login.html ,登录账户和密码都是admin,监控界面我就不贴了。
配置好Druid以后,就能连接数据库了,如果使用原生的jdbc连接数据库也可以,但是这样就太麻烦了,所以我采用了Myatis的增强版Mybatis-Plus,Mybatis-Plus对Mybatis只做增强不做修改,所以完美兼容了Mybatis,而且也支持自动生成代码给你,以及给用户支持了大量的CRUD的接口,也有很多的优秀案例采用了Mybaits-Plus。
首先在父pom.xml中引入Mybatis-Plus的相关依赖,配置core下application-dev.yml文件,在根据官网中所要求的在启动类中添加@MapperScan(basePackages = "com.ywh.**.dao")来扫描你dao包下所有接口自动注入到Spring的IOC容器中,以便我们使用;依赖分别为:mybatis-plus-boot-starter,freemarker,velocity,后两个为生成代码的时候以哪个为模板,后面会用到,这两个可自行上网搜索查看简介。
<!-- mybatisPlus的依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.6</version> </dependency> <!-- freemarke引擎依赖引入 --> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <!-- velocity引擎依赖引入 --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> 复制代码
application-dev.yml
mybatis-plus: mapper-locations: classpath*:/mybatis-mappers/* # MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名 type-aliases-package: com.ywh.core.entity # 数据库表与实体类的驼峰命名自动转换 configuration: map-underscore-to-camel-case: true 复制代码
@SpringBootApplication(scanBasePackages = "com.ywh") /** * 全局配置,扫描指定包下的dao接口,不用每个dao接口上都写@Mapper注解了 */ @MapperScan(basePackages = "com.ywh.**.dao") public class CoreApplication { public static void main(String[] args) { SpringApplication.run(CoreApplication.class, args); } } 复制代码
配置好以后我们来测试一下是否可以对数据库进行操作了,数据库ywh_code中创建一个user表并且插入几条数据供我们查询。
CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名', `age` tinyint(3) unsigned NOT NULL COMMENT '用户年龄', `gender` tinyint(3) unsigned NOT NULL COMMENT '用户性别', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; INSERT INTO `user` VALUES ('1', 'ywh', '22', '1'); INSERT INTO `user` VALUES ('2', 'lry', '22', '1'); INSERT INTO `user` VALUES ('3', 'whp', '26', '0'); 复制代码
在我们之前创建的Entity实体包中的 ExampleEntity 实体类中编写对应数据库的属性,dao层的 ExampleDao 接口类中写个查询方法,并在springboot的测试类中测试一下我们的配置是否好使,实体类中的属性要有自己的get,set方法,我使用Lombok的注解方式帮我们自动生产get,set方法。首先在父pom.xml引入lombok的依赖包,并在idea中安装lombok的插件,如果认为这种方式太麻烦,可以直接自己生成get,set方法。
<!-- lombok的依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency> 复制代码
在idea中选择File->Settings->Plugins中搜索lombok Plugin插件并安装,如果有连接超时的错误,下载不了的话,可以点击 IDEA中lombok插件下载下载 到本地后,本地安装此插件。
实体类
import lombok.Data; /** * CreateTime: 2018-12-09 18:24 * ClassName: ExampleEntity * Package: com.ywh.core.entity * Describe: * 测试实体类 * * @author YWH */ @Data public class ExampleEntity { private Integer id; private String name; private String age; private String gender; } 复制代码
dao接口
import com.ywh.core.entity.ExampleEntity; import org.apache.ibatis.annotations.Select; import java.util.List; /** * CreateTime: 2018-12-09 18:25 * ClassName: ExampleDao * Package: com.ywh.core.dao * Describe: * 测试例子的Dao层 持久层 * * @author YWH */ public interface ExampleDao { @Select("select * from user") List<ExampleEntity> findAll(); } 复制代码
SpringBoot测试类
import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class CoreApplicationTests { @Autowired private ExampleDao exampleDao; @Test public void contextLoads() { List<ExampleEntity> all = exampleDao.findAll(); System.out.println(all); } } 复制代码
运行测试方法后,输出结果为:
[ExampleEntity(id=1, name=ywh, age=22, gender=1), ExampleEntity(id=2, name=lry, age=22, gender=1), ExampleEntity(id=3, name=whp, age=26, gender=0)] 复制代码
集成了MybatisPlus,关于MybatisPlus的核心功能中的代码生成器可以帮我们大大提升工作效率,不用创建很多的重复工作,AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率,这个代码生成的也不过是我们提前定好的通用的方法,具体的业务代码还是要我们自己来写的,不过在很大程度上帮助了我们很多。
这个功能我是放到了common模块下的,所以我们要对common子模块分一下结构。
创建好目录结构以后,我们创建一个myBatisPlus.properties文件来存放我们常常要改变的变量,这样就不用去代码中去更改了,内容如下:
#此处为本项目src所在路径(代码生成器输出路径) outputDir=/ywh-starter-core/src/main/java #父的包名 setParent=com.ywh.core #是否覆盖文件 默认是false 如果生成的代码有改动的话 在没有确认之前不要改成true 否则会把文件覆盖 丢失代码 fileOverride=false #数据库地址 url=jdbc:mysql://127.0.0.1:3306/ywh_code?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2B8 #数据库驱动 driverClass=com.mysql.cj.jdbc.Driver #数据库用户名 userName=root #数据库密码 passWord=123456 复制代码
我们生成代码是需要根据模板来生成的,MybatisPlus官方默认使用的模板是velocity,它还提供了另外一种模板就是freemarker。
在 com.baomidou.mybatis-plus-generator 包下有一个templates文件夹下有官方提供的模板文件,我们使用的是freemarker模板引擎,后缀名为.ftl的就是了,把带.ftl的文件都复制到我们创建的templates下,当然如果不想自己修改内容,可以不用复制出来,直接使用默认的就可以了,跳过这步就可以。
controller.java.ftl:由于代码过多,这里只贴出一个示例,其他具体代码请前往我的git查看。 freemarker模板
package ${package.Controller}; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.beans.factory.annotation.Autowired; import ${package.Service}.${table.serviceName}; import ${package.Entity}.${table.entityName}; <#if restControllerStyle> import org.springframework.web.bind.annotation.RestController; <#else> import org.springframework.stereotype.Controller; </#if> <#if superControllerClassPackage??> import ${superControllerClassPackage}; </#if> /** * CreateTime: ${date} * ClassName: ${table.controllerName} * Package: ${package.Controller} * Describe: * ${table.comment!} 前端控制器 * @author YWH */ <#if restControllerStyle> @RestController <#else> @Controller </#if> @RequestMapping("<#if controllerMappingHyphenStyle??>${table.controllerName}<#else>${controllerMappingHyphen}</#if>") <#if superControllerClass??> public class ${table.controllerName} extends ${superControllerClass}<${table.serviceName},${table.entityName}> { <#else> public class ${table.controllerName} { </#if> private static final Logger log = LoggerFactory.getLogger(${table.controllerName}.class); @Autowired private ${table.serviceName} service; } 复制代码
接下来我们就可以按着官方的提供的示例来编写我们自己用来生成代码的工具类了,在utils下创建CodeGenerator类,代码详解我就不介绍了,可以根据官方文档来阅读(在上面有贴出地址),生成的代码中虽然是空的,但是因为继承了MybatisPlus提供的类,所以我们已经有了大量的CRUD的接口来供我们使用了,具体的CRUD接口可以参考 MybatisPlus官方CRUD接口
package com.ywh.common.utils; /** * CreateTime: 2018-12-16 13:52 * ClassName: CodeGenerator * Package: com.ywh.common.utils * Describe: * MybatisPlus的代码生成器 * * @author YWH */ public class CodeGenerator { /** * 获取控制台上的内容 * @param tip 控制台输入的内容 * @return */ public static String scanner(String tip){ Scanner scanner = new Scanner(System.in); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("请输入" + tip + ":"); System.out.println(stringBuilder.toString()); if(scanner.hasNext()){ String ipt = scanner.next(); if(StringUtils.isNotEmpty(ipt)){ //输入的不是空就返回 return ipt; } } throw new MybatisPlusException("请输入正确的" + tip +"! "); } public static void main(String[] args) { ResourceBundle resource = ResourceBundle.getBundle("myBatisPlus"); String outPutDir = resource.getString("outputDir"); Boolean fileOverride = false; if("true".equals(resource.getString("fileOverride"))){ fileOverride = true; } String url = resource.getString("url"); String driverClass = resource.getString("driverClass"); String userName = resource.getString("userName"); String passWord = resource.getString("passWord"); String setParent = resource.getString("setParent"); //代码生成器 。。。。。。。由于代码过长,具体代码请前往github查看 } } 复制代码
效果如下: