728x90
반응형

 

티스토리를 사용하는 대부분의 사용자들이 IT업계에서 일하는 걸로 알고있습니다.

 

그래서 코드 리뷰를 할때 코드를 예쁘게 보여주는 툴을 사용해 올리곤 했었죠.

 

https://colorscripter.com/

 

Color Scripter

Simple & Flexible Syntax HighLighter

colorscripter.com

 

 

 

 

하지만 티스토리 에디터가 대규모로 수정되고 문제가 생겼습니다.

 

일단 업데이트 전에는 그냥 붙여넣기만 해도 아래와같이 이쁘게 색상이 입혀진 채로 붙여넣기가 되었습니다.

@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
 

 

 

 

 

 

하지만 업데이트가 되고 난 뒤에 붙여넣기를 하면 아래와 같이 이상하게 보여지게 되었습니다.

@SpringBootApplication

public class Application {

 

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

 

}

Colored by Color Scripter

cs

 

 

 

 

Color Scripter 사이트에서 상단에 여러가지 버튼들이 있습니다.

 

세부설정 버튼을 클릭합니다.

 

 

 

 

위와같이 HTML 태그 자체 복사만 체크하고 저장해도 깔끔하게 나오는것을 확인할 수 있습니다.

 

728x90
반응형
728x90
반응형

 

Thymeleaf 를 구현하다보면 표현식을 꼭 사용하게 됩니다.

 

기본적으로 지원하는 Number Format 함수를 알아보겠습니다.

 

아래의 내용은 Thymeleaf3.0 버전 기준으로 작성되었습니다.

 

 

 

정수 최소값 설정

Array, List, Set또한 설정이 가능합니다.

 

ex) 100 or 001

 

${#numbers.formatInteger(num,3)}

${#numbers.arrayFormatInteger(numArray,3)}

${#numbers.listFormatInteger(numList,3)}

${#numbers.setFormatInteger(numSet,3)}

 

 

 

 

최소 정수 자릿수와 천단위 구분 기호 설정

Array, List, Set또한 설정이 가능합니다.

 

구분자로는 ‘POINT’, ‘COMMA’, ‘WHITESPACE’, ‘NONE’, ‘DEFAULT’  가 있습니다.

 

${#numbers.formatInteger(num,3,'POINT')}

${#numbers.arrayFormatInteger(numArray,3,'POINT')}

${#numbers.listFormatInteger(numList,3,'POINT')}

${#numbers.setFormatInteger(numSet,3,'POINT')}

 

 

 

 

정수, 소수의 최소값 과 자릿수 설정

Array, List, Set또한 설정이 가능합니다.

 

${#numbers.formatDecimal(num,3,2)}

${#numbers.arrayFormatDecimal(numArray,3,2)}

${#numbers.listFormatDecimal(numList,3,2)}

${#numbers.setFormatDecimal(numSet,3,2)}

 

 

 

 

정수, 소수 최소값과 천단위 구분기호 설정

Array, List, Set또한 설정이 가능합니다.

 

${#numbers.formatDecimal(num,3,2,'COMMA')}

${#numbers.arrayFormatDecimal(numArray,3,2,'COMMA')}

${#numbers.listFormatDecimal(numList,3,2,'COMMA')}

${#numbers.setFormatDecimal(numSet,3,2,'COMMA')}

 

 

 

 

정수, 소수 설정후 각각의 천단위 구분기호 설정

Array, List, Set또한 설정이 가능합니다.

 

${#numbers.formatDecimal(num,3,'POINT',2,'COMMA')}

${#numbers.arrayFormatDecimal(numArray,3,'POINT',2,'COMMA')} ${#numbers.listFormatDecimal(numList,3,'POINT',2,'COMMA')}

${#numbers.setFormatDecimal(numSet,3,'POINT',2,'COMMA')}

 

 

 

 

통화 환율 설정

${#numbers.formatCurrency(num)}

${#numbers.arrayFormatCurrency(numArray)}

${#numbers.listFormatCurrency(numList)}

${#numbers.setFormatCurrency(numSet)}

 

 

 

 

퍼센트 설정

${#numbers.formatPercent(num)}

${#numbers.arrayFormatPercent(numArray)}

${#numbers.listFormatPercent(numList)}

${#numbers.setFormatPercent(numSet)}

 

 

 

정수, 소수 최소값 설정 후 퍼센트 설정

${#numbers.formatPercent(num, 3, 2)}

${#numbers.arrayFormatPercent(numArray, 3, 2)}

${#numbers.listFormatPercent(numList, 3, 2)}

${#numbers.setFormatPercent(numSet, 3, 2)}

 

 

 

 

유틸리티 메서드

x 에서 y까지 정수의 시퀀스 생성

 

${#numbers.sequence(from,to)}

${#numbers.sequence(from,to,step)}

 

 

 

 

공식적으로 Thymeleaf에서 지원하는 Number Format 함수를 알아보았습니다.

 

728x90
반응형
728x90
반응형

 

Spring Boot 의 기본 템플릿 엔진은 Thymeleaf 로 사용되고 있습니다.

 

Jpa 의 저장 또한 LocalDateTime 으로 아래처럼 사용하고 있습니다.

 

 

 

일반적인 방법으로는 java.util.date 객체를 사용하고 있지만 Java8 에서는 LocalDateTime 을 사용하도록 권장하고 있기때문에 Format 방식도 조금 다르게 진행합니다.

 

그래서 간단하게 Thymeleaf 3.0에서 Format하는 방식을 설명하겠습니다.

 

백엔드에서 아래와같이 model로 넘기는 가정으로 진행하겠습니다.

 

model.addAttribute("standardDate", new Date());

model.addAttribute("localDateTime", LocalDateTime.now());

model.addAttribute("localDate", LocalDate.now());

model.addAttribute("timestamp", Instant.now());

 

 

 

 

날짜  어떻게 백엔드쪽에 설정 되었는지에 상관없이 , 그것은 선택된 표준에 따라 보여 질 것입니다. 

 

standardDate는 #에 의해 처리 될 것입니다 날짜 유틸리티입니다. 새로운 LocalDateTime, LocalDate  Instant 클래스는 # temporals 유틸리티에 의해 처리됩니다 . 

 

<h1>Format ISO</h1>

<p th:text="${#dates.formatISO(standardDate)}"></p>

<p th:text="${#temporals.formatISO(localDateTime)}"></p>

<p th:text="${#temporals.formatISO(localDate)}"></p>

<p th:text="${#temporals.formatISO(timestamp)}"></p>

 

 

 

자동으로 하지 않고 원하는 format을 설정하는 방식입니다.

 

<h1>Format manually</h1>

<p th:text="${#dates.format(standardDate, 'dd-MM-yyyy HH:mm')}"></p>

<p th:text="${#temporals.format(localDateTime, 'dd-MM-yyyy HH:mm')}"></p>

<p th:text="${#temporals.format(localDate, 'MM-yyyy')}"></p>

 

 

 

 

 

# temporals.format (...)을 사용 하여 Instant 클래스를 처리 할 수 ​​없습니다 . 

 

UnsupportedTemporalTypeException 이 발생 합니다. 또한 LocalDate의 서식 지정은 특정 날짜 필드 만 지정하고 시간 필드를 건너 뛰는 경우에만 가능합니다.

 

자세한 설명은 아래의 url을 통해 확인하실수 있습니다.

 

https://www.baeldung.com/dates-in-thymeleaf

 

How to Work with Dates in Thymeleaf | Baeldung

A quick and practical guide to working with dates in Thymeleaf

www.baeldung.com

728x90
반응형
728x90
반응형

 

새로운 Android Studio 버전을 설치 하였거나 포멧을 한 뒤에 기존에 NDK를 사용하던 프로젝트를 열고 빌드 했을때 아래와 같은 에러메시지가 출력됬습니다.

 

 

 

진짜 안드로이드 에러는 검색말고는 절대 혼자 해결할 수 없는것 같네요.

 

문제는 NDK 관련 SDK 설치가 되어있지 않아서 발생된 오류로 NDK 를 설치해서 처리해보도록 하겠습니다.

 

Android Studio 메뉴에서 Preferences 로 이동합니다.

 

 

 

Appearance & Behavior > System Settings > Android SDK 메뉴를 클릭합니다.

 

우측 화면에서 SDK Tools 탭을 클릭하면 아래와 같은 화면이 나옵니다.

 

 

CMake 와 NDK 가 설치되지 않아 설치를 진행하였습니다.

 

 

 

NDK 버전이 높으면 Gradle 버전도 높아져야 하기 때문에 상황에 맞게 대처를 해야될것같습니다.

 

위와 같은 방법으로도 처리가 안될 수 있으니 에러로그를 천천히 살펴 보시기 바랍니다.

728x90
반응형
728x90
반응형

 

Spring Boot 2.x 로 개발을 하다보면 어마어마한 문제들이 많이 발생합니다.

 

최근 보안정책을 준수하기 때문에 일반적으로 사용이 가능한 부분들도 보안취약점으로 구분되기도 하죠.

 

이번에도 VirtualKeypad 사용하는 프로젝트에서 Spring Security 를 적용하면서 생긴 문제를 해결했습니다.

 

https://gigas-blog.tistory.com/100

 

WebPonent Virtual Key - HTML 보안 키패드

웹과 하이브리드 앱에서 사용할 수 있는 보안키패드를 소개하겠습니다. HTML 기반으로 다양한 환경에서 사용이 가능하다는 장점이 있는 VirtualKey 입니다. 주민번호를 입력하는곳과 비밀번호 등 개인정보에 민감..

gigas-blog.tistory.com

 

 

 

VirtualKeypad 는 html 기반으로 iFrame 을 띄우는 방식으로 만들어진 솔루션입니다.

 

하지만 Security 적용을 하니 아래와 같은 오류들이 뿜어져나왔습니다.

 

 

Refused to display 'http://localhost:9050/keypad/keypad-core.html' in a frame because it set 'X-Frame-Options' to 'deny'.

 

Uncaught DOMException: Blocked a frame with origin "http://localhost:9050" from accessing a cross-origin frame.

 

X-Frame-Options'를 'deny'로 설정 했기때문에 keypad-core.html 프레임 표시를 거부했다고 나오고,

 

Uncaught DOMException : 원본 "http : // localhost : 9050"이 교차 출처 프레임에 액세스하지 못하도록 프레임을 차단했다고 나옵니다.

 

 

 

 

이런저런 에러를 보다보니 정말 많은 경험이 되는것 같습니다..

 

CrossOrigin 이라는것도 찾아보고. Cors설정도 찾아봤지만 어떤 문제인지 확인조차 어려워서 이설정은 아닌것같아 첫번째 오류메시지 기준으로 찾아보기 시작했습니다.

 

'X-Frame-Options' to 'deny'. 이 부분을 처리 해줘야하는데 DOMException 이 나와서 javascript 문제인줄 알고 VirtualKeypad 설정 js 파일을 찾아보았지만 없었습니다.

 

다시 원점으로 돌아가 Spring Security 적용전에는 문제 없이 되었으니 Spring Security 설정으로 가능할거라는 생각으로 다시 검색을 했습니다.

 

찾아보니 Spring Security 는 기본적으로  X-Frame-Options Click jacking 공격 막기 설정이 되어있습니다.

 

iFrame 을 사용하기 때문에 설정이 해주어야 합니다.

 

 

 

 

 

Xml 로 설정도 가능하지만 SpringBoot 에서는 Java로 구성하기 때문에 Java 로 작성합니다.

 

Spring Security 설정을 하는 WebSecurityConfigurerAdapter.configure(HttpSecurity http) 메서드에 작성을 하겠습니다.

 

X-Frame-Options 를 비활성화 하는 설정이지만 보안적인 이슈가 발생할 수 있습니다.

 

http.headers().frameOptions().disable();

 

 

 

동일 도메인에서는 iframe 접근이 가능하도록 X-Frame-Options를 sameOrigin() 으로 설정하면 됩니다.

 

http.headers().frameOptions().sameOrigin();

 

 

 

Java로 간단하게 설정이 가능하지만 Spring Boot 에서는 강력한 properties 파일로 설정이 가능합니다.

 

security.headers.frame = false

 

 

 

 

이 설정 하나로 iFrame 사용하는 프로젝트에서 문제없이 진행할 수 있습니다.

 

728x90
반응형
728x90
반응형

이 글은 Thymeleaf 3.0 버전 기준으로 작성되었습니다.

 

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

 

Tutorial: Using Thymeleaf

1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a

www.thymeleaf.org

 

 

 

 

현재 회사 프로젝트에서 Thymeleaf 로 JSP 를 대신해 화면을 구현하고 있습니다.

 

Tiles 처럼 layout 을 만들어서 진행하려고 찾고 진행해보려고 찾아보니 thymeleaf-layout-dialect 를 사용하여 구현하는 글이 많았습니다.

 

gradle 기준 implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' 의존성 주입을 받아 진행하였습니다.

 

그런데 아무리 해봐도 실행되지 않았습니다.

 

찾아보니 3.0 버전에선 사용이 불가능하다고 하고. 그래도 기존에 돌아가던 코드를 깃헙에서 받아 실행해보았지만 역시 안되네요.

 

그래서 그냥 Thymeleaf 3.0 문서를 보고 구현해보았습니다.

 

 

 

 

 

layout 구현부 입니다.

 

th:fragment="layout(title, content)" 이 부분이 상속을 받을수 있게 해줍니다.

 

fragment 를 생성하면서 함수 인자로 title 과 content 를 받고 있습니다.

 

<title th:replace="${title}">Layout Title</title> 변수를 출력하는 코드로 동적 title 사용이 가능합니다.

 

<div th:replace="${content}"></div> 동적으로 content 를 출력하는 코드 입니다.

 

<!DOCTYPE html>
<html th:fragment="layout(title, content)" xmlns:th="http://www.thymeleaf.org">
<head>
    <title th:replace="${title}">Layout Title</title>
</head>

<body>

    <h1>Layout H1</h1>

    <div th:replace="${content}">

        <p>Layout content</p>

    </div>

    <footer>
        Layout footer
    </footer>

</body>
</html>

 

 

 

 

 

 

content 에 들어갈 html 입니다.

 

html 태그에 th:replace="~{layoutFile :: layout(~{::title}, ~{::section})}" 이런식으로 layoutFile 파일을 선택하고 :: 구분자를 넣어주고 layout() 함수를 호출하는 방식입니다.

 

~{title} title 태그를 주입받습니다.

 

~{section} section 태그를 주입받습니다.

 

두개다 역시 head 나 body 어떤 태그를 사용할 수 있습니다.

 

<!DOCTYPE html>
<html th:replace="~{layoutFile :: layout(~{::title}, ~{::section})}">
<head>
    <title>Page Title</title>
</head>
<body>

<section>

    <p>Page content</p>

    <div>Included on page</div>

</section>
</body>

 

 

 

 

 

 

이대로 실행하면 layout 이 정해진 html 의 content 부분에 section 태그 내용들이 보일것 입니다.

 

툴에 따라 다르지만 IntelliJ 에서 빨간 밑줄이 나오지만 문제없이 돌아갑니다.

 

eclipse 는 빨간줄이 나오지는 않습니다.

 

이 layout 구현을 하려고 Thymeleaf 2.x 대로 내려가려고 했지만 더 가볍게 사용이 가능하니 Thymeleaf 3.x 를 그대로 사용하는걸 추천드립니다.

 

728x90
반응형
728x90
반응형

 

이전 글에서 Mac OS X 환경 Docker 설치를 진행했었습니다.

 

이번엔 Oracle Database 설치를 진행해보겠습니다.

 

https://gigas-blog.tistory.com/117

 

[Mac OS X] Docker 설치

가벼운 가상환경을 제공하는 Docker가 요즘 이슈 입니다. 쉽고 간편하게 컨테이너를 만든다는게 엄청난 이유인것 같습니다. Docker 에 대해서는 많은 자료가 있으니 따로 알아보셔야 될것 같습니다. Docker를 설치..

gigas-blog.tistory.com

 

 

 

1. 터미널 or GUI 에서 로그인

터미널에서 docker login 을 입력하여 로그인을 진행합니다.

 

 

 

또는 Mac 상단에서 Docker 아이콘을 클릭하여 Sign in / Create Docker ID 메뉴를 클릭합니다.

 

 

Download 할 때 가입했던 계정을 입력합니다.

 

 

2. Oracle 11g 버전 다운로드

docker search oracle-xe-11g 명령어로 많은 이미지를 볼 수 있습니다.

 

docker에서는 이 이미지를 사용하여 다운로드를 진행하게 됩니다.

 

저는 docker pull jaspeen/oracle-xe-11g 명령어를 실행했습니다.

 

 

 

 

 

3. 이미지 실행

이미지를 다운받는다고해서 바로 동작하지 않고, 다운받은 이미지를 실행해야 실제로 사용이 가능합니다.

 

docker images 명령어로 현재 등록된 docker 이미지를 확인할 수 있습니다.

 

 

등록된 이미지가 있으니 docker run -d -p 8080:8080 -p 1521:1521 jaspeen/oracle-xe-11g 명령어로 실행해보겠습니다.

 

 

옵션은 아래와 같습니다.

-d  백그라운드에서 실행

-p 플래그를 사용하여 호스트포트와 컨테이너포트를 매핑 (호스트포트:컨테이너포트)

 

 

 

이렇게 실행이 되면 SQL Developer나 sqlplus 로 접속해 확인해 볼 수 있습니다.

 

간단하게 Docker에서 원하는 이미지를 설치하고 실행까지 하는 방법을 알아보았습니다.

 

728x90
반응형

'프로그래밍 > Oracle' 카테고리의 다른 글

[Oracle] 오늘이 포함된 일주일 날짜 구하기  (0) 2019.04.12
728x90
반응형

 

프로젝트를 진행하는데 기존 시스템이 있는곳이라 DB를 2개 이상 사용해야된다고 합니다.

 

이제 Spring Boot 2.x 를 공부겸 진행하고 있는데 매번 난관이군요.

 

늘 생각하는거지만 실제론 쉬운 코드인데 엄청 어렵게 설명되어있는 글들이 많네요.

 

일단 제가 작성한대로 정리해보겠습니다.

 

 

 

 

 

 

Packacge 구조

다중 DB를 사용할 때에는 package 로 구분하게 됩니다.

 

customer 와 user 로 분류하여 진행하도록 하겠습니다.

-com
    -project
        - customer
            - config
                - CustomerDataSourceConfig.java
            - domain
                - Customer.java
            - repository
                - CustomerRepository.java
        -user
            - config
                - UserDataSourceConfig.java
            - domain
                - User.java
            - repository
                - UserRepository.java
        DataSourceProperties.java
 

 

 

application.yml

Oracle을 사용하기에 JDBC jar를 등록하여 사용했습니다.

 

https://gigas-blog.tistory.com/112

 

[Spring] Gradle 외부 Jar 등록

Spring Boot Project 를 만들면 Maven 이나 Gradle이 기본적으로 설치되어있습니다. 다양한 library 을 쉽고 간편하게 가져와서 쓸수 있지만 외부와의 통신을 허용하지 않는 개발 환경이 있기도 합니다. 이럴때에..

gigas-blog.tistory.com

SpringBoot 2.x 부터 기본 jdbc 로 hikari를 사용하고 있기 때문에 url 이 아닌 jdbc-url로 수정해 주어야 합니다.

 

url 과 driver-class-name, username, password 는 db에 맞는 정보로 수정해야 합니다.

 

customer 와 user 이렇게 2개로 분리하였습니다.

server:
  port: 9099


spring:
  datasource:
    hikari:
      customer:
        jdbc-url: jdbc:oracle:thin:@localhost:1521:xe
        username: -
        password: -
        driver-class-name: oracle.jdbc.OracleDriver
        
      user:
        jdbc-url: jdbc:oracle:thin:@-:-
        username: -
        password: -
        driver-class-name: oracle.jdbc.OracleDriver
 

 

 

DataSourceProperties.java

공통적인 DataSource 부분은 한곳에 정의하였습니다.

 

@Bean 으로 등록할 때 이름을 지정해주어 사용하려고 name을 등록해주었습니다.

 

@Qualifier 로 객체를 선택할 수 있도록 지정해 줍니다.

 

@Primary 주가 되는 DataSource를 지정해 줍니다.

 

@ConfigurationProperties yml이나 properties 속성을 지정해 줍니다.

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.zaxxer.hikari.HikariDataSource;

@Configuration
@EnableConfigurationProperties
public class DataSourceProperties {
    
    @Bean(name = "customerDataSource")
    @Qualifier("customerDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.hikari.customer")
    public DataSource customerDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }
    
    @Bean(name = "userDataSource")
    @Qualifier("userDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari.user")
    public DataSource userDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }
}

 

 

Customer.java

User.java 와 동일합니다.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;

@Entity
@Data
@Table(name = "CUSTOMER")
public class Customer {

  @Id
  @Column(name = "컬럼명")
  private  String column1;

  @Column(name = "컬럼명")
  private String column2;

}
 

 

 

CustomerRepository.java

CustomerRepository 입니다.

import org.springframework.data.jpa.repository.JpaRepository;

import com.project.customer.domain.Customer;

public interface CustomerRepository extends JpaRepository<Customer, Long>{

}

 

 

 

CustomerDataSourceConfig.java

주가 되는 Customer 입니다.

 

User와는 @Primary 차이만 있을뿐 기본적인 설정은 같습니다.

 

@EnableJpaRepositories의 basePackages 는 repository 경로를 설정해주면 됩니다.

 

customerEntityManagerFactory 의 packages 는 domain 경로를 설정해주면 됩니다.

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "customerEntityManagerFactory", 
        transactionManagerRef = "customerTransactionManager", 
        basePackages = { "com.project.customer.repository" })
public class CustomerDataSourceConfig {
    
    @Autowired
    @Qualifier("customerDataSource")
    private DataSource customerDataSource;
    
    @Primary
    @Bean(name = "customerEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(customerDataSource)
                .packages("com.project.customer.domain")
                .persistenceUnit("customer")
                .build();
    }
    
    @Primary
    @Bean("customerTransactionManager")
    public PlatformTransactionManager customerTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(customerEntityManagerFactory(builder).getObject());
    }

}

 

 

 

User.java

User.java 를 생성하였습니다.

 

테이블명과 컬럼명, 변수명은 DB에 맞게 맞춰주면 됩니다.

 

필요에 맞게  @GeneratedValue(strategy=GenerationType.AUTO) 를 생성해주시면 됩니다.

import javax.persistence.Column;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;

@Entity
@Data
@Table(name = "USER")
public class User {

  @Id
  @Column(name = "컬럼명")
  private  String column1;

  @Column(name = "컬럼명")
  private String column2;

}

 

 

UserRepository.java

UserRepository 입니다.

import org.springframework.data.jpa.repository.JpaRepository;

import com.project.user.domain.User;

public interface UserRepository extends JpaRepository<User, String>{

}

 

 

UserDataSourceConfig.java

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "userEntityManagerFactory", 
        transactionManagerRef = "userTransactionManager", 
        basePackages = { "com.project.user.repository" })
public class UserDataSourceConfig {

    @Autowired
    @Qualifier("userDataSource")
    private DataSource userDataSource;

    @Bean(name = "userEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean userEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(userDataSource)
                .packages("com.project.user.domain")
                .persistenceUnit("user")
                .build();
    }

    @Bean("userTransactionManager")
    public PlatformTransactionManager userTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(userEntityManagerFactory(builder).getObject());
    }
}

 

 

 

 

@Primary 설정으로 @Transactional 처리의 기준이 됩니다.

 

기본 설정이 아닌 DB 의 Transaction을 처리 하려면 @Transactional(value = "userTransactionManager") 이런식으로 사용하면 됩니다.

 

간단하게 test를 해보았습니다.

 

각각의 package의 기준으로 분리된 db 를 조회해서 정상적으로 출력이 된다면 잘 적용된것을 알 수 있습니다.

 

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.project.customer.repository.CustomerRepository;
import com.project.user.repository.UserRepository;

import lombok.extern.slf4j.Slf4j;

@RunWith(SpringRunner.class)
@Slf4j
@SpringBootTest
public class SpringBootMultipleJpaApplicationTests {
    
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private CustomerRepository customerRepository;

    @Test
    public void userTest() {
        userRepository.findAll()
            .stream()
            .map(i -> i.toString())
            .forEach(log::info);
    }

    @Test
    public void custoemrTest(){
        customerRepository.findAll()
            .stream()
            .map(i -> i.toString())
            .forEach(log::info);
    }
}
 

 

 

 

부가적으로 설명해야할 부분이 많지만 기본적인 지식을 갖고 있는 분을 기준으로 작성했으며 다른 속성들은 문의 주시면 감사하겠습니다.

 

728x90
반응형
728x90
반응형

 

회사에서 개발을 진행하는데 비밀번호 인증번호를 메일로 전송해야하는 상황이 생겼습니다.

 

Sprint Boot 로 개발을 해보려고 찾아보던중 간단하게 Mail을 전송하는 방법을 정리해보려고 합니다.

 

너무 많은 정보들 중에 꼭 필요한 부분만 처리해야하지만 복잡하게 설명이 되어있어 간략하게 진행해본뒤에 작성하는 글 입니다.

 

개발 환경은 Spring Boot 2.x + Gradle 입니다.

 

 

 

 

선행해야되는 부분은 발송설정을 Gmail 등록할땐 보안 수준이 낮은 앱의 액세서를 꼭 허용해야 합니다.

 

허용하지 않고 진행한다면 아래와같은 메일을 받으실 수 있습니다.

활동확인으로 보안수준이 낮은 앱 차단이 되고 있는지 알수 있습니다.

 

 

Google에서 액세스를 막고 있기 때문에 아래의 URL로 접속해서 허용을 해주시면 됩니다.

 

https://myaccount.google.com/lesssecureapps

 

로그인 - Google 계정

하나의 계정으로 모든 Google 서비스를 Google 계정으로 로그인

accounts.google.com

 

 

build.gradle 에 mail 관련 의존성 주입

/// Mail
implementation 'org.springframework.boot:spring-boot-starter-mail'

 

 

 

application.yml 에서 mail 설정

Gmail 기준으로 작성해보았습니다.

 

host 는 고정값이며, port 는 465 or 587 로 사용가능합니다.

 

id에 @gmail.com 생략 가능하고 password 도 입력해주시면 됩니다.

 

Gmail 인증관련의 TLS 설정을 해줍니다.

# ===============================

# = Email Config

# ===============================

spring:

    mail:

        # Gmail smtp

        host: smtp.gmail.com

 

        # 465 또는 587

        port: 587

 

        # id

        username: 아이디

 

        # password

        password: 비밀번호

 

        # TLS

        properties:

            mail:

                smtp:

                    auth: true

                    starttls:

                        enable: true

cs

 

 

 

 

Java 코드를 작성

EmailService 라는 class 를 생성해주었습니다.

 

@Service 어노테이션을 통해 Bean으로 등록해줍니다.

 

JavaMailSender 과 TemplateEngine 을 생성자로 의존성 주입을 받습니다.

 

받는 메일주소와 제목, 내용을 파라미터로 받고 MimeMessagePreparator 와 MimeMessageHelper 를 구현합니다.

 

build() 함수에서 Thymeleaf 파일경로를 잡아주고 Thymeleaf 에서 사용할 변수를 설정해줄 수 있습니다.

 

지금은 text 라는 변수만 생성해 주었으며 messageHelper.setText() 로 설정한 content 를 넣어주고 두번째 인자에선 html로 사용하겠다는 설정을 해주었습니다.

 

기본값은 text이기 때문에 <html> ... <html> 형태로 받게 되니 꼭 true 값을 넣어줍니다.

import org.springframework.mail.javamail.JavaMailSender;

import org.springframework.mail.javamail.MimeMessageHelper;

import org.springframework.mail.javamail.MimeMessagePreparator;

import org.springframework.stereotype.Service;

import org.thymeleaf.TemplateEngine;

import org.thymeleaf.context.Context;

 

@Service

public class EmailService {

 

    // Java 메일

    private JavaMailSender javaMailSender;

 

    // Thymeleaf Template 사용

    private TemplateEngine templateEngine;

 

    public EmailService(JavaMailSender javaMailSender, TemplateEngine templateEngine) {

        this.javaMailSender = javaMailSender;

        this.templateEngine = templateEngine;

    }

 

    public void sendSimpleMessage(String to, String subject, String text) {

        // Thymeleaf 사용

        MimeMessagePreparator message = mimeMessage -> {

            String content = build(text);

 

            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);

            messageHelper.setTo(to);

            messageHelper.setSubject(subject);

            messageHelper.setText(content, true);

        };

        javaMailSender.send(message);

    }

 

    /*

        Thymeleaf 셋팅

     */

    private String build(String text) {

        Context context = new Context();

        context.setVariable("text", text);

        return templateEngine.process("mail-template", context);

    }

}

Colored by Color Scripter

cs

 

 

 

 

메일을 전송했을때 보여주는 html 파일을 생성

Java에서 등록한 변수를 바로 사용할 수 있습니다.

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="UTF-8">

    <title>Mail Template</title>

</head>

<body>

 

    <span th:text="${text}"></span>

</body>

</html>

Colored by Color Scripter

cs

 

 

 

테스트 코드 작성

test package 에서 EmailSendTest 클래스를 생성하고 테스트를 진행해보면 됩니다.

 

테스트가 정상적으로 진행이 되면 메일을 확인할 수 있습니다.

import com.kcfinance.service.EmailService;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;

 

@RunWith(SpringRunner.class)

@SpringBootTest

public class EmailSendTest {

 

    // 이메일 발송 테스트

    @Autowired

    private EmailService emailService;

 

 

    @Test

    public void sendEmail() {

        String to = "받는주소";

        String subject = "메일 테스트";

        String text = "메일 내용";

 

        emailService.sendSimpleMessage(to, subject, text);

    }

}

 

Colored by Color Scripter

cs

 

728x90
반응형
728x90
반응형

 

Sprint Boot 환경에서 개발을 하는데 IntellJ IDE가 이상해서 STS로 실행해보려고 했습니다.

 

Oracle jdbc 를 설정한 뒤에 나는 문제인것 같은데 '로케일을 인식할 수 없습니다' 라는 오류가 발생했습니다.

 

Mac OS X 업데이트를 하고나면 종종 발생하는 문제라는 글을 많이 볼 수 있었습니다.

 

이럴 경우에 간단하게 해결하는 방법을 알아보겠습니다.

 

 

 

 

상단 메뉴에서 시스템 환경설정으로 들어갑니다.

 

 

언어 및 지역으로 진입합니다.

 

 

지역을 타국으로 변경한 뒤 다시 대한민국으로 변경합니다.

 

이렇게 몇번의 클릭만으로 해결이 되는 오류임을 알 수 있습니다.

 

다시 Sprint Boot 개발을 진행하는데 문제없이 진행 할 수 있었습니다.

 

728x90
반응형

+ Recent posts