# How to Configure Redis Caching with JetCache Annotations in ContiNew-Admin

> Learn how to configure Redis caching with JetCache annotations in ContiNew-Admin. Streamline your application performance using powerful, transparent method-level caching.

- Repository: [OpenContiNew/continew-admin](https://github.com/continew-org/continew-admin)
- Tags: how-to-guide
- Published: 2026-02-27

---

**ContiNew-Admin uses JetCache with Redisson to provide transparent method-level caching backed by Redis, configured through YAML files and activated via `@EnableMethodCache` on the main application class.**

ContiNew-Admin is a modern Java admin framework that leverages JetCache to simplify distributed caching. By combining local Caffeine caches with a remote Redis backend via Redisson, the system achieves high-performance data access across clustered deployments. This guide explains how to configure Redis caching with JetCache annotations based on the actual implementation in the `continew-org/continew-admin` repository.

## Enable Method-Level Caching

JetCache requires explicit activation to scan for caching annotations. In [`ContiNewAdminApplication.java`](https://github.com/continew-org/continew-admin/blob/main/ContiNewAdminApplication.java), the `@EnableMethodCache` annotation triggers the framework to process `@Cached`, `@CacheInvalidate`, and related annotations within the specified base packages.

```java
// continew-server/src/main/java/top/continew/admin/ContiNewAdminApplication.java
package top.continew.admin;

import com.alicp.jetcache.anno.config.EnableMethodCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableMethodCache(basePackages = "top.continew.admin")
public class ContiNewAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(ContiNewAdminApplication.class, args);
    }
}

```

This configuration ensures that any class within the `top.continew.admin` package hierarchy can use JetCache annotations without additional configuration.

## Configure the Cache Stack

ContiNew-Admin implements a **two-tier caching strategy** that balances speed and consistency. The configuration resides in [`continew-server/src/main/resources/config/application-dev.yml`](https://github.com/continew-org/continew-admin/blob/main/continew-server/src/main/resources/config/application-dev.yml) (and [`application-prod.yml`](https://github.com/continew-org/continew-admin/blob/main/application-prod.yml) for production).

### Local Cache (Caffeine)

The local tier provides microsecond-level access for data within the same JVM instance. Configure it under the `jetcache.local` block:

```yaml
jetcache:
  statIntervalMinutes: 15
  local:
    default:
      type: caffeine
      keyConvertor: jackson
      expireAfterWriteInMillis: 7200000  # 2 hours

      limit: 1000

```

The `limit: 1000` parameter restricts the local cache to 1000 entries, preventing memory pressure. The `jackson` key converter ensures complex objects serialize consistently.

### Remote Redis Cache (Redisson)

The remote tier uses **Redisson** to connect to Redis, enabling data sharing across multiple application instances. Configure this under `jetcache.remote`:

```yaml
jetcache:
  remote:
    default:
      type: redisson
      keyConvertor: jackson
      expireAfterWriteInMillis: 7200000
      broadcastChannel: ${spring.application.name}
      valueEncoder: java
      valueDecoder: java

```

The `broadcastChannel` setting ensures cache invalidation events propagate to all JVMs listening on the same channel, preventing stale data in clustered environments.

## Connect to Redis

JetCache's Redisson client reuses standard Spring Redis configuration. Define the connection parameters in the same YAML profile:

```yaml
spring:
  redis:
    host: localhost
    port: 6379
    password:      # leave empty for development

```

The Docker Compose setup in [`docker/docker-compose.yml`](https://github.com/continew-org/continew-admin/blob/main/docker/docker-compose.yml) spins up a Redis instance that matches these defaults for local development.

## Annotate Service Methods

Once configured, apply JetCache annotations to service layer methods. The framework automatically intercepts calls to check the local cache first, then Redis, before executing the method body.

### Cache Read Operations

Use `@Cached` to store method results. In [`UserServiceImpl.java`](https://github.com/continew-org/continew-admin/blob/main/UserServiceImpl.java), user lookups are cached with a custom expiration:

```java
// continew-system/src/main/java/top/continew/admin/system/service/impl/UserServiceImpl.java
import com.alicp.jetcache.anno.Cached;

@Service
public class UserServiceImpl implements UserService {

    @Override
    @Cached(name = "user:", key = "#id", expire = 3600)
    public UserVO getUserById(Long id) {
        return userMapper.selectById(id);
    }
}

```

The `name` parameter defines the cache region prefix, while `key` uses Spring Expression Language (SpEL) to incorporate method arguments. The `expire` value overrides the default 2-hour TTL with a 1-hour (3600-second) timeout.

### Cache Invalidation

When data changes, remove stale entries using `@CacheInvalidate`. This ensures consistency between the database and both cache tiers:

```java
@Override
@CacheInvalidate(name = "user:", key = "#user.id")
public void updateUser(UserDTO user) {
    userMapper.updateById(user);
}

```

This annotation triggers deletion from both the local Caffeine cache and the remote Redis instance.

## Advanced JetCache Features

For high-traffic scenarios, ContiNew-Admin supports advanced JetCache patterns demonstrated in [`DashboardController.java`](https://github.com/continew-org/continew-admin/blob/main/DashboardController.java).

### Cache Penetration Protection

Prevent cache penetration attacks (where non-existent keys flood the database) using `@CachePenetrationProtect`:

```java
@CachePenetrationProtect(name = "config:", key = "#key", timeout = 3000)
public ConfigVO getConfig(String key) {
    return configMapper.selectByKey(key);
}

```

This locks the cache key during the first thread's database load, blocking subsequent concurrent requests for the same key until the value is cached.

### Automatic Refresh

Keep frequently accessed data fresh without blocking requests using `@CacheRefresh`:

```java
@CacheRefresh(name = "config:", key = "#key", refresh = 600)
public ConfigVO getFreshConfig(String key) {
    return configMapper.selectByKey(key);
}

```

The background refresh runs every 600 seconds (10 minutes), reloading the value from the database while serving stale data during the update.

## Summary

- **Enable caching** by adding `@EnableMethodCache(basePackages = "top.continew.admin")` to [`ContiNewAdminApplication.java`](https://github.com/continew-org/continew-admin/blob/main/ContiNewAdminApplication.java).
- **Configure tiers** in [`application-dev.yml`](https://github.com/continew-org/continew-admin/blob/main/application-dev.yml) using `type: caffeine` for local caching and `type: redisson` for Redis distribution.
- **Set Redis connection** under `spring.redis` in the same YAML file; JetCache automatically inherits these settings.
- **Apply annotations** such as `@Cached` for reads and `@CacheInvalidate` for writes to maintain cache consistency.
- **Use broadcast channels** to synchronize invalidation events across clustered JVM instances via the `${spring.application.name}` channel.

## Frequently Asked Questions

### What is the difference between local and remote cache in ContiNew-Admin?

The **local cache** uses Caffeine to store data in the application's JVM memory, providing sub-millisecond access for single-instance hot data. The **remote cache** uses Redisson to store data in Redis, enabling microsecond-scale access across distributed instances. ContiNew-Admin checks the local tier first, then falls back to Redis, and finally executes the method if both miss.

### How does ContiNew-Admin prevent stale cache data in clustered deployments?

The configuration sets `broadcastChannel: ${spring.application.name}` in the JetCache remote settings. When one instance invalidates or updates a cache entry, Redisson publishes the event to this channel. All other application instances listening on the same channel automatically evict their corresponding local Caffeine entries, ensuring consistency across the cluster.

### Can I change the default cache expiration time?

Yes. While the default `expireAfterWriteInMillis` is 7200000 (2 hours) in [`application-dev.yml`](https://github.com/continew-org/continew-admin/blob/main/application-dev.yml), you can override this per-method using the `expire` parameter in the `@Cached` annotation. Specify the value in seconds; for example, `@Cached(expire = 3600)` sets a 1-hour TTL for that specific cache region.

### Do I need to configure Redisson separately from Spring Redis?

No. JetCache's Redisson implementation in ContiNew-Admin automatically reuses the connection settings defined under `spring.redis` in your YAML configuration. You only need to ensure the Redis server is accessible at the specified host and port; no additional Redisson-specific beans or configuration files are required.