You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
6.9 KiB
Markdown

# Getting Started
## Configuration
### Logging
```
JpaAndRequestLoggingConfig.java : JPA / Web
P6spySqlFormatConfiguration.java - decorator.datasource.p6spy.enable-logging: true
CustomCommonsRequestLoggingFilter.java - org.springframework.web.filter: debug 필수
decorator.datasource.p6spy
Security 비활성
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class})
SecurityJavaConfig.java - 예외 등록
- h2, swagger
Swagger 설정 : SwaggerConfig
resources 설정
WebAndFluxCommonConfig.java - MVC / Flux 공통 사용
MVC / Flux 동시 사용 설정
@EnableWebMvc 만 설정 - @EnableWebFlux는 미사용(사용시 충돌)
MVC application
- @EnableWebMvc
- @SpringBootApplication : exclude에 WebMvcAutoConfiguration.class
```
### swagger
```java
//파라메터 값을 모두 String으로 취급
//String이 아닌 경우 example 값을 부여해야 compile시 WARN 발생 안함
@ApiImplicitParam(name="cmmUserId", value="사용자ID-PK", example = "1")
```
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.5.0/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.5.0/maven-plugin/reference/html/#build-image)
# **Tailwind CSS**
- [Tailwind CSS](https://tailwindcss.com/): 경량의 **CSS** 프레임워크이다. 덩치가 큰 **Bootstrap**과 달리 **CSS**로만 작동하면서 사용자에게 **UI** 구현을 맡기는 컨셉이다. 구현이 직관적이고 자유도가 높아 최근 급속도로 생태계가 확장되고 있다.
- [Tailwind Cheat Sheet](https://nerdcave.com/tailwind-cheat-sheet): **Tailwind CSS**의 모든 클래스를 한 눈에 조회 검색 가능한 사이트이다. 사용이 편리하여 레퍼런스 사이트보다 더 찾게 된다.
- [Tailwind Toolbox](https://www.tailwindtoolbox.com/): **Tailwind CSS** 기반으로 **UI** 구현에 참고할만한 여러 완성 템플릿을 제공한다.
- [Tailwind Components](https://tailwindcomponents.com/): **Tailwind CSS** 기반으로 **UI** 구현에 참고할만한 여러 완성 컴포넌트를 제공한다.
- [Awesome Tailwind CSS](https://github.com/aniftyco/awesome-tailwindcss): **Tailwind CSS** 관련 유용한 유용한 정보들을 소개한다.
- [We build a login using TailwindCSS](https://stefanbauer.me/building-pingping/we-build-a-login-using-tailwindcss): **Tailwind CSS**을 이용한 로그인 폼 제작 과정을 설명한다.
# **Webflux 지원 Database**
1. Postgres (io.r2dbc:r2dbc-postgresql)
2. H2 (io.r2dbc:r2dbc-h2)
3. Microsoft SQL Server (io.r2dbc:r2dbc-mssql)
4. MySQL (com.github.mirromutth:r2dbc-mysql)
5. jasync-sql MySQL (com.github.jasync-sql:jasync-r2dbc-mysql)
### mysql 사용시
```xml
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-pool</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-pool</artifactId>
<version>0.8.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
<version>0.8.1.RELEASE</version>
</dependency>
```
### sample
```java
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Repository;
import io.r2dbc.pool.ConnectionPool;
import io.r2dbc.pool.ConnectionPoolConfiguration;
import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.Result;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Repository
public class DatabaseConfig {
private ConnectionFactory factory;
private ConnectionPool pool;
//연결
@PostConstruct
public void init() {
factory = ConnectionFactories.get("r2dbcs:pool:mysql://비번:아이디@주소:포트/db명");
ConnectionPoolConfiguration configuration = ConnectionPoolConfiguration.builder(factory)
.maxIdleTime(Duration.ofMillis(1000))
.maxSize(20)
.build();
pool = new ConnectionPool(configuration);
}
//단일 셀렉트, 조회할 테이블 데이터가 n개이면 이런식으로 쓰면 안된다.
public Mono<HashMap<Object, Object>> selectSingle() {
Mono<HashMap<Object, Object>> mono = Mono.from(pool.create()).map(connection -> //커넥션 가공
Flux.from(connection.createStatement("select name, desc, date from test where id_=?ids").bind("ids", "2").execute())
.concatMap( result-> //1차 변환
result.map((row, rowMetadata)-> { //결과 재 조립 후 리턴
HashMap<Object, Object> item = new HashMap<>();
item.put("names", row.get("name",String.class));
item.put("desc", row.get("desc",String.class));
item.put("date", row.get("date",Object.class));
return item;
})
).doFinally( (st)->{connection.close();})
).flatMap( ccc -> Mono.from(ccc)); //2차 변환
return mono;
}
//단순 셀렉트 예제
public Flux<HashMap<Object, Object>> selectMany() {
Flux<HashMap<Object, Object>> flux = Flux.from(pool.create()).concatMap(connection -> //커넥션 가공 및 1차 변환
Flux.from(connection.createStatement("select name, desc, date from test where id_=?ids").bind("ids", "2").execute())
.concatMap( result-> //2차 변환
result.map((row, rowMetadata)-> { //결과 재 조립 후 리턴
HashMap<Object, Object> item = new HashMap<>();
item.put("names", row.get("name",String.class));
item.put("desc", row.get("desc",String.class));
item.put("date", row.get("date",Object.class));
return item;
})
).doFinally( (st)->{connection.close();})
);
return flux;
}
//저장 예제
public Mono<? extends Result> insertTest() {
return Mono.from(pool.create()).map( con ->
Mono.from(
con.createStatement(" insert into test(name, desc, date) values (?name, ?desc, ?date) ")
.bind("name", "abcd").bind("desc", "desc").bind("date", LocalDateTime.now()).execute()
).doFinally( st-> con.close()).map( result -> result)
).flatMap( c-> Mono.from(c));
}
}
```