本篇作為SpringBoot2.1版本的個人開發框架 子章節,請先閱讀SpringBoot2.1版本的個人開發框架再次閱讀本篇文章
後端專案地址:SpringBoot2.1版本的個人應用開發框架
前端專案地址:ywh-vue-admin
建立core子模組的專案結構
我們先對core模組進行規劃,core模組主要用來編寫業務程式碼,能把一些公用的方法或者類最好都提出去放到common模組下,修改以上檔案後,我們對core模組中建立我們寫程式碼以及配置的一些package在core模組下com,ywh.core右鍵點選 New->package建立包名,這裡以我自己的習慣來建立的,可以按照自己的習慣來命名。
core是專案的核心模組,結構初步規劃如下:
- config —— 放一些配置檔案
- controller —— controller層的控制器放在這個包下
- dao —— 對資料庫的一些操作介面放到這裡
- entity —— 業務物件的實體類
- service —— service層的介面與實現類,Impl裡放service的實現類
- system —— 可以放一些core單獨使用的系統類
- mybatis-mappers —— 放Mybatis的xml檔案,這個檔案在resource下建立
Druid介紹
建立資料庫連線是一個很耗時的操作,也很容易對資料庫造成安全隱患。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響程式的效能指標。
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
我選擇用mysql資料庫,在配置Druid之前先要引入mysql的依賴以及Druid的依賴,在父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,監控介面我就不貼了。
整合Mybatis-Plus
配置好Druid以後,就能連線資料庫了,如果使用原生的jdbc連線資料庫也可以,但是這樣就太麻煩了,所以我採用了Myatis的增強版Mybatis-Plus,Mybatis-Plus對Mybatis只做增強不做修改,所以完美相容了Mybatis,而且也支援自動生成程式碼給你,以及給使用者支援了大量的CRUD的介面,也有很多的優秀案例採用了Mybaits-Plus。
專案中配置Mybatis-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,關於MybatisPlus的核心功能中的程式碼生成器可以幫我們大大提升工作效率,不用建立很多的重複工作,AutoGenerator 是 MyBatis-Plus 的程式碼生成器,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模組的程式碼,極大的提升了開發效率,這個程式碼生成的也不過是我們提前定好的通用的方法,具體的業務程式碼還是要我們自己來寫的,不過在很大程度上幫助了我們很多。
這個功能我是放到了common模組下的,所以我們要對common子模組分一下結構。
- base:放基礎的controller、service等
- config:放一些配置類
- entity:放一些基礎的實體類
- mapper:可以放基礎的mapper.xml檔案
- exception:可以放我們自定義的異常類
- utils:放一些公用的工具類
- resources目錄下建立templates放我們後面用到的模板檔案。
建立好目錄結構以後,我們建立一個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
# mapper.xml檔案生成路徑
mapperPath=/ywh-starter-core/src/main/resources/mybatis-mappers/
複製程式碼
配置模板內容
我們生成程式碼是需要根據模板來生成的,MybatisPlus官方預設使用的模板是velocity,它還提供了另外一種模板就是freemarker。
- velocity:Velocity是一個基於Java的模板引擎。它允許任何人使用簡單而強大的模板語言來引用Java程式碼中定義的物件。
- freemarker:FreeMarker是一款模板引擎: 即一種基於模板和要改變的資料, 並用來生成輸出文字的通用工具。
- freemarker的語法可以參考:Freemaker FTL指令常用標籤及語法
在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檢視
}
}
複製程式碼
效果如下: