일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- jsp
- springboot
- Oracle
- javascript
- laravel
- Web Server
- JVM
- 요리
- linux
- AWS
- redis
- devops
- ReactJS
- Gradle
- php
- Git
- Spring Batch
- elasticsearch
- 맛집
- java
- it
- Design Patterns
- db
- tool
- MySQL
- Spring Boot
- ubuntu
- IntelliJ
- Spring
- jenkins
- Today
- Total
아무거나
Gradle 멀티 프로젝트 구성 본문
2. build.gradle과 settings.gradle을 작성하자
[build.gradle]
buildscript {
ext {
springBootVersion = '2.0.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath "io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE"
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.bkjeon.admin'
version = '0.0.0'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
task initSourceFolders {
sourceSets*.java.srcDirs*.each {
if( !it.exists() ) {
it.mkdirs()
}
}
sourceSets*.resources.srcDirs*.each {
if( !it.exists() ) {
it.mkdirs()
}
}
}
dependencies {
compileOnly('org.projectlombok:lombok')
}
}
project(':admin-api') {
dependencies {
compile project(':admin-common')
}
}
project(':admin-web') {
dependencies {
compile project(':admin-common')
}
}
- 프로젝트 모듈마다 대부분 lombok을 사용한다는 가정하에 공통 gradle파일에 의존성을 추가하였다.
- task initSourceFolders { ... } 를 작성하여 해당 프로젝트 빌드시에 각각 프로젝트 하위모듈을 자동으로 생성하게끔 문법작성
[settings.gradle]
rootProject.name = 'bkjeon-admin'
include 'admin-common', 'admin-api', 'admin-web'
위의 내용을 작성하면 자동적으로 settings.gradle에 include에 추가된 이름들이 실제로 프로젝트 모듈로 추가된다.
3. admin-web 같은 경우는 템플릿엔진과 연동시에 생성된 모듈을 삭제하고 직접 프로젝트를 생성한다. ( ide를 사용한 템플릿엔진이 연동된 프로젝트로 생성하지않으면 직접 연동설정을 해줘야하는 번거로움이 있다. )
4. 프로젝트별 gradle파일을 작성하자.
[admin-api]
// const
def swaggerVersion = '2.8.0'
dependencies {
compile project(':admin-common')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
compile group: 'io.springfox', name: 'springfox-swagger2', version: swaggerVersion
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: swaggerVersion
}
[admin-common]
bootJar{
enabled = false;
}
jar {
enabled = true;
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
runtime('com.h2database:h2')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.47'
}
- 위의 bootJar { ... }, jar { ... } 옵션은 스프링부트 2.0이상 일 때 bootRepackage { enabled = false } 대신에 작성하여야한다.
( bootRepackage의 태스크를 실행할 경우 자동적으로 압출파릴을 재작성한다. 즉 프로젝트를 jar혹은 war로 빌드할지를 설정 혹은 선언할 수 있다. )
[admin-web]
dependencies {
compile project(':admin-common')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('org.springframework.boot:spring-boot-devtools')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
5. 각각의 모듈마다 메인 메소드를 작성하자.
[admin-api]
package com.bkjeon.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
[admin-common]
package com.bkjeon.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CommonApplication {
public static void main(String[] args) {
SpringApplication.run(CommonApplication.class, args);
}
}
[admin-web]
package com.bkjeon.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
6. 테스트할 코드를 작성하자. (테스트는 admin-api에서 진행한다.) 구조는 아래와 같습니다.
# admin-common
[Sample.java]
package com.bkjeon.admin.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
@Table(name = "sample")
public class Sample {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sample_id", nullable = false, length = 11)
private Long sampleId;
@Column(name = "name", nullable = true, length = 30)
private String name;
}
[SampleRepository.java]
package com.bkjeon.admin.repository;
import com.bkjeon.admin.entity.Sample;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SampleRepository extends JpaRepository<Sample, Long> {
}
[SampleService.java]
package com.bkjeon.admin.service;
import com.bkjeon.admin.entity.Sample;
import com.bkjeon.admin.repository.SampleRepository;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SampleService {
@Autowired
private SampleRepository sampleRepository;
@Transactional(readOnly = true)
public List<Sample> getSamples() {
return sampleRepository.findAll();
}
@Transactional(readOnly = true)
public Sample getSample(Long sampleId) {
return sampleRepository.findById(sampleId).get();
}
@Transactional
public Sample setSample(Sample command) {
return sampleRepository.save(command);
}
@Transactional
public Sample putSample(Long sampleId, Sample sample) {
sample = sampleRepository.findById(sampleId).get();
return sampleRepository.saveAndFlush(sample);
}
@Transactional
public void delSample(Long sampleId) {
sampleRepository.deleteById(sampleId);
}
}
# admin-api
[TestController.java]
package com.bkjeon.admin.api.controller;
import com.bkjeon.admin.entity.Sample;
import com.bkjeon.admin.api.service.ApiSampleService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("test")
public class TestController {
@Autowired
private ApiSampleService apiSampleService;
@GetMapping
public List<Sample> getSamples() {
return apiSampleService.getSamples();
}
@GetMapping("{sampleId}")
public Sample getSample(
@PathVariable Long sampleId
) {
return apiSampleService.getSample(sampleId);
}
@PostMapping
public Sample setSample(
@RequestBody Sample command
) {
return apiSampleService.setSample(command);
}
@PutMapping("{sampleId}")
public Sample putSample(
@PathVariable Long sampleId,
@RequestBody Sample command
) {
return apiSampleService.putSample(sampleId, command);
}
@DeleteMapping("{sampleId}")
public void delSample(
@PathVariable Long sampleId
) {
apiSampleService.delSample(sampleId);
}
}
[ApiSampleService.java]
package com.bkjeon.admin.api.service;
import com.bkjeon.admin.entity.Sample;
import com.bkjeon.admin.service.SampleService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ApiSampleService {
@Autowired
private SampleService sampleService;
public List<Sample> getSamples() {
return sampleService.getSamples();
}
public Sample getSample(Long sampleId) {
return sampleService.getSample(sampleId);
}
public Sample setSample(Sample command) {
return sampleService.setSample(command);
}
public Sample putSample(Long sampleId, Sample command) {
Sample sample = sampleService.getSample(sampleId);
sample.setName(command.getName());
return sampleService.putSample(sampleId, sample);
}
public void delSample(Long sampleId) {
sampleService.delSample(sampleId);
}
}
* admin-api와 admin-common 에 service가 둘다 있어서 혼동이 될 것이다. admin-api에 있는 서비스는 비즈니스 로직이 작성될 클래스이고 admin-common에 있는 서비스는 원하는 repository를 연동할때의 서비스이다.
7. 실행할 모듈의 application.yml을 작성하자. ( 실행하게될 모듈은 admin-api이므로 이것만 작성하자. )
[admin-api]
spring:
profiles: local
h2:
console:
enabled: true
jpa:
hibernate:
ddl-auto : update
server:
port: 8080
8. 마지막으로 common모듈을 사용할 다른 프로젝트 빌드시에 common.jar가 제대로 같이 포함되는지 확인해보자.
# 빌드가 되면 해당 프로젝트 루트에 /build/libs/xx.jar 로 파일이 생성된다 해당 경로에서 jar파일의 압축을 풀어보자 ( admin-api-0.0.0.jar 를 예제로 압축을 풀자)
ex) jar xvf {path}/admin-api-0.0.0.jar
-> 압축푼 파일중에 /BOOT-INF/lib/.. 에서 admin-common.jar가 있는지 확인하자.
9. 이제 실행을하면 정상 동작하는것을 확인할 수 있다.
참고소스 : https://github.com/bkjeon1614/java-example-code/tree/master/sample-multi-module
'Java & Kotlin > Gradle & Maven' 카테고리의 다른 글
[gradle] dependency추가해도 계속 안받아지는경우, 캐시 삭제 (0) | 2019.08.17 |
---|---|
[maven] maven 시작하기 (0) | 2019.06.24 |
[Maven] ERROR : Error Message: Type interface com.deploy.model.HistoryMapper is not known to the MapperRegistry. (0) | 2019.03.08 |
[Maven] pom.xml에서 packaging에서 Execution default-testResources of goal ... 에러 (0) | 2019.03.08 |
[Maven] build encoding error (0) | 2019.03.08 |