## 目標
- 使用 Gradle 構建一個多模塊系統,熟悉腳本
- 搭建 SpringBoot ,Spring Security ,Mybatis子模塊,實現基本的 Hello World。可以獨立運行。
總體步驟:新建父工程(gradle) - 配置maven - 新建多個子工程(SpringBoot ,Spring Security ,Mybatis) - 修改父子的build.gradle & 父的settings.gradle - 將無用的文件進行刪除 - 寫相關測試類 - 測試
Pre1: 建本地數據庫
Pre2: 把一個empty項目變成gradle項目: gradle init build
Pre3: git 從分支拉取:git clone -b brachname XXX
git push指定分支:git push origin brachname
1 搭建父工程:父工程沒什么要求,直接new一個gradle的空工程就行。
父模塊建好之后,多了下面紅色框標出的東西,我們需要修改的有build.gradle(配置構建gradle項目時的一些東西,后面會細說,搭建多模塊項目,主要就是在配置各個模塊的這個文件) 和 settings.gradle (配置父子模塊間的依賴關系)。
build.grale文件詳細解釋:https://www.cnblogs.com/caesar-the-great/p/12671179.html
配置父模塊的build.gradle文件
1 /* 2 * This file was generated by the Gradle 'init' task. 3 * 4 * This is a general purpose Gradle build. 5 * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds 6 */ 7 buildscript { 8 repositories { 9 maven { 10 url 'https://maven.aliyun.com/repository/gradle-plugin' 11 } 12 } 13 } 14 plugins { 15 id 'org.springframework.boot' version '2.2.5.RELEASE' apply false 16 id 'io.spring.dependency-management' version '1.0.9.RELEASE' 17 } 18 description="flight-sample" 19 20 ext { 21 22 23 //================= datasource ================ 24 mysqlConnectorJavaVersion = "8.0.19" 25 druidStarterVersion = "1.1.18" 26 druidVersion = "1.0.31" 27 28 mybatisPlusStarterVersion = "3.3.1" 29 30 //=================json======================= 31 fastjsonVersion = "1.2.62" 32 gsonVersion = "2.8.6" 33 jjwtVersion = "0.9.1" 34 35 //=================cache======================= 36 ehcacheVersion = "2.10.6" 37 38 //=================httpclient================= 39 httpclientVersion = "4.5.10" 40 OkHttpVersion = "3.14.4" 41 42 //================= tools==================== 43 GuavaVersion = "26.0-jre" 44 validationApiVersion = "2.0.1.Final" 45 protostuffVersion = "1.6.0" 46 curatorVersion = "4.0.1" 47 jacksonDataformatYamlVersion="2.9.8" 48 49 //================= test ==================== 50 h2Version = "1.4.197" 51 52 } 53 54 configure(allprojects ) { abjects -> 55 apply plugin: 'java' 56 apply plugin: 'maven-publish' 57 repositories { 58 59 maven { 60 url 'https://maven.aliyun.com/nexus/content/groups/public/' 61 } 62 63 maven { 64 url = 'https://repo.spring.io/libs-milestone' 65 } 66 67 maven { 68 url 'https://repo.spring.io/snapshot/' 69 } 70 71 maven { 72 url = 'https://oss.sonatype.org/content/repositories/snapshots/' 73 } 74 75 mavenLocal() 76 77 } 78 } 79 80 configure(subprojects){subjects -> 81 apply plugin: 'java' 82 apply plugin: 'maven' 83 apply plugin: 'maven-publish' 84 apply plugin: 'io.spring.dependency-management' 85 86 group = 'com.td.flight' 87 version = '0.0.1' 88 89 repositories { 90 91 maven { 92 url 'https://maven.aliyun.com/nexus/content/groups/public/' 93 } 94 95 maven { 96 url = 'https://repo.spring.io/libs-milestone' 97 } 98 99 maven { 100 url 'https://repo.spring.io/snapshot/' 101 } 102 103 maven { 104 url = 'https://oss.sonatype.org/content/repositories/snapshots/' 105 } 106 107 mavenLocal() 108 } 109 110 dependencyManagement { 111 imports { 112 mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES 113 } 114 } 115 116 dependencies{ 117 compile "org.springframework.boot:spring-boot-starter-aop" 118 compile "org.springframework.boot:spring-boot-autoconfigure" 119 compile "org.springframework.boot:spring-boot-configuration-processor" 120 compile "org.springframework.retry:spring-retry" 121 testImplementation 'org.junit.platform:junit-platform-commons:1.5.2' 122 testCompile "org.springframework.boot:spring-boot-starter-test" 123 testCompile "org.assertj:assertj-core:3.15.0" 124 } 125 test { 126 useJUnitPlatform() 127 } 128 129 130 compileJava { 131 sourceCompatibility = 1.8 132 targetCompatibility = 1.8 133 options.encoding = "UTF-8" 134 } 135 136 task sourcesJar(type: Jar) { 137 from sourceSets.main.allJava 138 archiveClassifier = 'sources' 139 } 140 141 task javadocJar(type: Jar) { 142 from javadoc 143 archiveClassifier = 'javadoc' 144 } 145 146 }
2 搭建子模塊:boot-demo
type選擇gradle project
這里勾選web依賴(方便后面的測試),然后直接next->finish
這個時候,IDEA一直提示在importing gradle project,仿佛卡死在了這里
因為對於子項目xxx而言,IDEA為它自動生成了一個默認的build.gradle,這句mavenCentral()意思是從maven中心倉庫下載相關依賴,大家都知道去國外的網站下載這些資源肯定是慢的一批
這里我們手動停止build的動作,刪除其他無用配置(上面的父工程的build.gradle已經對所有的子項目做了配置,所以各個子工程里不需要再配了),只留下一句話
然后reimport all gradle projects
配置application.yaml
IDEA為我們默認生成的是application.properities文件,修改后綴為.yaml,然后添加port號
配置controller:添加@RestController 和 @RequestMapping注解,並寫一個方法
啟動測試
處理父子模塊依賴:
修改父工程的settings.gradle,使子模塊boot-demo屬於父模塊,多個子模塊可以使用下面的逗號隔開的書寫格式。寫完include后,IDEA應該會自動重新import, 如果沒有,則按上面的步驟執行reimport all gradle projects
如果gradle項目呈現出下圖所示的所屬結構,則證明子父模塊依賴弄好了。
PS: 每新建一個module,都會生成一個和父工程同級的item (如下圖所示),我們需要選中它,點擊減號清理掉它(不然會有一些不必要的麻煩)
3 搭建子模塊:mybatisplus-demo
參考:https://www.cnblogs.com/happy4java/p/11206801.html
對於Mybatisplus-demo模塊的yaml文件有詳細注釋,方便以后學習:https://www.cnblogs.com/lgg20/archive/2019/10/28/11752946.html
和第2步搭建的boot-demo模塊步驟基本一致,唯一的區別在於build.gradle文件中多引入了一些依賴(紅框中的兩個是必須的,其他的是我為了測試弄的)
build.gradle的腳本
1 configurations { 2 mybatisGenerator 3 } 4 dependencies { 5 implementation 'org.springframework.boot:spring-boot-starter-web' 6 compile "com.baomidou:mybatis-plus-boot-starter:${mybatisPlusStarterVersion}" 7 implementation "mysql:mysql-connector-java:${mysqlConnectorJavaVersion}" 8 //implementation 'org.projectlombok:lombok:1.18.2' 9 implementation 'org.mybatis.generator:mybatis-generator-core:1.3.5' 10 //mybatisGenerator 'mysql:mysql-connector-java:${mysqlConnectorJavaVersion}' 11 //implementation 'tk.mybatis:mapper:3.3.9' 12 //implementation 'tk.mybatis:mapper-spring-boot-starter:2.0.0' 13 annotationProcessor 'org.projectlombok:lombok:1.18.2' 14 compileOnly 'org.projectlombok:lombok:1.18.2' 15 }
配置application.yaml
1 spring: 2 datasource: 3 driver-class-name: com.mysql.cj.jdbc.Driver 4 url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false 5 username: root 6 password: root 7 mybatis-plus: 8 mapper-locations: classpath:/mybatis/*Dao.xml 9 #實體掃描,多個package用逗號或者分號分隔 10 type-aliases-package: com.example.entity 11 global-config: 12 #主鍵類型 0:"數據庫ID自增", 1:"用戶輸入ID",2:"全局唯一ID (數字類型唯一ID)", 3:"全局唯一ID UUID"; 13 id-type: 3 14 #字段策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷" 15 field-strategy: 2 16 #駝峰下划線轉換 17 db-column-underline: true 18 logic-delete-value: 1 19 logic-not-delete-value: 0 20 configuration: 21 map-underscore-to-camel-case: true 22 cache-enabled: false 23 server: 24 port: 8097
新建controller/mapper/entity/config類
controller
1 @RestController 2 public class UserController { 3 4 @Autowired 5 private UserDao UserDao; 6 7 @RequestMapping("/getUserInfoById") 8 public User getUserInfoById(){ 9 //List<User> users = UserDao.selectAll(); 10 User user = UserDao.selectById("1"); 11 return user; 12 } 13 @RequestMapping("/getUserList") 14 public List<User> getUserList(){ 15 List<User> users = UserDao.selectList(new QueryWrapper<>()); 16 return users; 17 } 18 @RequestMapping("/hello") 19 public String hello(){ 20 return "hello"; 21 } 22 @RequestMapping("/insertUserInfo") 23 public String insertUserInfo(){ 24 String result = ""; 25 User user = new User(); 26 user.setName("飛飛飛"); 27 user.setEmail("121213@163.com"); 28 user.setAge(21); 29 int count = UserDao.insert(user); 30 if(count > 0){ 31 result = "插入成功!"; 32 } else { 33 result = "失敗!"; 34 } 35 return result; 36 } 37 }
mapper
1 @Mapper 2 public interface UserDao extends BaseMapper<User> { 3 //User findById(String id); 4 }
entity
1 @Data 2 @TableName("user") 3 public class User{ 4 @TableId 5 private String id; 6 private String name; 7 private int age; 8 private String email; 9 }
config
1 @Configuration 2 @MapperScan("com.example.dao")//掃描文件 3 public class MybatisPlusConfig { 4 5 /* 6 * 分頁插件,自動識別數據庫類型 7 * 多租戶,請參考官網【插件擴展】 8 */ 9 @Bean 10 public PaginationInterceptor paginationInterceptor() { 11 return new PaginationInterceptor(); 12 } 13 }
項目結構
測試
查詢(根據id查詢,為了方便,id在代碼中寫死了)
DB中的數據
插入數據(為了方便,要插入的User對象直接在代碼中寫死了)
DB中的數據
4 搭建子模塊:security-demo
build.gradle文件
1 dependencies { 2 compile project(":mybatisplus-demo") 3 implementation 'org.springframework.boot:spring-boot-starter-security' 4 implementation 'org.springframework.boot:spring-boot-starter-web' 5 annotationProcessor 'org.projectlombok:lombok:1.18.2' 6 compileOnly 'org.projectlombok:lombok:1.18.2' 7 }
測試用的類ref: https://www.cnblogs.com/telwanggs/p/10802851.html
這里說一下我對springSecurity工作原理的初步認識:
shiro架構初步解讀:
解釋:user想和application交互之前,必須先問問security manager同不同意,security manager需要去咨詢一下realm,最終做出決定。
PS: 在搭建mybatisplus-demo模塊的過程中,踩了很多坑,在這里Mark一下
坑1:在build gradle項目的時候,一直提示cannot find implement(),IDEA把問題定位到了build.gradle的文件中的這些位置,做法:在gradle中直接移除子模塊,再reimport (ref步驟2中的PS部分)
坑2:在所有的配置項,測試類寫好之后,開始測試的時候,web頁面一直提示:Whitelabel Error Page,百度了一下:一般出現這個問題的原因就是目錄結構不正確,導致主應用程序類(Main application class)掃描不到controller類。默認情況下主應用程序類(Main application class)只會掃描同一包下的Class。對照了一下自己的,我是把啟動類放到了config包下,所以導致掃描不到其他包,做法:把啟動類拖出來,和com.example同級。
坑3:web頁面訪問查數據的url (getUserInfoById),在web頁面死活不返回數據,只有一個大大的 {}, 里面什么都沒有;同時類里面的user.setXXXX() 等方法報一系列亂碼,當時我就懵逼了,反思了一下:我user的entity用的lombok,然后百度了一下lombok的gradle依賴引入,原來是我的引用方式不對。在gradle4.7版本以后甚至現在gradle5.0了里面這種方式會產生警告,在gradle5.0里面會直接報編譯錯誤。正確使用可以采用如下方式:
1 annotationProcessor 'org.projectlombok:lombok:1.18.2' 2 compileOnly 'org.projectlombok:lombok:1.18.2'
注釋掉的是我寫的錯的。
Lombok的使用:主要是entity中少些了一些setter 和getter等方法。
坑4:本來用的是mybatisplus框架,因為在搭模塊的時候參考了網上的一些資料,竟然陰差陽錯的又引入了另外一個mybatis框架:tk.mybatis,然后就遇到了下面的問題:java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseSelectProvider.<init>(),使用selectByPrimaryKey無法根據主鍵查找獲取結果,解決方法:在寫實體類時,引入@Id注解時,導入正確的包:import javax.persistence.Id
而我導成了:org.springframework.data.annotation.Id (當然最后注釋掉了tk.mybatis相關的依賴,不然會沖突,這里只是mark一下遇到這個問題的解決方法)
同時應該只保留一種Mybatis相關的框架依賴,我原來是兩個共存(不知道是抽什么風加進去的。。。)
PS: 其他細節,后續再補上,今天先寫到這里 --- 20200408-23:03
補充(2020.4.22)
1 刪除項目中的無用文件:
刪除所有子模塊中的gradlew文件
刪除所有子模塊中的gradlew.bat文件
刪除所有子模塊中的gradle文件夾
刪除所有子模塊中的.gitignore文件,在項目最外層配置.gitignore文件,做為整個項目的git提交忽略配置
github: 暫時未公開
PS: 第一次寫博客,難免有不妥的地方,希望理解。