热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javaspr_Java中的42行代码中的URL缩短器服务(Java(?!)SpringBoot+Redis

javaspr显然,编写URL缩短服务是新的“Hello,world!”在IoT微服务时代的世界中。一切始于在45行Scala中的URL缩

java spr

显然,编写URL缩短服务是新的“ Hello,world! ”在IoT /微服务/时代的世界中。 一切始于在45行Scala中的URL缩短服务 -整洁的Scala,以Spray和Redis进行调味以进行存储。 紧随其后的是, 在35行Clojure中提供了url缩短服务 ,甚至在Haskell的43行中提供了URL缩短服务 。 所以我内心的反时髦人士问:用Java语言要花多长时间? 但是,出于善意,不是普通的Java。 带有Spring Data Redis的 Spring Boot是一个很好的起点。 我们需要的只是一个处理GET和POST的简单控制器:

import com.google.common.hash.Hashing;
import org.apache.commons.validator.routines.UrlValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.*;
import java.nio.charset.StandardCharsets;@org.springframework.boot.autoconfigure.EnableAutoConfiguration
@org.springframework.stereotype.Controller
public class UrlShortener {public static void main(String[] args) {SpringApplication.run(UrlShortener.class, args);}&#64;Autowired private StringRedisTemplate redis;&#64;RequestMapping(value &#61; "/{id}", method &#61; RequestMethod.GET)public void redirect(&#64;PathVariable String id, HttpServletResponse resp) throws Exception {final String url &#61; redis.opsForValue().get(id);if (url !&#61; null)resp.sendRedirect(url);elseresp.sendError(HttpServletResponse.SC_NOT_FOUND);}&#64;RequestMapping(method &#61; RequestMethod.POST)public ResponseEntity save(HttpServletRequest req) {final String queryParams &#61; (req.getQueryString() !&#61; null) ? "?" &#43; req.getQueryString() : "";final String url &#61; (req.getRequestURI() &#43; queryParams).substring(1);final UrlValidator urlValidator &#61; new UrlValidator(new String[]{"http", "https"});if (urlValidator.isValid(url)) {final String id &#61; Hashing.murmur3_32().hashString(url, StandardCharsets.UTF_8).toString();redis.opsForValue().set(id, url);return new ResponseEntity<>("http://mydomain.com/" &#43; id, HttpStatus.OK);} elsereturn new ResponseEntity<>(HttpStatus.BAD_REQUEST);}
}

该代码很好地自我描述&#xff0c;并且在功能上等同于Scala中的版本。 我没有尝试过太多的压缩&#xff0c;以使行数尽可能的短&#xff0c;上面的代码很典型&#xff0c;只有很少的细节&#xff1a;

  • 我通常不使用通配符导入
  • 我不使用完全限定的类名&#xff08;我承认我想保存一个import行&#xff09;
  • 我用if括号包围if else用括号括起来
  • 我几乎从不使用场注入&#xff0c;这是控制家族反转中最丑陋的兄弟。 相反&#xff0c;我会去让构造函数允许使用模拟的Redis进行测试&#xff1a;

&#64;Autowired
private final StringRedisTemplate redis;public UrlShortener(StringRedisTemplate redis) {this.redis &#61; redis;
}

我最苦恼的事情是……获取原始的完整URL。 基本上&#xff0c;我需要.com或port之后的所有内容。 没有流血的方式&#xff08;既没有servlet&#xff0c;也没有Spring MVC&#xff09;&#xff0c;因此笨拙的getQueryString()摆弄着。 您可以按以下方式使用该服务-创建较短的URL&#xff1a;

$ curl -vX POST localhost:8080/https://www.google.pl/search?q&#61;tomasz&#43;nurkiewicz> POST /https://www.google.pl/search?q&#61;tomasz&#43;nurkiewicz HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
<
http://mydomain.com/50784f51

通过较短的URL重定向&#xff1a;

$ curl -v localhost:8080/50784f51> GET /50784f51 HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
<

为了完整起见&#xff0c;这是Gradle中的一个构建文件&#xff08;maven也可以使用&#xff09;&#xff0c;在所有以前的解决方案中都跳过了&#xff1a;

buildscript {repositories {mavenLocal()maven { url "http://repo.spring.io/libs-snapshot" }mavenCentral()}dependencies {classpath &#39;org.springframework.boot:spring-boot-gradle-plugin:1.1.5.RELEASE&#39;}
}apply plugin: &#39;java&#39;
apply plugin: &#39;spring-boot&#39;sourceCompatibility &#61; &#39;1.8&#39;repositories {mavenLocal()maven { url &#39;http://repository.codehaus.org&#39; }maven { url &#39;http://repo.spring.io/milestone&#39; }mavenCentral()
}dependencies {compile "org.springframework.boot:spring-boot-starter-web:1.1.5.RELEASE"compile "org.springframework.boot:spring-boot-starter-redis:1.1.5.RELEASE"compile &#39;com.google.guava:guava:17.0&#39;compile &#39;org.apache.commons:commons-lang3:3.3.2&#39;compile &#39;commons-validator:commons-validator:1.4.0&#39;compile &#39;org.apache.tomcat.embed:tomcat-embed-el:8.0.9&#39;compile "org.aspectj:aspectjrt:1.8.1"runtime "cglib:cglib-nodep:3.1"
}tasks.withType(GroovyCompile) {groovyOptions.optimizationOptions.indy &#61; true
}task wrapper(type: Wrapper) {gradleVersion &#61; &#39;2.0&#39;
}

实际上也是42行...这就是整个应用程序&#xff0c;没有XML&#xff0c;没有描述符&#xff0c;没有安装。

对于最短&#xff0c;最模糊的工作代码&#xff0c;我不认为此练习只是一个虚拟的代码。 带有Redis后端的URL缩短器Web服务是给定语言和生态系统的语法和功能的有趣展示。 有趣的是&#xff0c;还有很多算法问题&#xff0c;例如Rosetta代码中发现的问题。 这也是编写REST服务的一个很好的最低限度模板。

原始Scala实现的一个重要功能&#xff08;包括该实现&#xff09;在所有实现中都以某种方式被默默地忘记了&#xff0c;它是非阻塞的。 HTTP和Redis的访问是事件驱动的&#xff08; React &#xff0c;没事&#xff0c;我说&#xff09;&#xff0c;所以我想它可以同时处理客户数以万计。 阻止由Tomcat支持的控制器无法实现这一点。 但是您仍然必须承认&#xff0c;这种用Java编写的服务&#xff08;甚至不是Java 8&#xff01;&#xff09;简明扼要&#xff0c;易于遵循和简单明了-其他解决方案都不是可读的&#xff08;这当然是主观的&#xff09;。

等待别人&#xff01;

翻译自: https://www.javacodegeeks.com/2014/08/url-shortener-service-in-42-lines-of-code-in-java-spring-boot-redis.html

java spr



推荐阅读
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
author-avatar
loloyoyo555
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有