1. 개요

Ehcache를 Spring Boot와 함께 사용하는 예를 살펴보겠습니다. JSR-107 캐시 관리자 구현을 제공하는 Ehcache 버전 3을 사용합니다 .

예제는 숫자의 제곱을 생성하는 간단한 REST 서비스입니다.

2. 의존성

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.7.2</version></dependency>
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.1</version>
</dependency>     

3. 예시

서비스를 호출하여 숫자를 제곱하고 결과를 JSON 문자열로 반환하는 간단한 REST 컨트롤러를 만들어 보겠습니다.

@RestController
@RequestMapping("/number", MediaType.APPLICATION_JSON_UTF8_VALUE)
public class NumberController {

    // ...

    @Autowired
    private NumberService numberService;

    @GetMapping(path = "/square/{number}")
    public String getSquare(@PathVariable Long number) {
        log.info("call numberService to square {}", number);
        return String.format("{\"square\": %s}", numberService.square(number));
    }
}

이제 서비스를 만들어 봅시다.

Spring이 캐싱을 처리할 수 있도록 메서드에 @Cacheable 어노테이션을 추가합니다. 이 어노테이션의 결과로 Spring은 Square 메소드 에 대한 호출을 가로채고 Ehcache를 호출하기 위해 NumberService 의 프록시를 생성합니다.

사용할 캐시의 이름과 선택적으로 키를 제공해야 합니다. 캐시되는 항목을 제한하는 조건을 추가할 수도 있습니다.

@Service
public class NumberService {

    // ...
    @Cacheable(
      value = "squareCache", 
      key = "#number", 
      condition = "#number>10")
    public BigDecimal square(Long number) {
        BigDecimal square = BigDecimal.valueOf(number)
          .multiply(BigDecimal.valueOf(number));
        log.info("square of {} is {}", number, square);
        return square;
    }
}

마지막으로 기본 Spring Boot 애플리케이션을 생성해 보겠습니다.

@SpringBootApplication
public class Application {

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

4. 캐시 구성

Spring의 @EnableCaching 어노테이션을 Spring bean에 추가하여 Spring의 어노테이션 기반 캐시 관리를 활성화해야 합니다.

CacheConfig 클래스 를 생성해 보겠습니다 .

@Configuration
@EnableCaching
public class CacheConfig {
}

Spring의 자동 구성은 Ehcache의 JSR-107 구현을 찾습니다. 그러나 기본적으로 캐시는 생성되지 않습니다.

Spring도 Ehcache도 기본 ehcache.xml 파일을 찾지 않기 때문입니다. 다음 속성을 추가하여 Spring에서 찾을 위치를 알려줍니다.

spring.cache.jcache.config=classpath:ehcache.xml

squareCache 라는 캐시가 있는 ehcache.xml 파일을 생성해 보겠습니다 .

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.ehcache.org/v3"
    xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
    xsi:schemaLocation="
            http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
            http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

    <cache alias="squareCache">
        <key-type>java.lang.Long</key-type>
        <value-type>java.math.BigDecimal</value-type>
        <expiry>
            <ttl unit="seconds">30</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>com.baeldung.cachetest.config.CacheEventLogger</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">2</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache>

</config>

그리고 CREATEDEXPIRED 캐시 이벤트 를 모두 기록하는 캐시 이벤트 리스너도 추가해 보겠습니다 .

public class CacheEventLogger 
  implements CacheEventListener<Object, Object> {

    // ...

    @Override
    public void onEvent(
      CacheEvent<? extends Object, ? extends Object> cacheEvent) {
        log.info(/* message */,
          cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
    }
}

5. 실행 중

Maven을 사용하여 mvn spring-boot:run 을 실행하여 이 앱을 시작할 수 있습니다 .

그런 다음 브라우저를 열고 포트 8080에서 REST 서비스에 액세스합니다.

http://localhost:8080/number/square/12 로  이동  하면 {“square”:144} 로 돌아가고 로그에 다음이 표시됩니다.

INFO [nio-8080-exec-1] c.b.cachetest.rest.NumberController : call numberService to square 12
INFO [nio-8080-exec-1] c.b.cachetest.service.NumberService : square of 12 is 144
INFO [e [_default_]-0] c.b.cachetest.config.CacheEventLogger : Cache event CREATED for item with key 12. Old value = null, New value = 144

NumberService 의 square 메소드 에서 로그 메시지를 볼 수 있고 EventLogger 에서 CREATED 이벤트를 볼 수 있습니다. 그런 다음 브라우저를 새로 고치면 로그에 다음 항목만 추가됩니다.

INFO [nio-8080-exec-2] c.b.cachetest.rest.NumberController : call numberService to square 12

NumberService 의 square 메소드에 있는 로그 메시지 가 호출되지 않습니다. 이는 캐시된 값이 사용되고 있음을 보여줍니다.

캐시된 항목이 만료될 때까지 30초 동안 기다렸다가 브라우저를 새로 고치면 EXPIRED 이벤트가 표시 되고 값이 캐시에 다시 추가됩니다.

INFO [nio-8080-exec-1] (...) NumberController : call numberService to square 12
INFO [e [_default_]-1] (...) CacheEventLogger : Cache event EXPIRED for item with key 12. Old value = 144,New value = null
INFO [nio-8080-exec-1] (... )NumberService : square of 12 is 144
INFO [e [_default_]-1] (...) CacheEventLogger : Cache event CREATED for item with key 12. Old value = null, New value = 144

브라우저에 http://localhost:8080/number/square/3 을 입력 하면 정답은 9이지만 값은 캐시되지 않습니다.

이는 @Cacheable 어노테이션에서 10보다 큰 숫자의 값만 캐시하는 조건을 사용했기 때문입니다.

6. 결론

이 빠른 사용방법(예제)에서는 Spring Boot로 Ehcache를 설정하는 방법을 보여 주었습니다.

항상 그렇듯이 코드 는 GitHub 에서 찾을 수 있습니다 .

Generic footer banner