By: Yim Sotharoth
===
## Table of Contents
[TOC]
## Architecture

## Redis Docker Compose
___you can run `docker compose up -d` to create the docker image/container of the redis server___
```yaml=
version: "3.8"
services:
cache:
image: redis:6.2-alpine
restart: always
ports:
- "6379:6379"
command: redis-server --save 20 1 --loglevel warning --requirepass eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81
volumes:
- cache:/data
volumes:
cache:
driver: local
```
## Dependencies
___Prerequisites___
```xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20151123</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
```
## application.yaml configurations
```yaml
server:
port: 8090
spring:
application:
name: Redis-Tutorial
data:
redis:
host: localhost
port: 6379
password: YOUR_PASSWORD
datasource:
url: jdbc:postgresql://YOUR_DATABASE_IP_ADDRESS:5432/YOUR_DB
username: YOUR_USERNAME
password: YOUR_PASSWORD
jpa:
show-sql: true
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
```
## Model
_Create a `models` folder_
### Student Model
_Create a `Student.java` file in `models`_
```java=
package www.metaphorlism.com.redis_tutorial.models;
import com.google.gson.Gson;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class Student {
@Id
private String id;
private String name;
private String major;
private String contact;
public String toJson(){
Gson gson = new Gson();
return gson.toJson(this);
}
}
```
### Response Model
___a model to get response in the below JSON sample___
```json
{
"status": "success",
"message": "student from cache",
"student": {
"id": "900851e1-4baa-4946-841d-daa8f8357643",
"name": "Student One",
"major": "Computer Science",
"contact": "yimsotharoth999@gmail.com"
}
}
```
_Create a `Response.java` file in `models`_
```java=
package www.metaphorlism.com.redis_tutorial.models;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Response {
private String status;
private String message;
private Student student;
public Response(String status,String message,Student student){
this.status = status;
this.message = message;
this.student = student;
}
}
```
## Repository
_Create a `repositories` folder and a `StudentRepository` interface_
```java=
package www.metaphorlism.com.redis_tutorial.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import www.metaphorlism.com.redis_tutorial.models.Student;
@Repository
public interface StudentRepository extends JpaRepository<Student,String> {
}
```
## Service
_Create a `services` folder and a `StudentService.java` file_
```java=
package www.metaphorlism.com.redis_tutorial.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import www.metaphorlism.com.redis_tutorial.models.Student;
import www.metaphorlism.com.redis_tutorial.repositories.StudentRepository;
import java.util.Optional;
@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
public void createStudent(Student student) {
studentRepository.save(student);
}
public Optional<Student> getStudentById(String student_id) {
return studentRepository.findById(student_id);
}
}
```
## Redis Configuration
_Create a `config` folder and a `RedisConfig.java` file_
```java=
package www.metaphorlism.com.redis_tutorial.config;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.connection.RedisConnectionFactory;
public class RedisConfig{
@Bean
public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<?, ?> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
}
```
## Controller
_Create a `controllers` folder and a `StudentController.java` file_
### DECLARATION AND GLOBAL VARIABLE
```java=
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Autowired
private StudentService studentService;
private final String REDIS_KEY = "STUDENT";
```
### CREATE STUDENT CONTROLLER
___a POST method controller to create new student to the database___
```java=
@PostMapping("/students")
public ResponseEntity<Object> createStudent(@RequestBody Student student) {
student.setId(UUID.randomUUID().toString());
studentService.createStudent(student);
return new ResponseEntity<Object>(new Response("success","create successfully",student), HttpStatus.CREATED);
}
```
### GET STUDENT BY ID CONTROLLER
___a get method that get student by ID from redis/database___
```java=
@GetMapping("/students/{student_id}")
public ResponseEntity<Object> getStudentById(@PathVariable String student_id) throws JsonProcessingException {
try{
String key = REDIS_KEY.concat(":").concat(student_id);
var cachedStudent = redisTemplate.opsForValue().get(key);
if(cachedStudent == null) {
Optional<Student> student = studentService.getStudentById(student_id);
if(student.isPresent()){
redisTemplate.opsForValue().set(key,student.get().toJson());
if(redisTemplate.getExpire(key) < 0){
redisTemplate.expire(key,2,TimeUnit.MINUTES);
}
return new ResponseEntity<Object>(new Response("success","student from db",student.get()), HttpStatus.OK);
}
return new ResponseEntity<Object>(new Response("success","student from db not found",null), HttpStatus.NOT_FOUND);
}
ObjectMapper objectMapper = new ObjectMapper();
Student student = objectMapper.readValue(cachedStudent,Student.class);
return new ResponseEntity<Object>(new Response("success","student from cache",student), HttpStatus.OK);
}catch (Exception e){
log.info(e.getMessage());
return new ResponseEntity<Object>(new Response("fail",e.getMessage(),null), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
```
Project Repository: https://github.com/metaphorlism/springboot-redis
## Contact Us
- :mailbox: yimsotharoth999@gmail.com
- [GitHub](https://github.com/metaphorlism)
- [Facebook Page](https://www.facebook.com/Metaphorlism)
- [Instagram: Metaphorlism](https://www.instagram.com/metaphorlism/)