728x90
반응형

 

JPA 를 사용하다보면 정말로 갈아 엎고 싶다는 생각이 많이 드네요.

 

연관관계가 복잡해지다 보면 간단하게 사용할 수 있는 JPA 가 꼭 필요한지 생각이 들곤 합니다.

 

그래서 조금 복잡한 쿼리를 진행하기 위해 MyBatis 를 적용해 보겠습니다.

 

 

 

 

build.gradle 에서 MyBatis 의존성을 추가 합니다.

 

버전은 조금씩 다를 수 있습니다.

dependencies {
    // MyBatis
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.0'
    
}

 

 

 

 

application.yml 파일에서 datasource 설정을 해줍니다.

 

DB를 사용하신다면 무조건 해줘야 하는 부분입니다.

  # ===============================
  # = DATA SOURCE (MARIADB)
  # ===============================
  datasource:
    # 기본 DB
    url: jdbc:mariadb://gigas.synology.me:3306/xxx
    username: xxx
    password: xxx

 

 

 

 

기존에 DAO로 사용하던 부분입니다.

 

Interface에서 메서드를 생성한 후 Mapper를 호출해서 사용하던 방식은 아닙니다.

 

XML이 아닌 java코드로 간단하게 코드를 작성할 수 있습니다.

 

@Mapper 어노테이션으로 Mapper등록을 합니다.

 

@Select 어노테이션처럼 CRUD 를 선언해서 사용할 수 있습니다.

@Mapper
public interface UserMapper {

    /**
     * userNo 로 User 조회
     * @param userNo
     * @return
     */
    @Select("SELECT * FROM user WHERE user_no = #{user_no}")
    User getUser(@Param("user_no") Long userNo);
}

 

 

 

 

테스트 코드로 데이터를 찍어서 잘 돌아가는지 확인할 수 있습니다.

@RunWith(SpringRunner.class)
@SpringBootTest
public class PersistenceTests {


    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void USER_MAPPER_TEST() {

        User user = userMapper.getUser(1L);

        System.err.println(user.toString());
    }
    
}

 

 

 

 

XML 을 사용하시는 분들은 application.yml 에 mybatis 속성을 추가 하여야 합니다.

 

type-aliases-package 는 result 도메인 패키지 경로를 작성합니다.

 

mapper-locations 는 mapper 파일 경로인데 resources 경로안에 mapper 폴더를 만들어 주겠습니다.

# ===============================
# = MYBATIS CONFIG
# ===============================
mybatis:
  type-aliases-package: com.xxx.xxxx
  mapper-locations: mapper/**/*.xml

 

 

 

UserMapper.xml 을 만들어 아래와 같이 select 문을 추가했습니다.

 

여기서 나오는 id 가 Mapper가 UserMapper 메서드와 매핑이 되어집니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.xxx.xxx.persistence.UserMapper">
    <!-- userNo로 User조회 -->
    <select id="findByUserNo" parameterType="Integer" resultType="UserVO">
        SELECT *
            FROM user
            WHERE user_no = #{userNo}
    </select>
</mapper>

 

 

 

 

@Select 어노테이션을 사용하지 않고 아래와 같이 사용합니다.

 

테스트는 동일합니다.

@Mapper
public interface UserMapper {

    /**
     * userNo 로 User 조회
     * @param userNo
     * @return
     */
    UserVO findByUserNo(Long userNo);
}

 

 

 

 

정말 간단하게 설정부분도 필요없이 의존성을 추가하고 Mapper 를 만들어 보았습니다.

 

복잡한 코드는 XML로 따로 분리를 해서 사용하는게 좋고 간단한 쿼리는 어노테이션으로 진행하는걸 추천드립니다.

 

 

 

728x90
반응형

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

[Lombok] Mac OS X Lombok Install  (2) 2019.07.18
[Lombok] Windows OS Lombok Install  (0) 2019.07.17
[STS] SpringToolSuite SVN 연결  (0) 2019.07.14
[Spring] Session Time Out Check  (2) 2019.05.31
[Spring] Thymeleaf Fragment Layout  (0) 2019.05.24
728x90
반응형

 

이전글에서는 Windows OS 에서 Lombok 설치하는 방법을 알아보았습니다.

 

이번글에서는 Mac OS X 에서 Lombok 을 설치해보도록 하겠습니다.

 

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

 

 

 

Lombok Download

아래의 URI로 이동하여 Lombok.jar 파일을 다운로드 합니다.

 

https://projectlombok.org/download

 

Download

 

projectlombok.org

 

 

Version은 계속 업데이트가 되고있습니다.

 

Download 1.18.8 Test 를 클릭해 다운로드 합니다.

 

 

 

Download 가 완료되면 아래와 같이 Jar 파일이 보이게 됩니다.

 

 

 

 

lombok.jar 실행합니다.

마우스 우클릭 -> 열기로 실행이 안된다면 터미널을 실행해서 진행해야 합니다.

 

터미널에서 파일명에 맞게 경로와 이름을 넣어 명령어를 실행합니다.

java -jar lombok-1.18.8.jar

 

 

명령어를 잘 입력하셨다면 아래와 같이 설치화면이 보여지게 됩니다.

 

자동으로 STS나 Eclipse 가 보여지지 않고 있기 때문에 Specify location... 버튼을 클릭해서 파일을 선택해줘야 합니다.

 

Specify location... 버튼을 클릭합니다.

 

 

탐색 화면이 나오는데 Applications -> Contents -> Eclipse 의 경로에 들어갑니다.

 

SpringToolSuite4.ini 라는 파일이 있는데 이 파일을 선택하고 Open 버튼을 클릭합니다.

 

잘 선택이 되었기 때문에 목록에 STS 가 보여지게 됩니다.

 

Install/Update 버튼을 클릭하여 설치를 진행하겠습니다.

 

아래와 같은 설치가 성공이 되었다면 Quit Installer 버튼을 클릭해 종료합니다.

 

 

설치가 잘 되었는지 확인합니다.

 

SpringToolSuite4.ini 파일을 열어보면 

 

-javaagent:/Applications/SpringTollSuite4.app/Contents/Eclipse/lombok.jar 옵션이 추가된것을 확인할 수 있습니다.

 

Mac OS X 역시 약간의 설치 과정이 필요하지만 개발을 더 쉽고 간편하게 진행할 수 있습니다.

 

Mac OS X 에서도 Lombok 을 쉽게 사용해보세요.

 

728x90
반응형

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

[Spring] Spring Boot 2 MyBatis 설정  (2) 2019.09.03
[Lombok] Windows OS Lombok Install  (0) 2019.07.17
[STS] SpringToolSuite SVN 연결  (0) 2019.07.14
[Spring] Session Time Out Check  (2) 2019.05.31
[Spring] Thymeleaf Fragment Layout  (0) 2019.05.24
728x90
반응형

 

Spring이나 Spring Boot를 사용한다면 Lombok을 들어보셨을 거라고 생각합니다.

 

java를 사용해 Entity를 작성할때 getter, setter 를 추가해줘야 하지만 코드가 길어지고 반복작업이 생길때가 많습니다.

 

이러한 작업을 자동으로 처리해주는게 Lombok 입니다.

 

이번글에서는 Windows OS에서 Lombok을 설치해 보도록 하겠습니다.

 

 

 

 

Lombok Download

아래의 URI로 이동하여 Lombok.jar 파일을 다운로드 합니다.

https://projectlombok.org/download

 

Download

 

projectlombok.org

 

 

 

 

lombok.jar 실행합니다.

더블클릭으로 실행이 안된다면 cmd.exe 파일을 실행해서 진행해야 합니다.

 

window + R  키보드를 누른뒤 cmd 를 실행합니다.

 

파일명에 맞게 이름을 넣어 명령어를 실행합니다.

java -jar lombok-1.18.4.jar

 

 

 

 

Specify location... 버튼을 클릭해 STS.exe or Eclipse.exe를 선택후 Install/Update를 클릭하여 진행합니다.

 

 

 

아래와 같은 설치가 성공이 되었다면 Quit Installer 버튼을 클릭해 종료합니다.

 

 

STS.ini or Eclipse.ini 에 옵션을 추가한다.

아래와같이 2줄을 추가하고 STS나 Eclipse 를 재시작 해주시면 됩니다.

-vmargs
-javaagent:lombok.jar

 

 

 

 

이렇게 약간의 설치 과정이 필요하지만 개발을 더 쉽고 간편하게 진행할 수 있습니다.

 

지금은 필수가 되어버린 Lombok 을 쉽게 사용해보세요.

 

728x90
반응형

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

[Spring] Spring Boot 2 MyBatis 설정  (2) 2019.09.03
[Lombok] Mac OS X Lombok Install  (2) 2019.07.18
[STS] SpringToolSuite SVN 연결  (0) 2019.07.14
[Spring] Session Time Out Check  (2) 2019.05.31
[Spring] Thymeleaf Fragment Layout  (0) 2019.05.24
728x90
반응형

 

이전글에서는 SpringToolSuite 에서 SVN Software를 설치해봤습니다.

 

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

 

[STS] SpringToolSuite SVN 설치

Spring Framework 를 생각하면 STS를 빼놓을순 없습니다. Eclipse 기반으로 기존 Eclipse를 사용하셨던 분들이라면 큰 어려움 없이 사용할 수 있습니다. https://spring.io/tools Spring Tools 4 Spring Tools 4 i..

gigas-blog.tistory.com

 

 

 

 

기존에 개인서버에서 SVN을 설치 하였거나 Local에 SVN을 설치하신 분들은 글을 따라 진행하면 되지만

 

SVN Server를 설치하지 않았다면 설치를 우선적으로 진행 후 글을 따라해주시기 바랍니다.

 

SVN Server는 별도의 글을 작성하여 URI를 공유하겠습니다.

 

 

 

 

 

SVN을 설치했으니 SVN 서버와 연결을 해보겠습니다.

 

STS우측 상단의 +버튼을 클릭합니다.

 

 

 

 

아래와 같이 SVN Repository Exploring 을 선택하고 Open 버튼을 클릭합니다.

 

 

 

 

창이 닫히면서 SVN Repositories 라는 탭이 보여지게 됩니다.

 

이 화면에서 다양한 프로젝트들을 연결하고 확인할 수 있습니다.

 

 

 

하지만 지금은 연결된게 없으니 새로 SVN 서버와 연결을 해보겠습니다.

 

SVN Repositories 탭안에서 마우스 우클릭을 합니다.

 

New -> Repository Location... 메뉴를 클릭합니다.

 

 

 

 

 

 

새로운 팝업창이 뜨게 됩니다.

 

Server 에서 SVN을 설치하면 나오는 주소를 입력하게 됩니다.

 

svn:// 으로 시작하는 주소를 넣어주고 Finish 버튼을 클릭합니다.

 

 

 

 

 

SVN에 등록한 Username 과 Password 를 입력해서 자격증명을 합니다.

 

 

 

 

 

정상적으로 증명이 되었다면 svn Server 와 연결이 된것을 확인할 수 있습니다.

 

 

 

 

정말 간단하게 연결을 완료했습니다.

 

다음글에서는 프로젝트를 생성해서 SVN Server에 올리는 방법을 알아보도록 하겠습니다.

 

728x90
반응형

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

[Lombok] Mac OS X Lombok Install  (2) 2019.07.18
[Lombok] Windows OS Lombok Install  (0) 2019.07.17
[Spring] Session Time Out Check  (2) 2019.05.31
[Spring] Thymeleaf Fragment Layout  (0) 2019.05.24
[Spring] Thymeleaf 3 String 날짜 Format  (0) 2019.05.22
728x90
반응형

 

Spring Boot security 를 구현하여 로그인, 로그아웃을 처리하고 있습니다.

 

고객이 로그아웃을 할때에 기록을 남겨 달라는 고객사의 요청이 있었습니다.

 

Security 를 사용할때 편하게 Session이 소멸시점을 체크할 수 있는 방법을 알아보겠습니다.

 

 

 

 

Security 설정에서 logout 을 세션을 초기화하는 코드를 작성합니다.

.and().logout()
      .logoutUrl("/logout")
      .logoutSuccessUrl("/login")  // 로그아웃 성공시 메인 고정
      .invalidateHttpSession(true)    // session invalidate
      .deleteCookies("JSESSIONID")	// cookie
      .permitAll()

 

 

 

Member Entity 입니다.

@Data
@Entity
@Table(name = "테이블")   // 회원 테이블
public class Member implements UserDetails {

	...
    
    /************************************
        UserDetails Override functions
     ************************************/
    /**
     * 사용자에게 부여된 권한
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
    	Set<GrantedAuthority> roles = new HashSet<>();
		role.forEach(e -> {
    		roles.add(new SimpleGrantedAuthority(e.getValue()));
    	});
    	return roles;
    }

    /**
     * 사용자 인증에 사용된 암호
     */
    @Override
    public String getPassword() {
        return memberPw;
    }

    /**
     * 사용자 인증에 사용된 이름
     */
    @Override
    public String getUsername() {
        return memberId;
    }

    /**
     * 사용자 계정 만료 여부
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     * 사용자가 잠김 여부
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    /**
     * 사용자의 자격증명(암호)이 만료 여부
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    /**
     * 사용자의 사용가능여부
     */
    @Override
    public boolean isEnabled() {
        return true;
    }
}

 

 

 

 

 

session 이 소멸하게 되면 아래의 listener 로 진입합니다.

 

SessionDestroyedEvent를 implemets 하면 security 로그인했던 사용자 정보를 담아두고 있습니다.

 

사용자는 UserDetails 를 상속받거나 User를 구현했다면 정보를 조회할 수 있습니다.

 

이때는 request 가 없기 때문에 필요한 정보는 미리 UserDetails 에 넣어둔 뒤 소멸되는 시점에 기록을 남기면 됩니다.

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.session.SessionDestroyedEvent;
import org.springframework.stereotype.Component;

import com.kcknock.primary.domain.Member;
import com.kcknock.primary.domain.MemberState;
import com.kcknock.primary.repository.MemberStateRepository;

/**
 * sessionDestroyed 요청시
 * @author gigas
 */
@Component
public class SessionDestroyListener implements ApplicationListener<SessionDestroyedEvent>{

	@Autowired
	private MemberStateRepository memberStateRepository;
	
	@Override
	public void onApplicationEvent(SessionDestroyedEvent event) {
		List<SecurityContext> securityContexts = event.getSecurityContexts();

        for (SecurityContext securityContext : securityContexts) {
        	
        	Member member = (Member)securityContext.getAuthentication().getPrincipal();
        	
        	MemberState memberState = new MemberState();
        	memberState.setMemberId(member.getMemberId());
        	memberState.setType("로그아웃");
//        	memberState.setDevice("");
//        	memberState.setIpAddr("");
//        	memberState.setOs("");
        	
        	memberStateRepository.save(memberState);
        }
	}
}

 

 

 

 

소멸시점을 check 하는것처럼 생성시점도 아래와 같이 확인할 수 있습니다.

@Component
public class SessionCreateListener implements ApplicationListener<SessionCreationEvent> {

	@Override
	public void onApplicationEvent(SessionCreationEvent event) {
    
    }
}

 

 

 

 

이와같은 코드를 작성하면서 세션이 초기화되면 자동로그아웃을 구현해야겠다는 생각이 들었습니다.

 

하지만 찾아본 결과로는 해당 session 을 처리하는 곳에선 request 정보가 없기때문에 처리가 어렵다는 글들이 많던데..

 

최대한 '자동로그아웃' 기능을 찾아서 글로 남겨보도록 하겠습니다.

728x90
반응형
728x90
반응형

 

다음 예제는 데이터가있는 테이블  렌더링하는 두 가지 다른 흥미로운 조각 사용법을 보여줍니다 . 

 

이것은 변경할 수있는 테이블 헤더와 데이터가 렌더링되는 본문의 두 가지 중요한 부분으로 구성된 재사용 가능한 테이블 조각입니다.

<table>
    <thead th:fragment="fields(theadFields)">
        <tr th:replace="${theadFields}">
        </tr>
    </thead>
    <tbody th:fragment="tableBody(tableData)">
        <tr th:each="row: ${tableData}">
            <td th:text="${row.id}">0</td>
            <td th:text="${row.name}">Name</td>
        </tr>
    </tbody>
    <tfoot>
    </tfoot>
</table>

 

 

 

 

이 테이블을 사용하려면 필드 함수를 사용하여 자체 테이블 헤더를 전달할 수 있습니다 . 

 

헤더는 myFields 클래스  참조됩니다 . 테이블 본문은 데이터를 매개 변수로 tableBody 함수 에 전달하여로드됩니다 .

<body>
    <header th:replace="fragments/general.html :: header"> </header>
    <table>
        <thead th:replace="fragments/tables.html
              :: fields(~{ :: .myFields})">
            <tr class="myFields">
 
                <th>Id</th>
                <th>Name</th>
            </tr>
        </thead>
        <div th:replace="fragments/tables.html
          :: tableBody(tableData=${data})">
        </div>
    </table>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

 

 

 

이것이 최종 페이지의 모양입니다.

<body>
    <div>
        <h1>Thymeleaf Fragments sample</h1>
    </div>
    <div>Data received</div>
    <table>
        <thead>
            <tr class="myFields">
 
                <th>Id</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1001</td>
                <td>John Smith</td>
            </tr>
            <tr>
                <td>1002</td>
                <td>Jane Williams</td>
            </tr>
        </tbody>
    </table>
    <footer>
        <a href="/spring-thymeleaf/fragments">Fragments Index</a> |
        <a href="/spring-thymeleaf/markup">Markup inclussion</a> |
        <a href="/spring-thymeleaf/params">Fragment params</a> |
        <a href="/spring-thymeleaf/other">Other</a>
    </footer>
</body>

 

 

 

템플릿 관리를 쉽게 할 수있는 강력한 도구 인 Thymeleaf Fragments를 사용하여보기 구성 요소를 재사용하는 방법을 살펴 보았습니다.

 

728x90
반응형
728x90
반응형

사이트에 따라서 날짜를 Database에 저장하는 방법이 조금씩 다릅니다.

 

TimeStemp로 하거나 Date로 하거나 String으로 저장하기도 하죠.

 

때에 따라서 Client에서 보여주는 Thymeleaf 에서 Format을 해야합니다.

 

 

 

 

일반적인 LocalDateTime 형태의 객체를 변환하려면 아래와 같이 한다는것을 쉽게 찾아볼 수 있습니다.

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

 

 

 

하지만 String 문자로 저장된 날짜를 yyyy-MM-dd 형태로 출력하려는 방법을 찾아보니 잘 나오지 않았습니다.

 

이런 형태로 하라는 글도 있었는데 너무 길고 지저분해 보이죠..

<th:block th:with="sdf = ${new java.text.SimpleDateFormat('yyyy-MM-dd''T''HH:mm:ss')}">
    <p th:text="${#dates.format(sdf.parse(myData.mdProperties.get('completionDate')), 'dd-MM-yyyy')}" />
</th:block>

 

 

늘 그렇지만 레퍼런스를 봐야겠다고 생각하고 들어갔지만 Thymeleaf Doc 은 간단한것만 나와있고 코드를 찾아가면서 분석해야합니다.

 

그냥 IntelliJ 자동완성기능을 사용하여 찾았습니다..

 

 

 

이렇게 작성해주었고. 내용은 '20190516' 이렇게 저장이 되있는 값을 사용했습니다.

 

현재 형식대로 두번째 인자값으로 넣으주면 기본 format 형태인 yyyy-MM-dd 로 출력이 됩니다.

<td th:text="${#temporals.createDate(user.crtDtm, 'yyyyMMdd')}"></td>

 

어렵지 않는 내용은 검색보단 직접 찾아보는게 빠를때도 있다는것을 다시 느끼게 해주는 시간이었습니다.

 

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
반응형

 

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
반응형

+ Recent posts