欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot 實現(xiàn)長鏈接轉(zhuǎn)短鏈接的示例代碼

 更新時間:2024年09月15日 10:18:27   作者:鵬鵬博客  
短鏈接服務通過將長URL轉(zhuǎn)換成6位短碼,并存儲長短鏈接對應關系到數(shù)據(jù)庫中,用戶訪問短鏈接時,系統(tǒng)通過查詢數(shù)據(jù)庫并重定向到原始URL,實現(xiàn)快速訪問,本文就來介紹一下如何使用,感興趣的可以了解一下

實現(xiàn)結(jié)果: 

轉(zhuǎn)換短鏈接api:

接口:http://127.0.0.1/api?url=urlencode('要縮短的網(wǎng)址')

例如:http://127.0.0.1/api?url=http%3a%2f%2fwww.baidu.com

返回:http://127.0.0.1/baidu

訪問短鏈接即可還原原url;

轉(zhuǎn)換原理: 將原url通過一系列方式,轉(zhuǎn)換成6位短碼(只要能不重復,隨便怎么方式都行);將長短鏈接存入數(shù)據(jù)庫,形成一條對應關系;訪問短鏈接的時候,在數(shù)據(jù)庫找到對應的長鏈接,并通過重定向?qū)崿F(xiàn)原url的訪問;(如果你的轉(zhuǎn)換方式能過還原,也可以不要數(shù)據(jù)庫,但必須保證轉(zhuǎn)換后的短碼不能重復)

實現(xiàn)步驟:

1.創(chuàng)建數(shù)據(jù)庫(shorturl),創(chuàng)建一個表,存儲長鏈接和與之對應的短鏈接;

CREATE TABLE `link` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `long_url` varchar(500) DEFAULT NULL COMMENT '長鏈接',
  `short_url` varchar(255) DEFAULT NULL COMMENT '短鏈接',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

2.搭建springboot項目,搭建方式網(wǎng)上很多,自行查找;下圖是項目構(gòu)建完成的項目結(jié)構(gòu)(public可以忽略):

3.邏輯層代碼依次是:

entity:

package com.tips.entity;

public class Link {

    private Integer id;
    private String longUrl;
    private String shortUrl;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLongUrl() {
        return longUrl;
    }

    public void setLongUrl(String longUrl) {
        this.longUrl = longUrl;
    }

    public String getShortUrl() {
        return shortUrl;
    }

    public void setShortUrl(String shortUrl) {
        this.shortUrl = shortUrl;
    }
}

dao:

package com.tips.mapper;

import com.tips.entity.Link;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface LinkMapper {

    Link selectByPrimaryKey(Integer id);

    int insert(Link link);

    Link findByLongUrl(String longUrl);

    String findByShortUrl(String shortUrl);
}

service:

package com.tips.service;

import com.tips.entity.Link;

public interface LinkService {

    String save(Link link);

    String restoreUrl(String url);

}

service.impl:

package com.tips.service.impl;

import com.tips.entity.Link;
import com.tips.mapper.LinkMapper;
import com.tips.service.LinkService;
import com.tips.util.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LinkServiceImpl  implements LinkService{

    @Autowired
    private LinkMapper linkMapper;

    /**
     * 轉(zhuǎn)化url
     * 查詢數(shù)據(jù)庫是否已經(jīng)存在 如果存在就返回數(shù)據(jù)庫對應的短鏈接,如果不存在就查詢一條新紀錄并返回新的短鏈接
     * <strong>@param </strong>link
     * <strong>@return
</strong><strong>     </strong>*/
    @Override
    public String save(Link link) {
        String shortUrl = "http://127.0.0.1/";  
        String longUrl = link.getLongUrl();
        System.out.println(longUrl);
        Link link1 = linkMapper.findByLongUrl(longUrl);
        if(link1 == null) {
            shortUrl += this.gererateShortUrl(longUrl);
            link.setShortUrl(shortUrl);
            linkMapper.insert(link);
        }else{
            shortUrl = link1.getShortUrl();
        }
        return shortUrl;
    }

    @Override
    public String restoreUrl(String url) {
        return linkMapper.findByShortUrl(url);
    }

    /**
     * <strong>@param </strong>args
     */
    public static void main(String[] args) {

        String sLongUrl = "http://474515923.qzone.qq.com" ; //長鏈接
        LinkServiceImpl link = new LinkServiceImpl();
        String result = link.gererateShortUrl(sLongUrl);
        // 打印出結(jié)果
       System.out.println("短鏈接為: "+ result);
    }

    /**
     * 將長鏈接轉(zhuǎn)換為短鏈接
     * <strong>@param </strong>url
     * <strong>@return
</strong><strong>     </strong>*/
    public String gererateShortUrl(String url) {
        // 可以自定義生成 MD5 加密字符傳前的混合 KEY
        String key = "caron" ;
        // 要使用生成 URL 的字符
        String[] chars = new String[] { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" ,
                "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" ,
                "u" , "v" , "w" , "x" , "y" , "z" , "0" , "1" , "2" , "3" , "4" , "5" ,
                "6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" ,
                "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T" ,
                "U" , "V" , "W" , "X" , "Y" , "Z"

        };
        // 對傳入網(wǎng)址進行 MD5 加密
        String sMD5EncryptResult = MD5Util.MD5(key+url);
        String hex = sMD5EncryptResult;

//        String[] resUrl = new String[4];
//        for ( int i = 0; i < 4; i++) {

            // 把加密字符按照 8 位一組 16 進制與 0x3FFFFFFF 進行位與運算
            String sTempSubString = hex.substring(2 * 8, 2 * 8 + 8);    //固定取第三組

            // 這里需要使用 long 型來轉(zhuǎn)換,因為 Inteper .parseInt() 只能處理 31 位 , 首位為符號位 , 如果不用 long ,則會越界
            long lHexLong = 0x3FFFFFFF & Long.parseLong (sTempSubString, 16);
            String outChars = "" ;
            for ( int j = 0; j < 6; j++) {
                // 把得到的值與 0x0000003D 進行位與運算,取得字符數(shù)組 chars 索引
                long index = 0x0000003D & lHexLong;
                // 把取得的字符相加
                outChars += chars[( int ) index];
                // 每次循環(huán)按位右移 5 位
                lHexLong = lHexLong >> 5;
            }
            // 把字符串存入對應索引的輸出數(shù)組
//            resUrl[i] = outChars;
//        }
        return outChars;
    }
}

util:

package com.tips.util;

import java.security.MessageDigest;


public class MD5Util { 
 // MD5加碼。32位 
 public static String MD5(String inStr) { 
  MessageDigest md5 = null; 
  try { 
   md5 = MessageDigest.getInstance("MD5"); 
  } catch (Exception e) { 
   System.out.println(e.toString()); 
   e.printStackTrace(); 
   return ""; 
  } 
  char[] charArray = inStr.toCharArray(); 
  byte[] byteArray = new byte[charArray.length]; 
 
  for (int i = 0; i < charArray.length; i++) 
   byteArray[i] = (byte) charArray[i]; 
 
  byte[] md5Bytes = md5.digest(byteArray); 
 
  StringBuffer hexValue = new StringBuffer(); 
 
  for (int i = 0; i < md5Bytes.length; i++) { 
   int val = ((int) md5Bytes[i]) & 0xff; 
   if (val < 16) 
    hexValue.append("0"); 
   hexValue.append(Integer.toHexString(val)); 
  } 
 
  return hexValue.toString(); 
 } 
 
 // 可逆的加密算法 
 public static String KL(String inStr) { 
  // String s = new String(inStr); 
  char[] a = inStr.toCharArray(); 
  for (int i = 0; i < a.length; i++) { 
   a[i] = (char) (a[i] ^ 't'); 
  } 
  String s = new String(a); 
  return s; 
 } 
 
 // 加密后解密 
 public static String JM(String inStr) { 
  char[] a = inStr.toCharArray(); 
  for (int i = 0; i < a.length; i++) { 
   a[i] = (char) (a[i] ^ 't'); 
  } 
  String k = new String(a); 
  return k; 
 } 
  
 // 測試主函數(shù) 
 public static void main(String args[]) { 
  String s = new String("a"); 
  System.out.println("原始:" + s); 
  System.out.println("MD5后:" + MD5(s)); 
  System.out.println("MD5后再加密:" + KL(MD5(s))); 
  System.out.println("解密為MD5后的:" + JM(KL(MD5(s)))); 
  System.out.println("判斷是否相同:" + MD5(s).equals(JM(KL(MD5(s))))); 
 } 
} 

mapper:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tips.mapper.LinkMapper">
    <resultMap id="BaseResultMap" type="com.tips.entity.Link">
        <id column="id" jdbcType="INTEGER" property="id" />
        <result column="long_url" jdbcType="VARCHAR" property="longUrl" />
        <result column="short_url" jdbcType="VARCHAR" property="shortUrl" />
    </resultMap>
    <sql id="Base_Column_List">
        id, long_url, short_url
    </sql>

    <!-- 根據(jù)長鏈接查詢 -->
    <select id="findByLongUrl" parameterType="java.lang.String" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from link
        where long_url = #{longUrl,jdbcType=VARCHAR}
    </select>
    <!-- 根據(jù)短鏈接查詢 -->
    <select id="findByShortUrl" parameterType="java.lang.String" resultType="java.lang.String">
        select long_url from link
        where short_url = #{shortUrl,jdbcType=VARCHAR}
    </select>

    <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from link
        where id = #{id,jdbcType=INTEGER}
    </select>

    <insert id="insert" parameterType="com.tips.entity.Link">
        insert into link (id, long_url, short_url)
        values (#{id,jdbcType=INTEGER}, #{longUrl,jdbcType=VARCHAR}, #{shortUrl,jdbcType=VARCHAR})
    </insert>



</mapper>

controller:

package com.tips.controller;

import com.tips.entity.Link;
import com.tips.service.LinkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
public class LinkController {

    @Autowired
    private LinkService linkService;

    /**
     * 生成短鏈接
     * @param url
     * @return Caron
     */
    @RequestMapping("/api")
    @ResponseBody
    public Object save(String url){

        if (url == null || "".equals(url)){
            return null;
        }
        if(url.startsWith("http://") || url.startsWith("https://")){
            Link link = new Link();
            link.setLongUrl(url);
            return  linkService.save(link);
        }else{
            return "網(wǎng)址必須以http或https開頭";
        }
    }

    /**
     * 301跳轉(zhuǎn)
     * @param url
     * @return
     */
    @RequestMapping("/{url}")
    public String restoreUrl(@PathVariable("url") String url){

        String restoreUrl = linkService.restoreUrl("http://cni.tips/"+url);

        if(restoreUrl != null && !"".equals(restoreUrl)){
            return "redirect:"+restoreUrl;
        }else{
            return "redirect:http://www.cnilink.com";
//            return  "forward:/404.html";    //如果要訪問本地html,@RequestMapping("/{url}")前面必須加一層路徑/aa/{url}
        }

    }

}

application.properties:

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com</groupId>
	<artifactId>tips</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>tips</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>



	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

基本所有源碼都貼出來了。跑起來試一下唄

到此這篇關于springboot 實現(xiàn)長鏈接轉(zhuǎn)短鏈接的示例代碼的文章就介紹到這了,更多相關springboot  長鏈接轉(zhuǎn)短鏈接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java常見面試題之多線程和高并發(fā)詳解

    Java常見面試題之多線程和高并發(fā)詳解

    這篇文章主要給大家介紹了關于Java面試題之多線程和高并發(fā)的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-04-04
  • java圖片驗證碼實現(xiàn)示例分享

    java圖片驗證碼實現(xiàn)示例分享

    這篇文章主要介紹了java實現(xiàn)圖片驗證碼示例,需要的朋友可以參考下
    2014-02-02
  • Spring中@Conditional注解的用法

    Spring中@Conditional注解的用法

    這篇文章主要介紹了Spring中@Conditional注解的用法,@Conditional是Spring4新提供的注解,它的作用是按照一定的條件進行判斷,滿足條件給容器注冊bean,需要的朋友可以參考下
    2024-01-01
  • Java通過notify和wait實現(xiàn)線程間的通信功能

    Java通過notify和wait實現(xiàn)線程間的通信功能

    在軟件開發(fā)中,線程是實現(xiàn)并發(fā)執(zhí)行的重要手段,然而,線程之間的協(xié)作與通信卻是開發(fā)者必須重點考慮的挑戰(zhàn)之一,Java作為一種廣泛應用于多線程編程的語言,本文將深入探討Java中通過notify和wait實現(xiàn)線程間通信的機制,需要的朋友可以參考下
    2024-06-06
  • 配置化Feign接口動態(tài)切換URL方式

    配置化Feign接口動態(tài)切換URL方式

    本文介紹了在開發(fā)、測試和生產(chǎn)環(huán)境中使用Feign接口時,根據(jù)不同的環(huán)境動態(tài)切換調(diào)用URL的方法,通過在不同環(huán)境的配置文件中配置URL,并實現(xiàn)一個Feign攔截器來讀取這些配置,從而實現(xiàn)URL的動態(tài)切換,這種方法避免了引入過多步驟,同時也保證了不同環(huán)境下的URL正確調(diào)用
    2024-11-11
  • Mybatis無法獲取帶有下劃線前綴的字段的值問題

    Mybatis無法獲取帶有下劃線前綴的字段的值問題

    這篇文章主要介紹了Mybatis無法獲取帶有下劃線前綴的字段的值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java CountDownLatch與CyclicBarrier及Semaphore使用教程

    Java CountDownLatch與CyclicBarrier及Semaphore使用教程

    對于并發(fā)執(zhí)行,Java中的CountDownLatch是一個重要的類。為了更好的理解CountDownLatch這個類,本文將通過例子和源碼帶領大家深入解析CountDownLatch與CyclicBarrier及Semaphore的原理,感興趣的可以學習一下
    2023-01-01
  • mybatis中如何實現(xiàn)一個標簽執(zhí)行多個sql語句

    mybatis中如何實現(xiàn)一個標簽執(zhí)行多個sql語句

    這篇文章主要介紹了mybatis中如何實現(xiàn)一個標簽執(zhí)行多個sql語句問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Java中system.exit(0) 和 system.exit(1)區(qū)別

    Java中system.exit(0) 和 system.exit(1)區(qū)別

    本文主要介紹了Java中system.exit(0) 和 system.exit(1)區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • 什么是 Java 的 CyclicBarrier(代碼示例)

    什么是 Java 的 CyclicBarrier(代碼示例)

    CyclicBarrier 是多線程協(xié)同的利器,適合需要多次同步的場景,本文通過代碼示例講解什么是 Java 的 CyclicBarrier,感興趣的朋友一起看看吧
    2025-03-03

最新評論