Spring Boot Admin Server, Client config 설정하기

이미지
 Spring Boot로 많은 프로젝트를 진행하게 됩니다. 많은 모니터링 도구가 있지만, Spring Boot 어플리케이션을 쉽게 모니터링 할 수 있는 방법을 소개하려고 합니다.   코드 중심으로 살펴보겠습니다. 1. 어드민 서버 구축 1-1. 디펜던시 추가 dependencies { // https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-server implementation 'de.codecentric:spring-boot-admin-starter-server:2.5.4' } 1-2. 어드민 서버 설정 활성화 @SpringBootApplication @EnableAdminServer public class ServerApplication { public static void main (String[] args) { SpringApplication. run (ServerApplication. class, args) ; } } EnableAdminServer를 하면 됩니다. 2. 클라이언트 서버 설정  예제는 book-client, member-client 2가지 클라이언트, member-client가 2개의 인스턴스 실행으로 작성했습니다.  2-1 디펜던시 추가 dependencies { // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web implementation 'org.springframework.boot:spring-boot-starter-web:2.5.4' // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-actuator implementation 'org.spring...

Spring boot webflux + mysql

스프링 부트의 webflux의 rest api 예제 입니다.


샘플 코드

https://github.com/withccm/spring-webflux-study/tree/feature/webflux-mysql-sample


북 테이블

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bookname` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`)
);


1. 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
runtimeOnly 'mysql:mysql-connector-java'
implementation 'dev.miku:r2dbc-mysql'


2. spring data r2dbc bean 등록

@Configuration
@EnableTransactionManagement
@EnableR2dbcRepositories
public class DataSourceR2DBCConfig extends AbstractR2dbcConfiguration {

@Bean
@Primary
public ConnectionFactory connectionFactory() {
ConnectionFactoryOptions options = ConnectionFactoryOptions.builder()
.option(ConnectionFactoryOptions.DRIVER, "pool")
.option(ConnectionFactoryOptions.PROTOCOL, "mysql")
.option(ConnectionFactoryOptions.HOST, "localhost")
.option(ConnectionFactoryOptions.PORT, 3306)
.option(ConnectionFactoryOptions.DATABASE, "mytest")
.option(ConnectionFactoryOptions.USER, "github")
.option(ConnectionFactoryOptions.PASSWORD, "test1234")
.option(ConnectionFactoryOptions.CONNECT_TIMEOUT, Duration.ofMillis(3000))
.option(Option.valueOf("socketTimeout"), 3000)
.option(Option.valueOf("allowMultiQueries"), true)
.option(Option.valueOf("useSSL"), false)
.build();

ConnectionFactory connectionFactory = ConnectionFactories.get(options);
ConnectionPoolConfiguration configuration = ConnectionPoolConfiguration .builder(connectionFactory)
.build();

return new ConnectionPool(configuration);
}

@Bean
ReactiveTransactionManager transactionManager(ConnectionFactory connectionFactory) {
return new R2dbcTransactionManager(connectionFactory);
}

@Bean
public R2dbcEntityTemplate r2dbcEntityTemplate(ConnectionFactory connectionFactory) {
R2dbcEntityTemplate r2dbcEntityTemplate = new R2dbcEntityTemplate(connectionFactory);
return r2dbcEntityTemplate;
}

}


3. 북 객체 정의

@Table(value = "book")  // @Table 을 사용해야 bean으로 등록이됨
public class Book {

@Id
private Integer id;
private String bookname;
}


4. 레파지토리 정의

public interface BookRepository extends ReactiveCrudRepository<Book, Integer> {
}


5. Handler 정의

@Component
@Slf4j
@RequiredArgsConstructor
public class BookHandler {

private final BookRepository bookRepository;

public Mono<ServerResponse> postBooks(ServerRequest serverRequest) {
Mono<BookRequest> bookRequestMono = serverRequest.bodyToMono(BookRequest.class);
Mono<Book> bookMono = bookRequestMono .map(bookRequest -> Book.builder().bookname(bookRequest.getBookname()).build()) .flatMap(book -> bookRepository.save(book));
return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON).body(bookMono, Book.class);
}

public Mono<ServerResponse> getBooks(ServerRequest serverRequest) {
Flux<Book> bookFlux = bookRepository.findAll();
return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON).body(bookFlux, Book.class);
}

public Mono<ServerResponse> getBook(ServerRequest serverRequest) {
String id = serverRequest.pathVariable("id");

Mono<Book> bookMono = bookRepository.findById(Integer.valueOf(id));
return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON).body(bookMono, Book.class);
}

public Mono<ServerResponse> putBooks(ServerRequest serverRequest) {
String id = serverRequest.pathVariable("id");

Mono<BookRequest> bookRequestMono = serverRequest.bodyToMono(BookRequest.class);
Mono<Book> bookMono = bookRequestMono .map(bookRequest -> Book.builder() .id(Integer.valueOf(id)) .bookname(bookRequest.getBookname()).build())
.flatMap(book -> bookRepository.save(book));
return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON).body(bookMono, Book.class);
}

}


6. Router 정의

@Configuration
public class BookRouter {

@Bean
public RouterFunction<ServerResponse> route(BookHandler bookHandler) {
return RouterFunctions
.route(RequestPredicates.POST("/books")
.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), bookHandler::postBooks)
.andRoute(RequestPredicates.GET("/books")
.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), bookHandler::getBooks)
.andRoute(RequestPredicates.GET("/books/{id}")
.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), bookHandler::getBook)
.andRoute(RequestPredicates.PUT("/books/{id}")
.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), bookHandler::putBooks);
}
}


댓글

이 블로그의 인기 게시물

Spring boot redis cache config

Spring boot redis RedisTemplate

MySQL PK 중복 (duplicate key ) 해결 방법