Implementing Short URL Redirection with SpringBoot
This article explains the concept of short‑URL redirection, its benefits, and provides a complete SpringBoot implementation—including database schema, entity, DAO, service, controller, and testing code—to convert long links into short, trackable links and handle redirects.
Background
Short‑URL redirection converts long web links into compact URLs that are easier to share, display and track. Third‑party services typically generate a short link that redirects to the original long URL and may provide click statistics.
Significance
Space saving: Short links reduce character count for sharing.
Link beautification: They appear cleaner and more attractive.
Link stability: Short links can be updated behind the scenes to avoid broken URLs.
Analytics: Click counts, sources and regions can be tracked.
Ease of sharing: Short links copy and paste easily across platforms.
Privacy: Original URL details can be hidden.
SpringBoot Implementation
1. Database Table
A table t_url_map stores the mapping between long URLs, short URLs, the owning username and timestamps.
2. Mapping Entity
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.Instant;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UrlMap {
private Long id;
private String longUrl;
private String shortUrl;
private String username;
private Instant expireTime;
private Instant creationTime;
}3. DAO Layer
import com.zhan.zhan215.Entity.UrlMap;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface UrlMapMapper {
UrlMap findFirstByLongUrl(@Param("longUrl") String longUrl, @Param("username") String username);
void saveUrlMap(UrlMap urlMap);
UrlMap findByShortUrl(String shortUrl);
}The corresponding MyBatis XML defines select and insert statements for the above methods.
4. Service Layer
import com.zhan.zhan215.Dao.UrlMapMapper;
import com.zhan.zhan215.Entity.UrlMap;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
@Service
public class UrlMapService {
@Resource
private UrlMapMapper urlMapMapper;
// Encode long URL to short URL
public String encode(String longUrl, String username) {
UrlMap urlMap = urlMapMapper.findFirstByLongUrl(longUrl, username);
if (urlMap != null && username.equals(urlMap.getUsername())) {
return urlMap.getShortUrl();
} else {
String shortLink = generateShortLink(longUrl, username);
UrlMap newMap = new UrlMap();
newMap.setLongUrl(longUrl);
newMap.setShortUrl(shortLink);
newMap.setUsername(username);
newMap.setCreationTime(Instant.now());
urlMapMapper.saveUrlMap(newMap);
return shortLink;
}
}
// Decode short URL to long URL
public String decode(String shortUrl) {
UrlMap map = urlMapMapper.findByShortUrl(shortUrl);
return map != null ? map.getLongUrl() : "https://bilibili.com";
}
// Generate short link using MD5 hash (first 8 chars) plus username
public static String generateShortLink(String originalUrl, String username) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(originalUrl.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : hash) { sb.append(String.format("%02x", b)); }
return sb.toString().substring(0, 8) + username;
} catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; }
}
}5. Controller Layer
import com.zhan.zhan215.Common.ResponseBean;
import com.zhan.zhan215.Service.UrlMapService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.RedirectView;
import javax.annotation.Resource;
@RestController
public class UrlMapController {
@Resource
private UrlMapService urlMapService;
@PostMapping("/shorten")
public ResponseBean shorten(@RequestParam String longUrl, @RequestParam String username) {
String short = urlMapService.encode(longUrl, username);
return ResponseBean.success(short);
}
@GetMapping("redirect")
public RedirectView redirectView(@RequestParam String shortUrl) {
String longUrl = urlMapService.decode(shortUrl);
return new RedirectView(longUrl);
}
}6. Response Wrapper
public class ResponseBean
{
private boolean success;
private T data;
// getters and setters omitted for brevity
public static
ResponseBean
success(T data) {
ResponseBean
r = new ResponseBean<>();
r.setSuccess(true); r.setData(data); return r;
}
public static
ResponseBean
error(T errorData) {
ResponseBean
r = new ResponseBean<>();
r.setSuccess(false); r.setData(errorData); return r;
}
}Result Testing
A sample Bilibili video URL is shortened to a value such as 1b9590bezhan . Accessing the short link correctly redirects to the original long URL, confirming the implementation works.
Discussion
The username parameter is included so that different users generating a short link for the same long URL receive distinct short URLs, enabling per‑user tracking and analytics.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.