1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/tinyframework-urlshorter

Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

#urlshorter Сначала хочу сказать, что открытый исходный код хостится на @红薯's платформе.

Предыдущий раз я писал статью «Простое проектирование и реализация преобразования длинной URL в короткую», которая была написана довольно仓促,缺乏设计,因此方案也不完整。 Увидев энтузиазм, чтение и сохранение этой статьи, я глубоко обеспокоен тем, что написал такую простую статью, поэтому появилась эта новая статья и её открытый исходный код.

Действительно, на этот раз было затрачено значительное количество времени на дизайн и написание кода, примерно один день.

#потребности

Сначала рассмотрим ключевые моменты:

  1. Текст должен удовлетворять потребностям создания коротких ссылок в различных сценариях.
  2. Текст должен поддерживать различные механизмы последовательностей номеров.
  3. Текст должен поддерживать различные способы создания коротких ссылок.
  4. Гибкость и расширяемость — следует принципу использования хорошего фреймворка, если он не удовлетворяет требованиям, его можно заменить.

Описание основных интерфейсов

Интерфейс генерации строк

package org.tinygroup.shorter;

/**
 * Генератор случайных строк
 * Created by luoguo on 2017/3/24.
 */
public interface StringGenerator {
    String generate(String url);
    void setLength(int length);
}

Метод setLength используется для установки длины генерируемой строки, метод generate используется для генерации соответствующих коротких ссылок.

В предыдущей статье некоторые люди критиковали логику генерации за её недостаточность, но на этот раз многое улучшено, и вы можете свободно выбирать способ, который вам нравится.

Конечно, чтобы сделать всё удобнее для ленивых, также предоставлено стандартное выполнение, которое просто перенёс алгоритм из предыдущей версии.

/**
 * Стандартный генератор случайных строк
 *
 * Created by luoguo on 2017/3/24.
 */
public class StringGeneratorRandom implements StringGenerator {

    public static final char[] VALID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray();
    private static final Random RANDOM = new Random(System.currentTimeMillis());
    private int length = 4;

    public StringGeneratorRandom() {}

    public StringGeneratorRandom(int length) {
        setLength(length);
    }
}```java
    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public String generate(int seed) {
        char[] shortUrl = new char[length];
        for (int i = 0; i < length; i++) {
            shortUrl[i] = VALID_CHARS[seed % VALID_CHARS.length];
            seed = RANDOM.nextInt(Integer.MAX_VALUE) % VALID_CHARS.length;
        }
        return new String(shortUrl);
    }
}
``````markdown
### Генерация случайной строки

Алгоритм очень простой, поэтому подробное объяснение не требуется.

#### Интерфейс генератора коротких ссылок
```java
/**
 *
 * Created by Luoguo on March 24, 2017.
 */
public interface UrlShorterGenerator<T extends ShorterGetter> {
    /**
     * Генерирует объект короткой ссылки
     *
     * @param url
     * @return
     */
    T generate(String url);
}

Здесь всего один метод, который позволяет создать короткую ссылку на основе длинной URL. Некоторые могут спросить, почему здесь используется тип T, если короткая ссылка должна быть просто строкой? Ответ заключается в том, что реальные сценарии использования требуют различных вариантов генерации коротких ссылок — от простых до сложных, таких как ссылки с паролями, ограничениями по количеству запросов и временными рамками доступности.

Поэтому был создан интерфейс ShorterGetter.

/**
 * Для получения короткой ссылки
 * Created by Luoguo on March 24, 2017.
 */
public interface ShorterGetter<T> {
    String getShorter();
}

Этот интерфейс требует только возврата одной строки короткой ссылки, а остальное может быть реализовано по желанию.

В проекте есть пять способов создания коротких ссылок:

#### Простая короткая ссылка
```java
/**
 * Возвращает короткий код и пароль
 * Создан Луогуо 24 марта 2017 года.
 */
public class ShorterString implements ShorterGetter<String> {
    private String shorter;

    public ShorterString() {}

    public ShorterString(String shorter) {
        setShorter(shorter);
    }

    public String getShorter() {
        return shorter;
    }

    public void setShorter(String shorter) {
        this.shorter = shorter;
    }
}

Короткая ссылка с паролем

/**
 * Хранит короткую ссылку и пароль
 * Создан Луогуо 24 марта 2017 года.
 */
public class ShorterWithPassword implements ShorterGetter<ShorterWithPassword> {
    private String shorter;
    private String password;

    public ShorterWithPassword() {}

Краткие ссылки с временем жизни

/**
 * Хранение короткого адреса и времени жизни
 * Создано Луогуо в 2017/03/24
 */
public class ShorterWithPeriod implements ShorterGetter<ShorterWithPeriod> {
    private String shorter;
    private long period;

    public ShorterWithPeriod() {}

    public ShorterWithPeriod(String shorter, long period) {
        setShorter(shorter);
        setPeriod(period);
    }

    public String getShorter() {
        return shorter;
    }

    public void setShorter(String shorter) {
        this.shorter = shorter;
    }

    public long getPeriod() {
        return period;
    }

    public void setPeriod(long period) {
        this.period = period;
    }
}

Краткие ссылки с временем жизни и количеством использований

/**
 * Хранение короткого адреса, времени жизни и количества использований
 * Создано Луогуо в 2017/03/24
 */
public class ShorterWithPeriodAndTimes implements ShorterGetter<ShorterWithPeriodAndTimes> {
    private String shorter;
    private long period;
    private long times;
``````java
/**
 * Для хранения строковых коротких адресов
 * Created by Luoguo on March 24, 2017
 */
public interface ShorterStorage<T extends ShorterGetter> {
    String get(String shortAddress);
    void clean(String url);
    void cleanShorter(String shortAddress);
    void save(String url, T shortAddress);
    void clean();
}

/**
 * Created by Luoguo on March 24, 2017
 */
public class ShorterStorageMemory<T extends ShorterGetter> implements ShorterStorage<T> {
    /**
     * Хранение shortAddress, url
     */
    private final Map<ShorterGetter, String> shortAddressToURLMap = new ConcurrentHashMap<>();
    /**
     * Хранение url, shortAddress
     */
    private final Map<String, ShorterGetter> urlToShortAddressMap = new ConcurrentHashMap<>();
    /**
     * Хранение shortAddress, shortAddress, url
     */
    private final Map<String, ShorterGetter> shortAddressToShortAddressMap = new ConcurrentHashMap<>();
}
    @Override
    public String get(String shortAddressKey) {
        ShorterGetter shortAddress = shortAddressToShortAddressMap.get(shortAddressKey);
        if (shortAddress != null) {
            return shortAddressToURLMap.get(shortAddress);
        }
        return null;
    }

    @Override
    public void clean(String url) {
        ShorterGetter shortAddress = urlToShortAddressMap.get(url);
        if (shortAddress != null) {
            urlToShortAddressMap.remove(url);
            shortAddressToURLMap.remove(shortAddress);
            shortAddressToShortAddressMap.remove(shortAddress.getShortAddress());
        }
    }

    @Override
    public void cleanShorter(String shortAddressKey) {
        ShorterGetter shortAddress = shortAddressToShortAddressMap.get(shortAddressKey);
        if (shortAddress != null) {
            urlToShortAddressMap.remove(shortAddressToURLMap.get(shortAddress));
            shortAddressToURLMap.remove(shortAddress);
            shortAddressToShortAddressMap.remove(shortAddress.getShortAddress());
        }
    }

    @Override
    public void save(String url, T shortAddress) {
        urlToShortAddressMap.put(url, shortAddress);
        shortAddressToURLMap.put(shortAddress, url);
        shortAddressToShortAddressMap.put(shortAddress.getShortAddress(), shortAddress);
    }

    @Override
    public void clean() {
        shortAddressToURLMap.clear();
        shortAddressToShortAddressMap.clear();
        urlToShortAddressMap.clear();
    }
}

Если требуется, вы можете реализовать своё собственное хранилище базы данных, Redis или любой другой способ, который вам нужен. До этого момента основные проблемы были решены; теперь рассмотрим реализацию генератора.

Примечание: Здесь отсутствует контроль за ограничениями, который следует включить при реальном использовании. Например, при получении данных проверьте наличие доступности, если она отсутствует, верните null. ## С генерацией по времениjava /**

  • Генерирует сокращённые ссылки с ограничением по времени использования

  • Создано LuoGou 24 марта 2017 года / public class UrlShorterGeneratorLimitPeriod implements UrlShorterGenerator { private StringGenerator generator; private ShorterStorage shorterStorage; /*

    • Время жизни ссылки в секундах */ private long period;

    public StringGenerator getGenerator() { return generator; }

    public void setGenerator(StringGenerator generator) { this.generator = generator; }

    public ShorterStorage getShorterStorage() { return shorterStorage; }

    public void setShorterStorage(ShorterStorage shorterStorage) { this.shorterStorage = shorterStorage; }

    public long getPeriod() { return period; }

    public void setPeriod(long period) { this.period = period; }

    @Override public ShorterWithPeriod generate(String url) { String shorter = generator.generate(url); while (shorterStorage.get(shorter) != null) { shorter = generator.generate(url); } ShorterWithPeriod shorterWithPeriod = new ShorterWithPeriod(shorter, period); shorterStorage.save(url, shorterWithPeriod); return shorterWithPeriod; } }


## Генератор с ограничением по количеству запросов

```java
/**
 * Генерирует сокращённые ссылки с ограничением по количеству запросов
 * Создано LuoGou 24 марта 2017 года
 */
public class UrlShorterGeneratorLimitTimes implements UrlShorterGenerator<ShorterWithTimes> {
    private StringGenerator generator;
    private ShorterStorage<ShorterWithTimes> shorterStorage;
    /**
     * Ограничение по количеству запросов
     */
    private long times;

    public StringGenerator getGenerator() {
        return generator;
    }

Генератор с ограничением по количеству использований и времени```java

/**

  • Класс для генерации короткого URL с ограничением по количеству использований и времени */ public class UrlShorterGeneratorLimitPeriodAndTimes implements UrlShorterGenerator { private StringGenerator generator; private ShorterStorage shorterStorage;

    /**

    • Время жизни в секундах */ private long period;

    /**

    • Максимальное количество использований */ private long times;

    public StringGenerator getGenerator() { return generator; }

    public void setGenerator(StringGenerator generator) { this.generator = generator; }

    public ShorterStorage getShorterStorage() { return shorterStorage; }

    public void setShorterStorage(ShorterStorage shorterStorage) { this.shorterStorage = shorterStorage; }

    public long getTimes() { return times; }

    public void setTimes(long times) { this.times = times; }

    public long getPeriod() { return period; }

    public void setPeriod(long period) { this.period = period; }

    public ShorterWithPeriodAndTimes generate(String url) { String shorter = generator.generate(url); while (shorterStorage.get(shorter) != null) { shorter = generator.generate(url); }


## Пример

### Генерация фиксированной длины короткого адреса

```java
/**
 * Создано LuoGou на 2017/3/24.
 */
public class UrlShorterGeneratorSimpleTest {
    @Test
    public void generate() throws Exception {
        for (int i = 4; i <= 8; i++) {
            UrlShorterGeneratorSimple simple = new UrlShorterGeneratorSimple();
            simple.setGenerator(new StringGeneratorRandom(i));
            simple.setShorterStorage(new ShorterStorageMemory<>());
            for (int j = 0; j < 5; j++) {
                String shorter = simple.generate("").getShorter();
                assert shorter.length() == i;
                System.out.println(shorter);
            }
        }
    }
}
```### Короткий адрес с паролем

```java
/**
 * Создано luoguo на 2017/3/25.
 */
public class UrlShorterGeneratorWithPasswordTest {
    @Test
    public void generate() throws Exception {
        for (int i = 4; i <= 8; i++) {
            UrlShorterGeneratorWithPassword withPassword = new UrlShorterGeneratorWithPassword();
            withPassword.setShorterGenerator(new StringGeneratorRandom(i));
            withPassword.setPasswordGenerator(new StringGeneratorRandom(4));
            withPassword.setShorterStorage(new ShorterStorageMemory<>());
            for (int j = 0; j < 5; j++) {
                ShorterWithPassword shorter = withPassword.generate("");
                assert shorter.getShorter().length() == i;
                System.out.printf("%s %s\n", shorter.getShorter(), shorter.getPassword());
            }
        }
    }
}

Результат выполнения:

0yET AYOf
37w1 MBjA
SDMg B72n
BdTv KAwd
KQ1w iwiP
mZAVV u8Zx
rdUlH 5a7T
uZQ5i j38x
PUfY0 kfH3
MG3iW bkHO
Ea4TJr Nt8v
2fycK1 6eF3
Q6arED rEID
wc9yf1 kcGr
uGs5uu vKhA
upsmJXt 1IIl
6feAOFV Afqm
j0qPXCG R9VN
2We0RqM 9722
SdgG0Yy tS6e
ZDUyOeeg kiTh

Хаха, результат полностью соответствует моим ожиданиям.

Заключение

Эта версия значительно превзошла предыдущую, с более рациональной архитектурой, расширенными функциями и большей гибкостью. Уверены, что она будет полезна для всех, кто нуждается в таких решениях.

Из-за короткого времени разработки, в проекте могут содержаться ошибки, недочёты или дизайнерские недоработки, поэтому мы приглашаем вас отправлять pull requests для совместной доработки.

Git адрес: https://git.oschina.net/tinyframework/urlshorter.gitДля просмотра других интересных публикаций, перейдите на блог "Успешный Блог". Подписывайтесь на наш канал, если вам интересны наши последние новости.

Если вы считаете этот проект полезным или ценным, не забудьте сделать пожертвование!

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Удовлетворение потребностей в создании коротких ссылок для различных сценариев. Развернуть Свернуть
MIT
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/tinyframework-urlshorter.git
git@api.gitlife.ru:oschina-mirror/tinyframework-urlshorter.git
oschina-mirror
tinyframework-urlshorter
tinyframework-urlshorter
master