Boot 이라기보다는 하나는 Spring 자체 사용하는 방법이다.
Spring에도 CDI의 한정자와 같은 것이 준비되어 있다.

한정자 이름으로 지정

코드 작성

MyInterface.java

package sample.springboot;

public interface MyInterface {
}

Hoge.java

package sample.springboot;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("hoge")
public class Hoge implements MyInterface {
}

Fuga.java

package sample.springboot;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("fuga")
public class Fuga implements MyInterface {
}

Main.java

package sample.springboot;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Main {

    public static void main(String[] args) {
        try (ConfigurableApplicationContext context = SpringApplication.run(Main.class, args)) {
            Main m = context.getBean(Main.class);
            System.out.println("hoge = " + m.hoge.getClass());
            System.out.println("fuga = " + m.fuga.getClass());
        }
    }

    @Autowired @Qualifier("hoge")
    private MyInterface hoge;

    @Autowired @Qualifier("fuga")
    private MyInterface fuga;
}

기동확인

콘솔 출력

hoge = class sample.springboot.Hoge
fuga = class sample.springboot.Fuga

설명

  • @Qualifier 어노테이션을 사용하여 빈의 이름을 지정할 수있다.
  • @Autowired와 함께 @Qualifier에 이름을 지정하여 특정 빈을 주입 할 수있다.
  • CDI로 말하면 @Named적인 사용된다.

한정자 자작

코드 작성

MyQualifier.java

package sample.springboot;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface MyQualifier {
    MyType value();
}

MyType.java

package sample.springboot;

public enum MyType {
    HOGE,
    FUGA,
}

Hoge.java

package sample.springboot;

import org.springframework.stereotype.Component;

@Component
@MyQualifier(MyType.HOGE)
public class Hoge implements MyInterface {
}

Fuga.java

package sample.springboot;

import org.springframework.stereotype.Component;

@Component
@MyQualifier(MyType.FUGA)
public class Fuga implements MyInterface {
}

Main.java

package sample.springboot;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Main {

    public static void main(String[] args) {
        try (ConfigurableApplicationContext context = SpringApplication.run(Main.class, args)) {
            Main m = context.getBean(Main.class);
            System.out.println("hoge = " + m.hoge.getClass());
            System.out.println("fuga = " + m.fuga.getClass());
        }
    }

    @Autowired @MyQualifier(MyType.HOGE)
    private MyInterface hoge;

    @Autowired @MyQualifier(MyType.FUGA)
    private MyInterface fuga;
}

기동 확인

콘솔 출력

hoge = class sample.springboot.Hoge
fuga = class sample.springboot.Fuga

설명

  • @Qualifier으로 자작 어노테이션을 부여하여 한정자를 만드는 것이 가능하다.
  • CDI의 커스텀 qualifier 것과 같은 방식으로 사용할 같다.


코드 작성

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE'
    }
}

apply plugin: 'war'
apply plugin: 'spring-boot'

sourceCompatibility = '1.8'
targetCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
    providedCompile 'org.springframework.boot:spring-boot-starter-tomcat'
}

war {
    baseName = 'spring-boot-war'
}
  • war 플러그인을 로드한다.
  • 기본적으로 내장 서버로 사용하는 Tomcat의 의존관계를 providedCompile로 변경한다.

Main.java

package sample.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class Main extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Main.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}
  • main 메소드를 정의하고 클래스는 다음과 같이 수정한다.
    • SpringBootServletInitializer를 상속한다.
    • configure (SpringApplicationBuilder)을 대체한다.

SampleResource.java

package sample.springboot;

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

@RestController
@RequestMapping("/sample")
public class SampleResource {

    @RequestMapping(method=RequestMethod.GET)
    public String hello() {
        return "Hello Spring Boot!!";
    }
}
  • 테스트 용 리소스 클래스.

동작 확인

war을 빌드한다.

$ gradle war

build/libs 아래 spring-boot-war.jar가 출력되므로 Tomcat에 디플로이한다.

curl으로 동작 확인

$ curl http://localhost:8080/spring-boot-war/sample
Hello Spring Boot!!

비교적 간단히 war 파일을 만들 수 있다.

참고


Main.java

package sample.springboot;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Main {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Main.class);
        app.setBannerMode(Banner.Mode.OFF);

        try (ConfigurableApplicationContext ctx = app.run(args)) {
            Main m = ctx.getBean(Main.class);
            m.hello();
        }
    }

    public void hello() {
        System.out.println("Hello Spring Boot!!");
    }
}
  • SpringApplication#setBannerMode(Banner.Mode)에 Banner.Mode.OFF을 설정하면 배너 표시가 없어진다.


spring-boot-starter-actuator를 의존관계에 추가하면 시스템의 상태를 Web API로 취득 할 수있게 된다.

build.gradle

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
    compile 'org.springframework.boot:spring-boot-starter-actuator'
}

Main.java

package sample.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Main.class, args);
    }
}

응용 프로그램을 시작하고, 일부 URL에 억세스를 해본다.

$ curl http://localhost:8080/health
{"status":"UP"}

$ curl http://localhost:8080/metrics
{"mem":253440,"mem.free":127785,"processors":8,"instance.uptime":51033,"uptime":53546,"systemload.average":-1.0,"heap.committed":253440,"heap.init":262144,"heap.used":125654,"heap":3717632,"threads.peak":16,"threads.daemon":14,"threads":16,"classes":5490,"classes.loaded":5490,"classes.unloaded":0,"gc.ps_scavenge.count":3,"gc.ps_scavenge.time":39,"gc.ps_marksweep.count":1,"gc.ps_marksweep.time":44,"httpsessions.max":-1,"httpsessions.active":0,"counter.status.200.health":1,"counter.status.200.metrics":1,"gauge.response.health":47.0,"gauge.response.metrics":23.0}

다음은 엔드 포인트의 목록이다.

id설명
dump스레드 덤프
env시스템 등록 정보 환경 변수, 등록 정보 파일의 설정 등
health응용 프로그램의 상태
metrics메모리 사용량과 스레드 수, GC 횟수 등
trace최근 방문 기록
shutdownPOST 메소드에 액세스하여 응용 프로그램을 중지 할 수 있다. 기본값은 비활성화 된다.

그 밖에도 여러가지가 있다.

 : 2017-08-31 22:09


코드 작성

로깅(Logging)은 Commons Logging, Log4j, Slf4j, Logback 등 다양한 사용할 수 있다.

Main.java

package sample.springboot;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
@EnableConfigurationProperties
public class Main {

    private static final Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        try (ConfigurableApplicationContext ctx = SpringApplication.run(Main.class, args)) {
            logger.error("error log");
            logger.warn("warn log");
            logger.info("info log");
            logger.debug("debug log");
            logger.trace("trace log");
        }
    }
}

실행 결과

2015-04-29 17:31:25.023 ERROR 8872 --- [           main] sample.springboot.Main                   : error log
2015-04-29 17:31:25.023  WARN 8872 --- [           main] sample.springboot.Main                   : warn log
2015-04-29 17:31:25.023  INFO 8872 --- [           main] sample.springboot.Main                   : info log
  • 기본적으로 INFO 레벨 이상만 출력된다.
  • 형식은 날짜 오류 레베 PID --- [스레드 명] 로거(logger) 이름 : 로그 메시지.

파일 출력

기본적으로 표준 출력만 로그가 출력되지 않지만 로그 파일을 지정하면 파일도 출력되게 된다.
로그 파일은 10MB 씩 회전된다.

파일 이름 지정

$ java -jar build/libs/spring-boot-sample.jar --logging.file=sample.log

$ dir /b *.log
sample.log
  • logging.file에서 출력 파일의 이름을 지정할 수 있다.
  • 편의상 명령 라인 인수로 지정하고 있지만, 속성 파일 등에서도 지정할 수 있다.
  • 파일의 대상 디렉토리가 존재하지 않으면 자동으로 만들어 진다.

폴더 지정

$ java -jar build/libs/spring-boot-sample.jar --logging.path=logs

$ dir /b logs
spring.log
  • logging.path에 로그 파일의 대상을 지정할 수 있다.
  • 로그 파일의 이름은 spring.log가 된다.
  • 디렉토리가 존재하지 않으면 자동으로 만들어 진다.

로거(logger)마다 로그 레벨을 지정

$java -jar build/libs/spring-boot-sample.jar --logging.level.sample.springboot.Main=TRACE

2015-04-29 18:14:17.969 ERROR 8288 --- [           main] sample.springboot.Main                   : error log
2015-04-29 18:14:17.970  WARN 8288 --- [           main] sample.springboot.Main                   : warn log
2015-04-29 18:14:17.970  INFO 8288 --- [           main] sample.springboot.Main                   : info log
2015-04-29 18:14:17.970 DEBUG 8288 --- [           main] sample.springboot.Main                   : debug log
2015-04-29 18:14:17.970 TRACE 8288 --- [           main] sample.springboot.Main                   : trace log
  • logging.level.[로거]=[로그 수준]에 로거에 대한 로그 수준을 지정할 수있다.
  • 로거 이름이 FQCN이되도록하고 있다면, --logging.level.sample.springboot=DEBUG과 같이 패키지 단위로 지정 가능하다.


+ Recent posts