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;<br/>import lombok.Builder;<br/>import lombok.Data;<br/>import lombok.NoArgsConstructor;<br/><br/>import java.time.Instant;<br/><br/>@Data<br/>@Builder<br/>@AllArgsConstructor<br/>@NoArgsConstructor<br/>public class UrlMap {<br/> private Long id;<br/> private String longUrl;<br/> private String shortUrl;<br/> private String username;<br/> private Instant expireTime;<br/> private Instant creationTime;<br/>}3. DAO Layer
import com.zhan.zhan215.Entity.UrlMap;<br/>import org.apache.ibatis.annotations.Mapper;<br/>import org.apache.ibatis.annotations.Param;<br/><br/>@Mapper<br/>public interface UrlMapMapper {<br/> UrlMap findFirstByLongUrl(@Param("longUrl") String longUrl, @Param("username") String username);<br/> void saveUrlMap(UrlMap urlMap);<br/> UrlMap findByShortUrl(String shortUrl);<br/>}The corresponding MyBatis XML defines select and insert statements for the above methods.
4. Service Layer
import com.zhan.zhan215.Dao.UrlMapMapper;<br/>import com.zhan.zhan215.Entity.UrlMap;<br/>import org.springframework.stereotype.Service;<br/><br/>import javax.annotation.Resource;<br/>import java.security.MessageDigest;<br/>import java.security.NoSuchAlgorithmException;<br/>import java.time.Instant;<br/><br/>@Service<br/>public class UrlMapService {<br/> @Resource<br/> private UrlMapMapper urlMapMapper;<br/><br/> // Encode long URL to short URL<br/> public String encode(String longUrl, String username) {<br/> UrlMap urlMap = urlMapMapper.findFirstByLongUrl(longUrl, username);<br/> if (urlMap != null && username.equals(urlMap.getUsername())) {<br/> return urlMap.getShortUrl();<br/> } else {<br/> String shortLink = generateShortLink(longUrl, username);<br/> UrlMap newMap = new UrlMap();<br/> newMap.setLongUrl(longUrl);<br/> newMap.setShortUrl(shortLink);<br/> newMap.setUsername(username);<br/> newMap.setCreationTime(Instant.now());<br/> urlMapMapper.saveUrlMap(newMap);<br/> return shortLink;<br/> }<br/> }<br/><br/> // Decode short URL to long URL<br/> public String decode(String shortUrl) {<br/> UrlMap map = urlMapMapper.findByShortUrl(shortUrl);<br/> return map != null ? map.getLongUrl() : "https://bilibili.com";<br/> }<br/><br/> // Generate short link using MD5 hash (first 8 chars) plus username<br/> public static String generateShortLink(String originalUrl, String username) {<br/> try {<br/> MessageDigest md = MessageDigest.getInstance("MD5");<br/> byte[] hash = md.digest(originalUrl.getBytes());<br/> StringBuilder sb = new StringBuilder();<br/> for (byte b : hash) { sb.append(String.format("%02x", b)); }<br/> return sb.toString().substring(0, 8) + username;<br/> } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; }<br/> }<br/>}5. Controller Layer
import com.zhan.zhan215.Common.ResponseBean;<br/>import com.zhan.zhan215.Service.UrlMapService;<br/>import org.springframework.web.bind.annotation.GetMapping;<br/>import org.springframework.web.bind.annotation.PostMapping;<br/>import org.springframework.web.bind.annotation.RequestParam;<br/>import org.springframework.web.bind.annotation.RestController;<br/>import org.springframework.web.servlet.view.RedirectView;<br/><br/>import javax.annotation.Resource;<br/><br/>@RestController<br/>public class UrlMapController {<br/> @Resource<br/> private UrlMapService urlMapService;<br/><br/> @PostMapping("/shorten")
public ResponseBean shorten(@RequestParam String longUrl, @RequestParam String username) {<br/> String short = urlMapService.encode(longUrl, username);<br/> return ResponseBean.success(short);<br/> }<br/><br/> @GetMapping("redirect")
public RedirectView redirectView(@RequestParam String shortUrl) {<br/> String longUrl = urlMapService.decode(shortUrl);<br/> return new RedirectView(longUrl);<br/> }<br/>}6. Response Wrapper
public class ResponseBean<T> {<br/> private boolean success;<br/> private T data;<br/> // getters and setters omitted for brevity<br/> public static <T> ResponseBean<T> success(T data) {<br/> ResponseBean<T> r = new ResponseBean<>();<br/> r.setSuccess(true); r.setData(data); return r;<br/> }<br/> public static <T> ResponseBean<T> error(T errorData) {<br/> ResponseBean<T> r = new ResponseBean<>();<br/> r.setSuccess(false); r.setData(errorData); return r;<br/> }<br/>}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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
