Welcome. In this tutorial, we will use Redis and Springboot to demonstrate the URL shortener (also known as Tiny URL) application. The application creates the raw URL and stores it in the Redis memory cache.
1. Introduction
Before continuing with this tutorial, we’ll take a look at some general terms, such as Spring Boot, an introduction to Docker, and Redis.
1.1 What is Spring Boot?
- Spring Boot is a module that provides rapid application development capabilities for the Spring framework, including auto-configuration, stand-alone code, and production-ready code
- It creates a package forA jar ofAnd use an embedded servlet container (such as Tomcat, Jetty, or Undertow) to launch the application directly. Therefore, no deployment is requiredThe warfile
- It simplifies Maven configuration by providing starter templates and helps resolve dependency conflicts. It automatically identifies the required dependencies and imports them into the application
- It helps to remove boilerplate code, extra comments, and XML configuration
- It provides powerful batching capabilities and manages the remaining endpoints
- It provides an efficient * JPA-starter library that can efficiently connect applications to relational databases
- It provides a microservices architecture and cloud configuration to centrally manage all application-specific configuration properties.
1.2 What is Docker?
In today’s world, Docker is an important term,
- Typically used in CI/CD platforms, which package and run applications with their dependencies in containers
- Is the standard for Linux containers
- acontainerIs a runtime that runs in any Linux kernel and provides a private machine-like space under Linux
1.2.1 Docker term
- Image: Representation of a Docker container, a JAR or WAR file in Java
- Container: The runtime of a Docker, which is a Docker image that is deployed and running. For example, an executable Spring Boot JAR
- Engine: Code to manage, create, and run Docker containers
- Central: A common developer registry for distributing their code
- Repository: A collection of Docker-related images, that is, different versions of the same application
1.3 What is Redis?
- Redis is an open source in-memory data store written in the C programming language
- Provides a distributed in-memory key-value database with optional persistence
- Typically used as a database, cache, or message broker, and supports different types of database types, such as string, list, map, collection, or sorted collection, etc.
- It is fast and the operation is atomic in nature (that is, two clients can access the data at the same time and the Redis server will receive updated values)
- Provide utilities, such as caching and message queuing
2. Spring Boot URL shortener
This is the system guide for implementing this tutorial.
2.1 Application Prerequisites
Starting with this tutorial, we hope that current users have finished installing Docker. If anyone needs to complete the Docker installation, please watch this video.
Let’s start building the application!
3. Extract the Redis image from the Docker Hub and start it
To start Redis and work on the localhost environment, we will extract the Redis image from the Docker and start the container. Users can refer to the following commands to pull the image and then start the container.
Docker command
## Docker commands
## step1 - Pulling redis image from docker hub
docker pull redis
## step2 - Running the container
docker run -d -p 6379:6379 --name my-redis redis
Copy the code
If all goes well, the Docker image is pulled out and started successfully. You can use the docker ps -a command to verify that the container started successfully.
4. Create a Spring Boot application
Here are the steps involved in developing the application.
4.1 the Maven rely on
Here, we specify dependencies for Spring Boot, Redis, Lombok, Guava, and Commons Validator. Maven will automatically resolve other dependencies. The update file will have the following code.
pom.xml
The < project XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" XMLNS = "http://maven.apache.org/POM/4.0.0" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <! - project properties - > < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Springboot. Redis. Now being < / groupId > The < artifactId > SpringbootTinyUrl < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>commons-validator</groupId> <artifactId>commons-validator</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>com.google.guava</ artifactId> <version>18.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId> </dependency> </dependencies> <build> <! -- to make the application as fat jar so that spring boot libraries are included --> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code
4.2 Application Properties
In the following position to create a new attribute file: SpringbootTinyUrl/SRC/main/resources/application and added to the Redis configuration file.
application.properties
# Application configuration.
## You can change the server port configuration as per their configuration idea.
server.port=10091
# Redis configuration.
## As we are running Redis on Docker we are setting up its configuration.
spring.redis.host=localhost
spring.redis.port=6379
Copy the code
4.3 Java classes
Let’s write all the Java classes involved in this application.
4.3.1 Implementation/Main Class
Add the following code to the main class to boot the application from the main method. Always remember that the entry point to a SpringBoot application is a class that contains the @SpringBootApplication annotation and the static main method.
Runner.java
package com.springboot.redis.tinyurl; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @Slf4j @SpringBootApplication public class Runner { public static void main(String[] args) { SpringApplication.run(Runner.class, args); log.info("Springboot and tinyurl application started successfully."); }}Copy the code
4.3.2 model class
Add the following code to the model class. UrlDto.java
package com.springboot.redis.tinyurl.model; import com.google.common.hash.Hashing; import lombok.AllArgsConstructor; import lombok.Getter; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; @Getter @AllArgsConstructor public class UrlDto { private final String id; private final String url; private final LocalDateTime created; public static UrlDto create(final String url) { final String id = Hashing.murmur3_32().hashString(url, StandardCharsets.UTF_8).toString(); return new UrlDto(id, url, LocalDateTime.now()); }}Copy the code
4.3.3 configuration class
Add the following code to the configuration class. Spring Boot is automatically configured by default and can be used with the string base key/value pair Redis template. In this tutorial, however, we store the key as a string and the value as a JSON object.
RedisConfig.java
package com.springboot.redis.tinyurl.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.springboot.redis.tinyurl.model.UrlDto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Autowired private ObjectMapper objectMapper; @Autowired private RedisConnectionFactory redisConnectionFactory; // Setting up the Redis template object. @SuppressWarnings({"rawtypes", "unchecked"}) @Bean public RedisTemplate<String, UrlDto> redisTemplate() { final Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(UrlDto.class); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); final RedisTemplate<String, UrlDto> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); return redisTemplate; }}Copy the code
4.3.4 Controller Classes
Add the following code to the controller class, where these methods will be used to create a shorter URL and get the original URL in exchange for a shorter URL. TinyUrlController.java
package com.springboot.redis.tinyurl.controller;
import com.springboot.redis.tinyurl.exception.TinyUrlError; import com.springboot.redis.tinyurl.model.UrlDto; import lombok.extern.slf4j.Slf4j; import org.apache.commons.validator.routines.UrlValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.Objects; import java.util.concurrent.TimeUnit; @Slf4j @RestController @RequestMapping(value = "/rest/url") public class TinyUrlController { @Autowired private RedisTemplate<String, UrlDto> redisTemplate; @Value("${redis.ttl}") private long ttl; @PostMapping public ResponseEntity create(@RequestBody final String url) { // Using commons-validator library to validate the input URL. final UrlValidator urlValidator = new UrlValidator(new String[]{"http", "https"}); if (! urlValidator.isValid(url)) { // Invalid url return HTTP 400 bad request. return ResponseEntity.badRequest().body(new TinyUrlError("Invalid URL.")); } // If valid URL, generate a hash key using guava's murmur3 hashing algorithm. final UrlDto urlDto = UrlDto.create(url); log.info("URL id generated = {}", urlDto.getId()); // Store both hasing key and url object in redis. redisTemplate.opsForValue().set(urlDto.getId(), urlDto, ttl, TimeUnit.SECONDS); // Return the generated id as a response header. return ResponseEntity.noContent().header("id", urlDto.getId()).build(); } @GetMapping(value = "/{id}") public ResponseEntity getUrl(@PathVariable final String id) { // Get from redis. final UrlDto urlDto = redisTemplate.opsForValue().get(id); if (Objects.isNull(urlDto)) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new TinyUrlError("No such key exists.")); } else { log.info("URL retrieved = {}", urlDto.getUrl()); } return ResponseEntity.ok(urlDto); }}Copy the code
5. Run the application
6. Project demonstration
Open the Postman tool, and then click the following URL.
// Create short url
http://localhost:10095/rest/url
// Get original url from url id
http://localhost:10095/rest/url/{{urlId}}
Copy the code
7. To summarize
In this section, we learn:
- Introduction to Spring Boot, Redis and Docker
- Integrate Redis with the Spring Boot application to build the URL shortener API
- Use the Postman tool to create a short url and get the original url