java spr_Java中的42行代码中的URL缩短器服务(Java(?!)Spring Boot + Redis

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);}@Autowired private StringRedisTemplate redis;@RequestMapping(value = "/{id}", method = RequestMethod.GET)public void redirect(@PathVariable String id, HttpServletResponse resp) throws Exception {final String url = redis.opsForValue().get(id);if (url != null)resp.sendRedirect(url);elseresp.sendError(HttpServletResponse.SC_NOT_FOUND);}@RequestMapping(method = RequestMethod.POST)public ResponseEntity<String> save(HttpServletRequest req) {final String queryParams = (req.getQueryString() != null) ? "?" + req.getQueryString() : "";final String url = (req.getRequestURI() + queryParams).substring(1);final UrlValidator urlValidator = new UrlValidator(new String[]{"http", "https"});if (urlValidator.isValid(url)) {final String id = Hashing.murmur3_32().hashString(url, StandardCharsets.UTF_8).toString();redis.opsForValue().set(id, url);return new ResponseEntity<>("http://mydomain.com/" + id, HttpStatus.OK);} elsereturn new ResponseEntity<>(HttpStatus.BAD_REQUEST);}
}

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

  • 我通常不使用通配符导入
  • 我不使用完全限定的类名(我承认我想保存一个import行)
  • 我用if括号包围if else用括号括起来
  • 我几乎从不使用场注入,这是控制家族反转中最丑陋的兄弟。 相反,我会去让构造函数允许使用模拟的Redis进行测试:
@Autowired
private final StringRedisTemplate redis;public UrlShortener(StringRedisTemplate redis) {this.redis = redis;
}

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

$ curl -vX POST localhost:8080/https://www.google.pl/search?q=tomasz+nurkiewicz> POST /https://www.google.pl/search?q=tomasz+nurkiewicz HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: text/plain;charset=ISO-8859-1
< Content-Length: 28
< Date: Sat, 23 Aug 2014 20:47:40 GMT
<
http://mydomain.com/50784f51

通过较短的URL重定向:

$ curl -v localhost:8080/50784f51> GET /50784f51 HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 302 Found
< Server: Apache-Coyote/1.1
< Location: https://www.google.pl/search?q=tomasz+nurkiewicz
< Content-Length: 0
< Date: Sat, 23 Aug 2014 20:48:00 GMT
<

为了完整起见,这是Gradle中的一个构建文件(maven也可以使用),在所有以前的解决方案中都跳过了:

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

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

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

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

等待别人!

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

java spr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339778.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python邮件发送哪个好_python发邮件(一)

复习模块如果我们要发送邮件&#xff0c;就需要用到smtplib模块的以下方法&#xff1a;1、import smtplib #引入smtplib模块2、server smtplib.SMTP() #server为变量&#xff0c;通过SMTP指定一个服务器&#xff0c;这样才能把邮件送到另一个服务器&#xff0c;SMTP…

SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战

问题 从卡夫卡镜子制造商转移到布鲁克林有我在这里所写的优势。 但是&#xff0c;进行这种迁移并不容易&#xff0c;因为它本来应该如此。 我面临的主要挑战是&#xff1a;在消费者Kafka经纪人和Brooklin之间建立SSL连接 解 SSL问题 事实证明&#xff0c;这个问题比我预期的要…

mysql移动数据的语句是_mysql基本语句

MySQL关系型数据库RDS中的老大哥&#xff0c;增删改查是MySQL入门的基础增删改查语句增删改查的语句命令为增&#xff1a;insert删&#xff1a;delete改&#xff1a;update查&#xff1a;SELECT或者show库操作创建数据库&#xff1a;create database shujukuba;创建带字符集的数…

jetty嵌入式容器_嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务

jetty嵌入式容器最近&#xff0c;我遇到了一个非常有趣的问题&#xff0c;我认为这只需要几分钟就可以解决&#xff1a;在Linux中使用Spring Security &#xff08;当前稳定版本3.2.5 &#xff09;保护Apache CXF &#xff08;当前版本3.0.1 &#xff09;/ JAX-RS REST服务。在…

python逻辑运算符的使用_总结Python中逻辑运算符的使用

下表列出了所有python语言支持的逻辑运算符。假设变量a持有10和变量b持有20&#xff0c;则&#xff1a;示例:试试下面的例子就明白了所有的python编程语言提供了逻辑运算符&#xff1a;#!/usr/bin/pythona 10b 20c 0if ( a and b ):print "line 1 - a and b are true&q…

如何使用用户数据脚本在EC2实例上安装Apache Web Server

你好朋友&#xff0c; 在本教程中&#xff0c;我们将看到如何使用用户数据脚本在EC2实例上安装Apache Web Server。 在我以前的教程之一中&#xff0c;我已经解释了如何使用AWS控制台启动EC2实例。如果您还没有完成该操作&#xff0c;我建议您先进行一下操作。 首先&#xf…

java 常量接口_java接口定义常量研究

背景和同事讨论到&#xff0c;在接口中定义常量的问题&#xff0c;引发了争论&#xff0c;即&#xff0c;假如在接口中定义变量&#xff0c;是否需要用static来限定的问题&#xff0c;或者说用static和不用static会有什么区别。引论package spring.interfaceTest;public interf…

spring 多租户_使用Spring Security的多租户应用程序的无状态会话

spring 多租户从前&#xff0c; 我发表了一篇文章&#xff0c;解释了构建无状态会话的原理 。 巧合的是&#xff0c;我们再次为多租户应用程序执行同一任务。 这次&#xff0c;我们将解决方案集成到Spring Security框架中&#xff0c;而不是自己构建身份验证机制。 本文将解释…

java api 1.6 下载_Java JDK API

JDKJavaDevelopmentKit是SunMicrosystems针对Java开发员的产品。自从Java推出以来&#xff0c;JDK已经成为使用最广泛的JavaSDK。JDK是整个Java的核心&#xff0c;包括了Java运行环境。相关软件软件大小版本说明下载地址jdk(Java Development Kit)是Sun Microsystems针对java开…

Java / Cloud:如何快速创建支持Kubernetes的REST微服务

可以肯定地说&#xff0c;如今微服务与云的结合风靡一时。 微服务的开发比以往任何时候都多&#xff0c;从而导致应用程序部署数量增加。 在过去的十年中&#xff0c;开发了诸如Docker和Kubernetes之类的容器化和编排工具&#xff0c;从而使微服务模式真正易于采用。 本文将教…

java考试安徽工业大学_2011~2012《Java语言程序设计》试卷A及答案(安徽工业大学)...

《2011~2012《Java语言程序设计》试卷A及答案(安徽工业大学)》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《2011~2012《Java语言程序设计》试卷A及答案(安徽工业大学)(6页珍藏版)》请在人人文库网上搜索。1、装 订 线 安 徽 工 业 大 学 试 题 纸(一)20112012学年第…

jsr303自定义验证_JSR 310新日期/时间API的自定义JSR 303 Bean验证约束

jsr303自定义验证借助JSR 310&#xff0c;Java 8终于为我们带来了不错的日期和时间API。 对于仍在使用Java 7的那些人&#xff08;就像我目前在我的当前项目中一样&#xff09;&#xff0c;有很好的反向移植&#xff0c;请访问www.threeten.org了解更多详细信息。 但是&#xf…

java spring注入 静态方法_JAVA静态方法中如何使用spring@Value进行注入的成员变量...

背景&#xff1a;一个旧项目原本集成有spring-session&#xff0c;现需要临时添加缓存的操作&#xff0c;需要复用spring-session中的一些缓存配置。实现方法&#xff1a;一、类上添加注解Component二、定义静态成员变量private static String redisUrl;private static String …

使用Testcontainers和PostgreSQL,MySQL或MariaDB的Spring Boot测试

Testcontainers是一个Java库&#xff0c;可轻松将Docker容器集成到JUnit测试中。 在Containerized World中 &#xff0c;将测试配置与嵌入式数据库和服务复杂化几乎没有意义。 而是使用在Docker中运行您的服务&#xff0c;并让Testcontainers为您管理此服务。 在此博客文章中&…

使用Spring Boot和Project Reactor处理SQS消息-第2部分

这是我关于使用Spring Boot和Project Reactor有效处理SQS消息的博客文章的后续文章 我在第一部分中列出了一些方法上的差距。 1.处理SQS客户端调用中的失败 2.该方法一次只能处理来自SQS的一条消息&#xff0c;如何并行化 3.它不处理错误&#xff0c;管道中的任何错误都会中…

java爬虫jsoup_Java爬虫之利用Jsoup自制简单的搜索引擎

内容导读在上述代码中&#xff0c;url为输入词条(暂时仅限于英文)&#xff0c;进入while循环可一直搜索&#xff0c;当输入为’exit’时退出。contentText为该词条的百度百科简介的网页形式&#xff0c;通过正则表达式将其中的文字提取出来。代码虽然简洁&#xff0c;但是功能还…

shader weaver_具有自定义汇编程序,Weaver和运行时的可插拔知识

shader weaver作为贝叶斯工作的一部分&#xff0c;我对Kie进行了很多重构&#xff0c;使其具有清晰的扩展点。 我想确保可以完成贝叶斯系统的所有工作部件&#xff0c;而无需在现有内核中添加任何代码。 因此&#xff0c;现在每种知识类型都可以拥有自己的包&#xff0c;汇编器…

matplotlib的默认字体_浅谈matplotlib默认字体设置探索

控制默认字体的设置根据官方文档https://matplotlib.org/tutorials/text/text_props.html#default-font可知&#xff1a;The base default font is controlled by a set of rcParams默认字体是由一组rcParams控制的。rcParamusage‘font.family"List of either names of f…

如何使用Apache Camel,Quarkus和GraalVM快速运行100个骆驼

今天&#xff0c;我继续在youtube上练习&#xff0c;并录制了10分钟的视频&#xff0c;介绍了如何创建一个新的Camel and Quarkus项目&#xff0c;该项目包括Rest和HTTP服务以及开箱即用的健康检查和指标。 然后比较以JVM模式运行示例与使用GraalVM编译的本机内存的使用情况。…

java空心菱形_java 空心菱形

分为两部分&#xff0c;先打印前四行&#xff0c;再打印后三行&#xff0c;int n 4;    //设初始值为4for(int i0;ifor(int j0;jSystem.out.print(" ");}for(int k0;kif(k0||k2*i) {    //打印前四行的*&#xff0c;中间部分输出空格System.out.print(&quo…