首页 > 解决方案 > URL Shortner 算法总是为相同的 URL 返回相同的值

问题描述

我需要将长 URL 转换为其中包含 8 个字符的短 URL 作为缩短 URL,我正在使用带有 Java 的 Spring Boot,问题是每当我尝试缩短相同的 URL 时,我得到的结果相同缩短 URL,但我不希望为相同的链接生成相同的链接

 @RequestMapping(value="/shorturl", method=RequestMethod.POST, consumes={"application/json"})
    public ResponseEntity<?> shortenUrl(HttpServletRequest request,
                                        @ApiParam(value="Body Parameters") @RequestBody @Validated ShortenRequest shortenRequest,
                                        BindingResult bindingResult) throws Exception {
        URLDto urlDto=new URLDto();
        try {
            LOGGER.info("Received url to shorten: " + shortenRequest.getUrl());
            if (bindingResult.hasErrors()) {
                throw new InvalidRequestException("Invalid Request", bindingResult);
            }
            String longUrl=shortenRequest.getUrl();
            if (URLValidator.INSTANCE.validateURL(longUrl)) {
                String shortenedUrl=urlConverterService.shortenURL(shortenRequest.getUrl());
                if (shortenedUrl.equalsIgnoreCase("") || shortenedUrl == null || shortenedUrl.isEmpty()) {
                    urlDto.setUrl("No Records Found");
                    return convertToResponse(urlDto, HttpStatus.NOT_FOUND);
                } else {
                    shortenedUrl=URLValidator.DOMAIN + "/" + shortenedUrl;
                    urlDto.setUrl(shortenedUrl);
                    LOGGER.info("Shortened url to: " + shortenedUrl);
                    return convertToResponse(urlDto, HttpStatus.OK);
                }
            }

        } catch (Exception e) {
            throw new CustomException(e.getMessage());
        }
        return convertToResponse(HttpStatus.OK);
    }

上面的代码是我的控制器方法

 public String shortenURL(String longUrl) {
        urlDetail=new URLDetail();
        String shortenedURL="";
        try {
            LOGGER.info("Shortening {}", longUrl);
            shortenedURL=urlShortener.shortenURL(longUrl);
            if (shortenedURL !=null){
                URLDetail isExistingURL=urlRepository.findByshortenURL(shortenedURL);
                if (isExistingURL == null || isExistingURL.equals("") || isExistingURL.equals(null)) {
                    LOGGER.info("The Unique ID, which is generated is " + shortenedURL);
                    urlDetail.setNoOfHits(0);
                    urlDetail.setShortenURL(shortenedURL);
                    urlDetail.setOriginalURL(longUrl);
                    LOGGER.info("Going to Save the URL Details to DB");
                    urlRepository.save(urlDetail);
                    LOGGER.info("URL Details has been Saved , Returning the shorten URL " + shortenedURL);
            }
                else{
                    LOGGER.info("Going to call shortenURL() in order to Shorten the URL (Recursive Call)");
                    shortenURL(longUrl);
                }
            } else {
                LOGGER.info("Going to call shortenURL() in order to Shorten the URL (Recursive Call)");
                shortenURL(longUrl);
            }
            return shortenedURL;
        } catch (Exception e) {
            LOGGER.info("Some issue while shortening the URL, Shorten URL{} " + e.getMessage());
            LOGGER.error("Some Issue while Shortening the URL, Shorten URL{} " + e.getMessage());
        }
        return shortenedURL;
    }

上面的代码是我的服务类方法,最后我的实际转换器类看起来像下面的代码

@EnableAutoConfiguration
@Service
public class URLShortener {
    // In order to store the generated key
    private HashMap<String, String> keyMap;
    private HashMap<String, String> valueMap;

    //THis attribute is used to map to our custom server url
    private String domain;
    private char myChars[];
    // Random Object used to generate random integers
    private Random myRandom;
    private int keyLength;

    URLShortener() {
        keyMap = new HashMap<>();
        valueMap = new HashMap<>();
        myRandom = new Random();
        keyLength = 8;
        myChars = new char[62];
        for (int i = 0; i < 62; i++) {
            int j = 0;
            if (i < 10) {
                j = i +  48;
            } else if (i > 9 && i <= 35) {
                j = i + 55;
            } else {
                j = i + 61;
            }
            myChars[i] = (char) j;
        }
        domain = "https://abc.in";
    }

    // Constructor to define tiny URL key length and base URL
    URLShortener(int length, String newDomain) {
        this();
        this.keyLength = length;
        if (!newDomain.isEmpty()) {
            newDomain = sanitizeURL(newDomain);
            domain = newDomain;
        }

    }

       // Shorten URL For the Public which can be called to shorten a given URL
    public String shortenURL(String longURL) {
        String shortURL = "";
        if (URLValidator.INSTANCE.validateURL(longURL)) {
            longURL = sanitizeURL(longURL);
            if (valueMap.containsKey(longURL)) {
                shortURL = valueMap.get(longURL);
            } else {
                shortURL = getKey(longURL);
            }
        }
        return shortURL;
    }

    //Expand URL public method by which returns back the original URL given the shorten URL
    public String expandURL(String shortURL) {
        String longURL = "";
//        String key = shorURL.substring(domain.length() + 1);
        longURL = keyMap.get(shortURL);
        return longURL;
    }

    // In order to Validate the URL Which whether given URL is valid or not, not implemented as of now, returning true as of now
    private boolean validateURL(String url) {
        return true;
    }

    //Sanitize URL takes care of several Issues with a valid URL
    private String sanitizeURL(String url) {
        if (url.substring(0, 7).equals("http://"))
            url = url.substring(7);

        if (url.substring(0, 8).equals("https://"))
            url = url.substring(8);

        if (url.charAt(url.length() - 1) == '/')
            url = url.substring(0, url.length() - 1);
        return url;
    }

    private String getKey(String longURL) {
        String key;
        key = generateKey();
        keyMap.put(key, longURL);
        valueMap.put(longURL, key);
        return key;
    }

    private String generateKey() {
        String key = "";
        boolean flag = true;
        if (flag) {
            key = "";
            for (int i = 0; i <= keyLength; i++) {
                key += myChars[myRandom.nextInt(62)];
            }
            if (!keyMap.containsKey(key)) {
                flag = false;
            }
        }
        return key;
    }

}

我的模型类看起来像这样

公共类 ShortenRequest {

private String url;

@JsonCreator
public ShortenRequest() {

}

@JsonCreator
public ShortenRequest(@JsonProperty("url") String url) {
    this.url = url;
}

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}

}

我不明白为什么它会一遍又一遍地为相同的链接生成相同的链接,对此的任何帮助将不胜感激。

标签: javaalgorithmspring-booturl-rewritingurl-shortener

解决方案


推荐阅读