1. thymeleaf-layout-dialect 추가(관련 글)

 1) 기존

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 2) 변경

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>


Pivotal 이 서울에서 처음 진행하는 행사라고 함.



1. 개발에 집중하기
- 개발자가 개발에 집중 할 수 있어야한다.
- 운영환경에서 손쉽게 모니터링을 할 수 있어야한다. (Spring actuator)
- 배포는 편하게 잘~ 되어야한다.



-> 위 내용을 듣는동안 공감이 많이 갔다. 업무를 진행하면서 세팅한 프로젝트들은 위 내용들을 잘 수행하였는가? 부족한 부분이 어디였을까?를 고민했다. 그러다보니 어느정도는 구축해서 운영하는 듯 했다. 모니터링에 필요한 apm을 운영했고, jenkins를 사용하여 보다 편하게 배포를 진행했던 것 같다. 단, 더 잘 할 수 있었을 것 같은 부분들이 있어서 그 부분들을 좀 더 고민해봐야겠다



2. Netflix
- netflix oss
- Zuul, Eureka.....

-> 자주 들었던 이야기지만, 역시나 대단한 회사다. 내부적으로 만든 프로그램을 오픈소스로 공개하고, 좋은 경험을 공개하는 이 회사가 참 대단하다고 한번 더 느꼈다.


3.PCF(Pivotal Cloud Foundry)
- UI가 잘 되어있다.
- 아~ 있으면 좋겠다~ 하는 기능이 많다! (Spring boot admin과 같이 필요한 기능이 잘 되어 있는 듯 하다.)

-> 나중에 시간을 내서 사용해봐야겠다. 사용해봐야 추후 만들 때 도움이 되니까!!



* 사진은 정말 대충 찍었습니다.

'개인 > 단상' 카테고리의 다른 글

2018-06-05 : Cloud Native Day in seoul  (0) 2018.06.05
2018-05-01  (0) 2018.05.01
Aws re:invent 2017! 후기  (0) 2017.12.02
2016-10-01  (0) 2016.10.01
2016-09-08  (0) 2016.09.08


1. embedded-redis

 - 개발 버전, 프로토 타이핑 등에서 간단하게 사용하기 편함.


2. pom.xml

 - https://github.com/kstyrc/embedded-redis 로 사용할 예정

<!-- embedded-redis -->
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.6</version>
</dependency>


3. Redis Configuration

 - application.yml

spring:
redis:
host: localhost
port: 6379
database: 0

 - Start 및 stop 설정 필요

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.embedded.RedisServer;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;

/**
* Embedded Redis Configration
*
* @author akageun
*/
@Component
public class EmbeddedRedisConfiguration {

@Value("${spring.redis.port}")
private int redisPort;

private RedisServer redisServer;

@PostConstruct
public void startRedis() throws IOException {
redisServer = new RedisServer(redisPort);
redisServer.start(); //Redis 시작
}

@PreDestroy
public void stopRedis() {
redisServer.stop(); //Redis 종료
}

}


 - Template 설정


import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
* Redis Configuration
*
* @author akageun
*/
@Configuration
public class RedisConfig {

@Value("${spring.redis.host}")
private String redisHost;

@Value("${spring.redis.port}")
private int redisPort;

@Value("${spring.redis.database}")
private int redisDatabase;

/**
* Factory
*
* @return
*/
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(redisHost);
jedisConnectionFactory.setPort(redisPort);
jedisConnectionFactory.setDatabase(redisDatabase);
jedisConnectionFactory.setUsePool(true);
return jedisConnectionFactory;
}

/**
* redis Template
*
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(jedisConnectionFactory());

return redisTemplate;
}
}


4. 사용

 - RedisTemplate 사용

@Autowired
private RedisTemplate redisTemplate;


- Code

redisTemplate.opsForValue().set("test", "test1111");
redisTemplate.opsForValue().get("test");


정말 간단하다.

1. banner.txt??


 - 위 이미지를 이쁘게 꾸며보자!.

2. 변경할 파일

 1) src/main/resources/banner.txt 

 

  - banner.txt 내에 원하는 텍스트를 넣으면 된다.


 2) 파일 위치도 변경하기

  (1) 기본 설정(application.yml or application.propertioes)

banner.location=classpath:banner.txt # Banner file location.


- 원하는 경로로 변경하면 된다.


3. 이쁜 text 만들기

 1) https://devops.datenkollektiv.de/banner.txt/index.html 


 2) http://patorjk.com/software/taag/#p=display&f=Ogre&t=Memorynotfound.com




4. 결과

 - 위에서 만든 텍스트를 banner.txt 파일에 넣으면 아래와 같이 볼 수 있다.



5. 좀더 이쁘게

 1) 컬러도 적용 가능하다.

 2) 아래 링크를 들어가면 Spring version 등의 값들을 노출 시킬 수 있다.

- 링크

 3) 이미지를 넣을 수도 있다.

banner.image.location=classpath:banner.gif # Banner image file location (jpg/png can also be used).

banner.image.width= # Width of the banner image in chars (default 76)

banner.image.height= # Height of the banner image in chars (default based on image height)

banner.image.margin= # Left hand image margin in chars (default 2)

banner.image.invert= # If images should be inverted for dark terminal themes (default false)


 4) 이미지를 ancii 로 변경할 수 있다.

- 링크


1. X-Application-Context Header????

 - response header를 보면, 아래와 같은 header 값이 있다. 

 - application name과 port가 노출된다.

X-Application-Context:
application:8080


 - 사용자에게 알려줄 필요없는 정보다.

 - 지우자!!


2. 옵션 설정

management:
add-application-context-header: false

3. 참고 

 - 해당 Header 값은 OncePerRequestFilter에서 ApplicationContext ID를 추가한다.

1. Goal

 - spring boot에 spring-boot-starter-web를 사용 중이다.

 - was가 initialization을 마친 뒤 첫 호출 시점에 dispatcherServlet이 initialization을 한다.

 - was가 initialization을 할 동안 같이 dispatcherServlet이 initialization을 했으면 좋겠다.


2. Log

2018-02-14 13:43:58 [user-PC] [INFO ] o.a.c.c.C.[Tomcat].[localhost].[/]:179 - Initializing Spring FrameworkServlet 'dispatcherServlet'

2018-02-14 13:43:58 [user-PC] [INFO ] o.s.web.servlet.DispatcherServlet:489 - FrameworkServlet 'dispatcherServlet': initialization started

2018-02-14 13:43:58 [user-PC] [INFO ] o.s.web.servlet.DispatcherServlet:508 - FrameworkServlet 'dispatcherServlet': initialization completed in 17 ms


3-1. 수정

 1) jdk 1.8 이하

@Bean
public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
return new BeanFactoryPostProcessor() {

@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bean = beanFactory.getBeanDefinition(
DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);

bean.getPropertyValues().add("loadOnStartup", 1);
}
};
}


 2) jdk 1.8 이상

@Bean
public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
return beanFactory -> {
BeanDefinition bean =
beanFactory.getBeanDefinition(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
bean.getPropertyValues().add("loadOnStartup", 1);
};
}


3-2. 수정(추천!!)

 - application.yml에 해당 내용 추가. (기본으로 -1로 되어 있다.)

spring:
mvc:
servlet:
load-on-startup: 1

  - application.properties일 경우

spring.mvc.servlet.load-on-startup=1


* 참고자료

https://stackoverflow.com/questions/31322670/how-to-configure-dispatcherservlet-load-on-startup-by-spring-boot

아래 소스는 간단한 파일업로드 기능에 ajax를 추가한 간단한 예제 코드 입니다.


1. JAVA Code

 1) Controller

package kr.geun.bootStartSample.www.controller;


import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.multipart.MultipartFile;


@Controller

public class FileUploadController {

    private static final Logger LOG = LoggerFactory.getLogger(FileUploadController.class);


    private final String UPLOADPATH = "C:\\temp";


    /**

     * File Upload Page

     * 

     * @return

     */

    @RequestMapping(value = "/fileupload", method = RequestMethod.GET)

    public String fileUpload() {

        return "fileupload";

    }


    /**

     * File Save

     * 

     * @param uploadfile

     * @return

     */

    @RequestMapping(value = "/fileupload", method = RequestMethod.POST)

    public ResponseEntity<?> fileUpload(@RequestParam("uploadFile") MultipartFile uploadfile) {

        

        try {

            String fileNm = uploadfile.getOriginalFilename();

            String filePath = UPLOADPATH + File.separator + fileNm;


            BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(filePath)));

            stream.write(uploadfile.getBytes());

            stream.close();


        } catch (Exception e) {

            LOG.error(e.getMessage(), e);

            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);

        }


        return new ResponseEntity<>(HttpStatus.OK);

    }

}



 2) Jsp

- HTML Code(fileupload.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>

<form id="upload_file_frm" onsubmit="return false;">

<table>

<tr>

<th>Upload File </th>

<td>

<input id="upload_file" type="file" name="uploadFile" accept="*" />

</td>

<td>

<button id="upload_file_btn">Upload Btn</button>

</td>

</tr>

<tr>

<td colspan="3" id="uload_result_msg"></td>

</tr>

</table>

</form>


- Javascript

<script type="text/javascript">

$(document).ready(function(){

$("#upload_file_btn").click(function(){

uploadFileFunc();

});

});

function uploadFileFunc(){

$.ajax({

url:"/fileupload",

type: "POST",

data: new FormData($("#upload_file_frm")[0]),

enctype: 'multipart/form-data',

        processData: false,

        contentType: false,

        cache: false,

        success: function () {

            $("#uload_result_msg").text("File Upload Success");

        },

        error: function () {

            $("#uload_result_msg").text("File Upload Error");

        }

});

}

</script>


1. Actuator란

어플리케이션의 health check를 손쉽게 할 수 있는 Spring boot 자원이다.


2. pom.xml 에 추가

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-actuator</artifactId>

</dependency>


3. Endpoints

Reference


4. run


5. 기타

  1) App info(application.properties에 위 소스 추가)

info.app.name=Sample

info.app.description=Spring Boot Start Sample 

info.app.version=1.0.0-snapshot


  - 실행화면 


  2) Custom Endpoint(application.properties에 위 소스 추가)

management.context-path=/monitor



  3) 실행화면

1. Spring Boot 특징

 - 따로 tomcat을 사용하지 않고도 내장 tomcat or jetty를 사용할 수 있다.(war로 배포하여 tomcat을 따로 사용할 수도 있다.)

 - 복잡한 Spring의 xml or java config 설정들을 일부 자동으로 설정해준다.


2. Spring boot 시작하기

 1) 프로젝트 만들기

   - STS에서 NEW -> Spring Starter Project 선택 




기본 정보 입력



기본 라이브러리 선택

- spring-boot-starter-web을 추가했다.


 2) Controller 만들기


package kr.geun.bootStartSample.www.controller;


import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;


/**

 * Test Controller

 * 

 * @author geunspage

 *

 */

@RestController

public class TestController {


    /**

     * 테스트 데이터

     * 

     * @return

     */

    @RequestMapping("/test")

    public String getTest() {

        return "{\"result\":true,\"resultMsg\":\"성공입니다.\"}";

    }

}




 3) Project Run

  - Project 이름 우클릭

  - Run As -> Spring Boot App 클릭 




3. 결과 화면

Boot 기본 port는 8080이다.

port 변경을 하고 싶으시면, ~/resources/application.properties 내에 아래 코드를 추가하면 된다.

server.port=8081

+ Recent posts