Create Rest API using Springboot and Redis
Introduction
Now on this article we will learn how to create RestAPI using Springboot with simple CRUD function and will connecting and storing data into Redis, and also we will test all apis using postman. take a look image below for the simple describe what we will created.
and then on this article we will creating three apis like below.
Previous Article
Dont forget to visit the previous article we already learn about how to create rest api using springboot and MongoDB
Requirements
- Maven 3+
- Java 8+
- IDE (Intelij Idea o Eclipse)
- Docker
- Redis (Docker container)
- Postman (API Test)
Overviews
- Introduction of Redis
- Create Redis Container and login into redis server and see the datas
- Generate Springboot project
- Add redis connection and configuration
- Create Controller, Service, Repo
- Test all Rest API using Postman
- Full source code in here
Introduction of Redis
Redis is an in-memory data structure store, used as a distributed, in-memory key–value database, cache and message broker, with optional durability. source from wikipedia.
on redis, our data will stored on database using key and value format, so we must understand before start working with redis.
take a look table below, we will created two rows data on redis database using key and value.
notes :
- key must be unique , when you add data into redis, and your key is same with existing keys on redis, redis will execute your action is update data, but if you wanna add new data your key must be unique.
Create Redis Container
- step 1, first we must create the Redis container as a database server for store the data, On this article we will use the Docker for simplify the installation. If you already have Docker on your machine, you just create the file docker-compose.yml and than you write the syntax like this :
version: "3"
services:
redis:
container_name: server_redis
image: redis:6.2-alpine
restart: always
ports:
- '6379:6379'
environment:
REDIS_PWD: 'password123'
command: /bin/sh -c "redis-server --requirepass $$REDIS_PWD"
volumes:
- redis:/data
networks:
- network
networks:
network:
driver: bridge
volumes:
redis:
driver: local
- step two, and run syntax like this
docker-compose up -d
- step three, we can check the the containers already success created with syntax
docker container ls
- step four, we can open redis container, and then login into redis server, and we can see all datas on redis, following syntax below.
// step 1) for open mongo db docker container and login into redis server
docker container exec -it server_redis redis-cli -h 127.0.0.1 -p 6379 -a "password123"
// step 2) for show all data on redis database
keys *
Generate Springboot project
- Next we create the springboot project, on link : https://start.spring.io/ and then add dependecies on pom.xml like this
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
Add redis connection and configuration
- step 1, open file application.properties, and than adding syntax like this.
#server port http
server.port=8181
# redis with auth basic
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=password123
spring.redis.database=0
spring.redis.timeout=10
## spring.redis.timeout=60000
- step 2, add DataSourceAutoConfiguration on main class, for enable the auto configuration and connection springboot to Redis Database.
package com.deni.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}
- step 3, create RedisConfig class for enable redis template, following syntax like below.
package com.deni.app.redis.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
@EnableRedisRepositories
public class RedisConfig {
@Value("${spring.redis.host}")
private String redisHostname;
@Value("${spring.redis.port}")
private int redisPort;
@Value("${spring.redis.password}")
private String redisPassword;
@Bean
public RedisTemplate<String, String> redisTemplate() {
// redis template
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new GenericToStringSerializer<String>(String.class));
redisTemplate.setHashKeySerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
// redis config (host, port, password)
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(redisHostname, redisPort);
redisConfig.setPassword(redisPassword);
// redis template
JedisClientConfiguration jedisClientConfig = JedisClientConfiguration.builder().build();
// redis connection
JedisConnectionFactory redisConnection = new JedisConnectionFactory(redisConfig, jedisClientConfig);
redisConnection.afterPropertiesSet();
redisTemplate.setConnectionFactory(redisConnection);
return redisTemplate;
}
}
Controller, Service, Repository Components
- Before we starting create the apis, we must knows the three important components of springboot framework, that are Controller, Service, Repository. take look the image below for simple describe the components.
- Controller is a class for handle the HTTP Method, request, response and all about HTTP.
- Service is a class for handle the bussines logic, validator, case , ect
- Repository is a class for handle the all function for manipulate data to Database such as (save, update, delete, select, etc)
so we already knows the mean of three important component on springboot framework. lets continues for craeted the apis.
Create DTO
- Create the RedisDTO class for maping with the redis data from Redis server
package com.deni.app.redis.dto;
import lombok.*;
@Data
@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class RedisDto {
String key;
Object value;
}
- Annotation Descriptions:
- Getter is used for generate variable getter function
- Setter is used for generate variable setter function
- AllArgsConstructor is used for auto generate all args contructior function
- NoArgsConstructor is used for auto generate no arg constructor function
- Builder is used for generate auto builder function
Create Repository
- Create RedisRepo class for handling all CRUD function, following syntax like this.
package com.deni.app.redis.repo;
import com.deni.app.redis.dto.RedisDto;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Repository
public class RedisRepo {
@Value("${spring.redis.timeout}")
private int redisTimeOut;
@Autowired
RedisTemplate redisTemplate;
public Object saveOrUpdate(String haskey, Object model) {
redisTemplate.opsForValue().set(haskey, new Gson().toJson(model));
redisTemplate.expire(haskey, redisTimeOut, TimeUnit.MINUTES);
return model;
}
public List<RedisDto> getAllData() {
return null;
}
public RedisDto getDataByHaskeyForString(String haskey) {
try {
String value = (String) redisTemplate.opsForValue().get(haskey);
if (value != null) {
return RedisDto.builder()
.key(haskey)
.value(value)
.build();
}
return null;
} catch (Exception e) {
return null;
}
}
public RedisDto getDataByHaskeyForEntity(String haskey, Class<?> classOfT) {
try {
String value = (String) redisTemplate.opsForValue().get(haskey);
if (value != null) {
return RedisDto.builder()
.key(haskey)
.value(new Gson().fromJson(redisTemplate.opsForValue().get(haskey).toString(), classOfT))
.build();
}
return null;
} catch (Exception e) {
return null;
}
}
public boolean deleteDataByHaskey(String haskey) {
redisTemplate.opsForValue().getAndDelete(haskey);
return true;
}
}
Create Service
we create service for handling the redis bussines logic.
- step 1, create RedisAbstractContract interface
package com.deni.app.redis.service;
import org.springframework.http.ResponseEntity;
public interface RedisAbstractContract {
public abstract ResponseEntity getDataByHaskey(String haskey);
}
- step 2, create RedisAbstractService abstract class
package com.deni.app.redis.service;
import com.deni.app.common.constants.Messages;
import com.deni.app.common.controller.ResponseHandler;
import com.deni.app.redis.dto.RedisDto;
import com.deni.app.redis.repo.RedisRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* this class for abstraction the redis service
* for generally all function for redis service needed
*/
public abstract class RedisAbstractService implements RedisAbstractContract {
@Autowired
public RedisRepo redisRepo;
// save or update data redis
public ResponseEntity saveOrUpdateData(RedisDto redisDto) {
Object redis = redisRepo.saveOrUpdate(redisDto.getKey(), redisDto.getValue());
if (redis != null) {
return ResponseHandler.createHttpResponse(
Messages.MSG_SAVE_SUCCESS,
redisDto,
HttpStatus.OK);
}
return ResponseHandler.createHttpResponse(
"save redis failed",
redisDto,
HttpStatus.BAD_REQUEST);
}
// delete data redis by haskey from redis
public ResponseEntity deleteDataByHaskey(String haskey) {
Object redis = redisRepo.getDataByHaskeyForString(haskey);
if (redis != null) {
redisRepo.deleteDataByHaskey(haskey);
return ResponseHandler.createHttpResponse(
String.format("Delete %s success", haskey),
"",
HttpStatus.OK);
}
return ResponseHandler.createHttpResponse(
Messages.MSG_DATA_NOT_FOUND,
haskey,
HttpStatus.OK);
}
// get data by hash key from redis
public ResponseEntity getDataByHaskey(String haskey) {
Object redis = redisRepo.getDataByHaskeyForString(haskey);
if (redis != null) {
return ResponseHandler.createHttpResponse(
Messages.MSG_DATA_FOUND,
redis,
HttpStatus.OK);
}
return ResponseHandler.createHttpResponse(
Messages.MSG_DATA_NOT_FOUND,
haskey,
HttpStatus.OK);
}
// get all data from redis
public ResponseEntity getAllData() {
Object redis = redisRepo.getAllData();
if (redis != null) {
return ResponseHandler.createHttpResponse(
Messages.MSG_DATA_FOUND,
redis,
HttpStatus.OK);
}
return ResponseHandler.createHttpResponse(
Messages.MSG_DATA_NOT_FOUND,
"",
HttpStatus.OK);
}
}
- step 3, create RedisServerService class
package com.deni.app.redis.service;
import org.springframework.stereotype.Service;
@Service
public class RedisServerService extends RedisAbstractService {
}
Create Controller
we create controller for handling the HTTP Method, request, response, endpoint api, and all about HTTP.
step 1, we create RedisAbstractController abstract class
package com.deni.app.redis.controller;
import com.deni.app.common.controller.Response;
import com.deni.app.redis.dto.RedisDto;
import com.deni.app.redis.service.RedisServerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
public abstract class RedisAbstractController {
@Autowired
public RedisServerService service;
@PostMapping(value = "/saveupdate")
public ResponseEntity<Response> saveOrUpdateData(@RequestBody RedisDto redisDto) {
return service.saveOrUpdateData(redisDto);
}
@DeleteMapping(value = "/delete/{haskey}")
public ResponseEntity<Response> deleteDataByHaskey(@PathVariable String haskey) {
return service.deleteDataByHaskey(haskey);
}
}
- step 2, we create RedisController class
package com.deni.app.redis.controller;
import com.deni.app.common.controller.Response;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/redis")
public class RedisController extends RedisAbstractController {
@GetMapping(value = "/find/{haskey}")
public ResponseEntity<Response> getDataByHaskey(@PathVariable String haskey) {
return service.getDataByHaskey(haskey);
}
@GetMapping(value = "/find/all")
public ResponseEntity<Response> getAllData() {
return service.getAllData();
}
}
Run the Springboot Application
- Run the Springboot application, and make sure the app is running .
Test the Rest API using Postman
You can get the postman api collection file on repository project, and then you can import into your local postman, for testing all apis.
Conclusion
Finally we already learn how to create REST full API using Springboot and Redis database, with case CRUD functions.
Full source code in here
Happy Coding & Keep Learning 🚀