1. 程式人生 > 其它 >Gradle構建微服務專案

Gradle構建微服務專案

先說一下初衷把:為啥突然要用Gradle,沒辦法公司領導說要用,後期自研專案都使用Gradle構建......

1、下載安裝

這個就不說了,網上大家搜尋一下,配置一下環境變數即可

2、Groovy的一些語法Gradle任務、檔案操作等等,大家感興趣可以去看看

// TODO 後期補上來

3、使用Gradle建立SpringBoot工程

首先,Gradle中的依賴方式分為三種:

  • 本地依賴:依賴本地的某一個jar包,具體的可通過檔案集合、檔案樹的方式指定
  • 模組依賴:依賴某個project
  • 直接依賴:依賴的型別 依賴的組名 依賴的名稱 依賴的版本號
dependencies {
    // 本地依賴
    implementation files('lib/mysql.jar','lib/junit.jar') // 依賴本地專案下的lib包中的jar檔案
    implementation fileTree('dir':'lib',includes: ['xxx.jar'],excludes: ['xxx.jar']) // 指定包含某些jar和排除依賴

    // 專案依賴
    implementation project(':專案的名稱')

    // 直接依賴
    implementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    implementation group:'org.junit.jupiter',name:'junit-jupiter-engine',version:'5.8.1' // 完整寫法

}

其次,Gradle依賴配置有5種方式

  • 1、implementation:會將指定的依賴新增到編譯路徑,並且會將該依賴打包到輸出,如jar中,但是這個依賴在編譯時不能暴露給其他模組。一句話:依賴不會傳遞
  • 2、api:使用api配置的依賴會將對應的依賴新增到編譯路徑,並將依賴打包輸出,但是這個依賴是可以傳遞的,比如模組A依賴模組B,B依賴庫C,模組B在編譯時能夠訪問到庫C

注意:api 與 implementation 區別 ===> api 來定義依賴資訊是可以進行依賴傳遞的,而implementation則不會

  • 3、compileOnly:compileOnly修飾的依賴會新增到編譯路徑中,但是不會打包到jar中,因此只能在編譯時訪問,且compileOnly修飾的依賴不會傳遞。
  • 4、runtimeOnly:與compileOnly相反,它修飾的依賴不會新增到編譯路徑中,但是被打包到jar中,執行時使用。
  • 5、annotationProcessor:這個我也沒整明白
1、建立一個工程
2、配置一下IDEA的Gradle構建工具,他預設使用的是wrapper下的gradle。我們改為自己本地安裝的

改為本地安裝的Gradle

3、在build.gradle檔案中加入依賴
plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.3' // 定義SpringBoot版本,不單獨使用
    id 'io.spring.dependency-management' version '1.1.0'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web' //省略版本,原生bom支援,外掛management提供
......
}
4、測試一下

4、使用Gradle建立SSM多模組工程

1、建立父工程

注意:記得把gradle修改為自己本地安裝的gradle

2、一次建立幾個子工程

gradle-ssm-api:前臺門戶端

gradle-ssm-admin:後臺管理端
gradle-ssm-service:業務處理層
gradle-ssm-mapper:持久層訪問資料庫
gradle-ssm-domain:實體類VO,BO,DTO,POJO......
..... 建立過程我就省略了

最終效果:

專案依賴關係:

3、我們先檢查gradle-ssm-parent工程的settings.gradle
rootProject.name = 'gradle-ssm-parent'
include 'gradle-ssm-api'
include 'gradle-ssm-admin'
include 'gradle-ssm-service'
include 'gradle-ssm-mapper'
include 'gradle-ssm-domain'
4、再修改gradle-ssm-parent工程的build.gradle
plugins {
    id 'java'
}

group 'com.qbb'
version '1.0-SNAPSHOT'

// 指定倉庫位置
repositories {
    mavenLocal()
    mavenCentral()
}

test {
    useJUnitPlatform()
}

// 指定子工程的共性資訊
subprojects {
    //新增外掛
    apply plugin: 'java'
    apply plugin: 'java-library'//支援api
    //編碼環境jdk版本
    sourceCompatibility = 17
    //編譯時jdk版本
    targetCompatibility = 17
    group 'com.qbb'
    version '1.0-SNAPSHOT'


    /*指定一下字符集,不然打包時有可能會報錯*/
    //業務編碼字符集,注意這是指定原始碼解碼的字符集[編譯器]
    compileJava.options.encoding "UTF-8"
    //測試編碼字符集,注意這是指定原始碼解碼的字符集[編譯器]
    compileTestJava.options.encoding "UTF-8"
    //編譯JAVA檔案時採用UTF-8:注意這是指定原始碼編碼的字符集【原始檔】
    tasks.withType(JavaCompile) {
        options.encoding = "UTF-8"
    }
    //編譯JAVA檔案時採用UTF-8:注意這是指定文件編碼的字符集【原始檔】
    tasks.withType(Javadoc) {
        options.encoding = "UTF-8"
    }


    //配置外部屬性
    ext {
        spring_version = "5.2.5.RELEASE"
    }

    //依賴的配置
    dependencies {
        //lombok
        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
        testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
        implementation 'log4j:log4j:1.2.17'
        //implementation 'org.slf4j:slf4j-api:1.7.25'
    }
    test {
        useJUnitPlatform()
    }
}

project("gradle-ssm-domain") {
    dependencies {
        // implementation 'org.projectlombok:lombok:1.18.24'
        // 這裡使用api的目的就是為了讓lombok依賴可以進行傳遞,上面我們也說過api和implementation的區別
        api 'org.projectlombok:lombok:1.18.24'
    }
}
project("gradle-ssm-mapper") {
    dependencies {
        api project(':gradle-ssm-domain')
        api 'org.mybatis:mybatis-spring:2.0.6'
        api 'com.alibaba:druid:1.2.8'
        api 'org.mybatis:mybatis:3.5.8'
        api 'mysql:mysql-connector-java:8.0.30'
    }
}
project("gradle-ssm-service") {
    dependencies {
        api project(':gradle-ssm-mapper')
        api 'org.springframework:spring-web:5.2.5.RELEASE'
        api 'org.springframework:spring-test:5.2.5.RELEASE'
        api 'org.springframework:spring-context:5.2.5.RELEASE'
        api 'org.springframework:spring-jdbc:5.2.5.RELEASE'
        api 'org.aspectj:aspectjweaver:1.9.8'
    }
}
project("gradle-ssm-admin") {
    apply plugin: 'war' // 打成war寶
    dependencies {
        implementation project(':gradle-ssm-service')
        implementation 'org.springframework:spring-webmvc:5.2.5.RELEASE'
        implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3'
        implementation "com.fasterxml.jackson.core:jackson-annotations:2.12.3"
        implementation "com.fasterxml.jackson.core:jackson-core:2.12.3"
        compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
        implementation 'jstl:jstl:1.2'
    }
}
project("gradle-ssm-api") {
    apply plugin: 'war'
    dependencies {
        //implementation project(':gradle-ssm-domain')
        implementation project(':gradle-ssm-service')
        implementation 'org.springframework:spring-webmvc:5.2.5.RELEASE'
        implementation "com.fasterxml.jackson.core:jackson-databind:2.12.3"
        implementation "com.fasterxml.jackson.core:jackson-annotations:2.12.3"
        implementation "com.fasterxml.jackson.core:jackson-core:2.12.3"
        implementation 'jstl:jstl:1.2'
    }
}
5、編寫測試類進行測試 (程式碼比較簡單,我直接放在後面的程式碼倉庫了

clear -> build -> 配置本地的tomcat

注意:我這裡用的是JDK17所以相關的版本也是試錯過得,大家JDK如果不是17,需要注意Spring的版本。不然構建會報錯的

Unsupported class file major version 61

到這本以為全部ok了,但是有一個大坑......我替大家踩了!我在發請求的時候後臺查詢資料庫沒問題,但是前臺一致報錯500...

解決辦法:參考Gradle打包lombok不生效

6、看著好像是完成了,但是還不夠還!這個日期時間我們變成了時間戳,我不喜歡

資料庫中的:

我修改了一下build.gradle依賴資訊

plugins {
    id 'java'
}

group 'com.qbb'
version '1.0-SNAPSHOT'

// 指定倉庫位置
repositories {
    mavenLocal()
    mavenCentral()
}

test {
    useJUnitPlatform()
}

// 指定子工程的共性資訊
subprojects {
    //新增外掛
    apply plugin: 'java'
    apply plugin: 'java-library'//支援api
    //編碼環境jdk版本
    sourceCompatibility = 17
    //編譯時jdk版本
    targetCompatibility = 17
    group 'com.qbb'
    version '1.0-SNAPSHOT'


    /*指定一下字符集,不然打包時有可能會報錯*/
    //業務編碼字符集,注意這是指定原始碼解碼的字符集[編譯器]
    compileJava.options.encoding "UTF-8"
    //測試編碼字符集,注意這是指定原始碼解碼的字符集[編譯器]
    compileTestJava.options.encoding "UTF-8"
    //編譯JAVA檔案時採用UTF-8:注意這是指定原始碼編碼的字符集【原始檔】
    tasks.withType(JavaCompile) {
        options.encoding = "UTF-8"
    }
    //編譯JAVA檔案時採用UTF-8:注意這是指定文件編碼的字符集【原始檔】
    tasks.withType(Javadoc) {
        options.encoding = "UTF-8"
    }


    //配置外部屬性
    ext {
        spring_version = "5.3.22"
    }

    //依賴的配置
    dependencies {
        //lombok
        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
        testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
        implementation 'log4j:log4j:1.2.17'
        //implementation 'org.slf4j:slf4j-api:1.7.25'
    }
    test {
        useJUnitPlatform()
    }
}

project("gradle-ssm-domain") {
    dependencies {
        // implementation 'org.projectlombok:lombok:1.18.24'
        // 這裡使用api的目的就是為了讓lombok依賴可以進行傳遞,上面我們也說過api和implementation的區別
//        api 'org.projectlombok:lombok:1.18.24'

        // 解決Gradle打包後lombok不生效
        api 'org.projectlombok:lombok:1.18.24'
        annotationProcessor 'org.projectlombok:lombok:1.18.24'
		
        // 在domain層加入,後續依賴domain的模組可繼續使用
        api 'com.fasterxml.jackson.core:jackson-databind:2.12.3'
        api "com.fasterxml.jackson.core:jackson-annotations:2.12.3"
        api "com.fasterxml.jackson.core:jackson-core:2.12.3"
    }
}
project("gradle-ssm-mapper") {
    dependencies {
        api project(':gradle-ssm-domain')
        api 'org.mybatis:mybatis-spring:2.0.6'
        api 'com.alibaba:druid:1.2.8'
        api 'org.mybatis:mybatis:3.5.8'
        api 'mysql:mysql-connector-java:8.0.30'
    }
}
project("gradle-ssm-service") {
    dependencies {
        api project(':gradle-ssm-mapper')
        api 'org.springframework:spring-web:5.3.22'
        api 'org.springframework:spring-test:5.3.22'
        api 'org.springframework:spring-context:5.3.22'
        api 'org.springframework:spring-jdbc:5.3.22'
        api 'org.aspectj:aspectjweaver:1.9.8'
    }
}
project("gradle-ssm-admin") {
    apply plugin: 'war' // 打成war寶
    dependencies {
        implementation project(':gradle-ssm-service')
        implementation 'org.springframework:spring-webmvc:5.3.22'
//        implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3'
//        implementation "com.fasterxml.jackson.core:jackson-annotations:2.12.3"
//        implementation "com.fasterxml.jackson.core:jackson-core:2.12.3"
        compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
        implementation 'jstl:jstl:1.2'
    }
}
project("gradle-ssm-api") {
    apply plugin: 'war'
    dependencies {
        //implementation project(':gradle-ssm-domain')
        implementation project(':gradle-ssm-service')
        implementation 'org.springframework:spring-webmvc:5.3.22'
//        implementation "com.fasterxml.jackson.core:jackson-databind:2.12.3"
//        implementation "com.fasterxml.jackson.core:jackson-annotations:2.12.3"
//        implementation "com.fasterxml.jackson.core:jackson-core:2.12.3"
        implementation 'jstl:jstl:1.2'
    }
}

在實體類上序列化一下

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

本以為大功告成,結果又報了這個錯

03-Dec-2022 17:59:42.295 涓ラ噸 [http-nio-8080-exec-4] org.apache.catalina.core.StandardWrapperValve.invoke 鍦ㄨ礬寰勪負/ssm鐨勪笂涓嬫枃涓紝Servlet[DispatcherServlet]鐨凷ervlet.service錛堬級寮曞彂浜嗗叿鏈夋牴鏈師鍥犵殑寮傚父Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.time.LocalDateTime]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.ArrayList[0]->com.qbb.User["createTime"])
	com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.ArrayList[0]->com.qbb.User["createTime"])
		at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
		at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276)
		at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
		at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
		at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
		at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
		at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
		at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
		at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
		at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
		at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:400)
		at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1510)
		at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1006)
		at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:456)
		at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)
		at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:290)
		at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:183)
		at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)
		at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:135)
		at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
		at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
		at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
		at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070)
		at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
		at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
		at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:670)
		at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
		at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
		at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
		at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
		at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
		at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
		at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
		at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
		at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
		at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
		at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
		at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
		at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
		at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
		at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
		at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
		at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
		at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
		at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
		at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:891)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1784)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.base/java.lang.Thread.run(Thread.java:833)

解決辦法:加入一個依賴就好了

project("gradle-ssm-domain") {
    dependencies {
        ......
        // 解決 Java 8 date/time type `java.time.LocalDateTime` not supported
        implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0'
        ......
    }
}

至此Gradle構建SSM多模組專案完成

5、使用Gradle建立微服務多模組工程