Spark入门:也可以用Java创建轻量级的RESTful应用程序

最近,我一直在使用Spark (一种Java的Web框架,与Apache Spark 相关)编写RESTful服务。 当我们计划写这篇文章时,我已经做好了不可避免的接口,样板代码和深层层次结构的Java风格的准备。 我很惊讶地发现,对于局限于Java的开发人员来说,还存在一个替代世界。

在本文中,我们将了解如何使用JSON传输数据来为博客构建RESTful应用程序。 我们会看到:

  • 如何在Spark中创建一个简单的Hello World
  • 如何指定请求中期望的JSON对象的布局
  • 如何发送帖子请求以创建新帖子
  • 如何发送获取请求以检索帖子列表

我们不会看到如何在数据库中插入该数据。 我们只将列表保留在内存中(在我的实际服务中,我一直在使用sql2o )。

一些依赖

我们将使用Maven,因此我将首先创建一个新的pom.xml并添加一些内容。 基本上:

  • 火花
  • 杰克逊
  • Lombok
  • 番石榴
  • Easymock(仅在测试中使用,本文中未介绍)
  • 格森
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>com.sparkjava</groupId><artifactId>spark-core</artifactId><version>2.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.5.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.5.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.2</version><scope>provided</scope></dependency><dependency><groupId>org.sql2o</groupId><artifactId>sql2o</artifactId><version>1.5.4</version></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>9.4-1201-jdbc41</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>18.0</version></dependency><dependency><groupId>org.easymock</groupId><artifactId>easymock</artifactId><version>3.3.1</version><scope>test</scope></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.3.1</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.2</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.2.1</version><configuration><mainClass>me.tomassetti.BlogService</mainClass><arguments></arguments></configuration></plugin></plugins></build>

火花你好世界

你有这一切吗? 太酷了,然后编写一些代码。

package me.tomassetti;import static spark.Spark.get;
import static spark.Spark.post;
import spark.Request;
import spark.Response;
import spark.Route;public class BlogService 
{public static void main( String[] args) {get("/posts", (req, res) -> {return "Hello Sparkingly World!";});}
}

现在,我们可以使用以下命令运行它:

mvn compile && mvn exec:java

让我们打开浏览器并访问localhost http:// localhost:4567 / posts 。 在这里我们要做一个简单的获取。 对于执行帖子,您可能想要在浏览器中使用Postman插件,或者只运行curl 。 一切为您服务。

使用Jackson和Lombok进行很棒的描述性交换对象

在典型的RESTful应用程序中,我们希望接收带有json对象的POST请求作为有效负载的一部分。 我们的工作将是检查代码是否为格式正确的JSON,是否与预期的结构相对应,值是否在有效范围内,等等。无聊且重复。 我们可以用不同的方式做到这一点。 最基本的一种是使用gson :

JsonParser parser = new JsonParser();
JsonElement responseData = parser.parse(response);
if (!responseData.isJsonObject()){// send an error like: "Hey, you did not pass an Object!
}
JsonObject obj = responseData.getAsJsonObject();
if (!obj.hasField("title")){// send an error like: "Hey, we were expecting a field name title!
}
JsonElement titleAsElem = obj.get("title");
if (!titleAsElem.isString()){// send an error like: "Hey, title is not an string!
}
// etc, etc, etc

我们可能不想这样做。

指定我们期望的结构的更具声明性的方法是创建特定的类。

class NewPostPayload {private String title;private List<String> categories;private String content;public String getTitle() { ... }public void setTitle(String title) { ... }public List<String> getCategories() { ... }public void setCategories(List<String> categories){ ... }public String getContent() { ... }public void setContent(String content) { ... }
}

然后我们可以使用Jackson:

try {ObjectMapper mapper = new ObjectMapper();NewPostPayload newPost = mapper.readValue(request.body(), NewPostPayload.class);
} catch (JsonParseException e){// Hey, you did not send a valid request!
}

这样,杰克逊会自动为我们检查有效载荷是否具有预期的结构。 我们可能想验证是否遵守其他约束。 例如,我们可能要检查标题是否为空,并且至少指定了一个类别。 我们可以创建一个仅用于验证的接口:

interface Validable {boolean isValid();
}class NewPostPayload implements Validable {private String title;private List<String> categories;private String content;public String getTitle() { ... }public void setTitle(String title) { ... }public List<String> getCategories() { ... }public void setCategories(List<String> categories){ ... }public String getContent() { ... }public void setContent(String content) { ... }public boolean isValid() {return title != null && !title.isEmpty() && !categories.isEmpty();}
}

仍然有很多无聊的getter和setter方法。 它们的信息量不是很大,只会污染代码。 我们可以使用Lombok摆脱它们。 Lombok是一个注释处理器,可以为您添加重复方法(getter,setter,equals,hashCode等)。 您可以将其视为编译器的插件,该插件可查找注释(例如@Data )并基于注释生成方法。 如果将其添加到依赖项中,maven会很好,但是您的IDE无法自动完成Lombok添加的方法。 您可能要安装插件。 对于Intellij Idea,我使用的是Lombok插件版本0.9.1,它的效果很好。

现在,您可以将类NewPostPayload修改为:

@Data
class NewPostPayload {private String title;private List<String> categories;private String content;public boolean isValid() {return title != null && !title.isEmpty() && !categories.isEmpty();}
}

好多了,是吗?

一个完整的例子

我们基本上需要做两件事:

  1. 插入新帖子
  2. 检索整个帖子列表

第一个操作应实现为POST(具有副作用),而第二个操作应实现为GET。 它们都对posts集合进行操作,因此我们将使用端点/ posts

让我们从插入帖子开始。 首先我们要解析

// insert a post (using HTTP post method)post("/posts", (request, response) -> {try {ObjectMapper mapper = new ObjectMapper();NewPostPayload creation = mapper.readValue(request.body(), NewPostPayload.class);if (!creation.isValid()) {response.status(HTTP_BAD_REQUEST);return "";}int id = model.createPost(creation.getTitle(), creation.getContent(), creation.getCategories());response.status(200);response.type("application/json");return id;} catch (JsonParseException jpe) {response.status(HTTP_BAD_REQUEST);return "";}});

然后查看如何检索所有帖子:

// get all post (using HTTP get method)get("/posts", (request, response) -> {response.status(200);response.type("application/json");return dataToJson(model.getAllPosts());});

最后的代码是:

package me.tomassetti;import static spark.Spark.get;
import static spark.Spark.post;import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.Data;
import spark.Request;
import spark.Response;
import spark.Route;import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;public class BlogService 
{private static final int HTTP_BAD_REQUEST = 400;interface Validable {boolean isValid();}@Datastatic class NewPostPayload {private String title;private List<String> categories = new LinkedList<>();private String content;public boolean isValid() {return title != null && !title.isEmpty() && !categories.isEmpty();}}// In a real application you may want to use a DB, for this example we just store the posts in memorypublic static class Model {private int nextId = 1;private Map<Integer, Post> posts = new HashMap<>();@Dataclass Post {private int id;private String title;private List<String> categories;private String content;}public int createPost(String title, String content, List<String> categories){int id = nextId++;Post post = new Post();post.setId(id);post.setTitle(title);post.setContent(content);post.setCategories(categories);posts.put(id, post);return id;}public List<Post> getAllPosts(){return posts.keySet().stream().sorted().map((id) -> posts.get(id)).collect(Collectors.toList());}}public static String dataToJson(Object data) {try {ObjectMapper mapper = new ObjectMapper();mapper.enable(SerializationFeature.INDENT_OUTPUT);StringWriter sw = new StringWriter();mapper.writeValue(sw, data);return sw.toString();} catch (IOException e){throw new RuntimeException("IOException from a StringWriter?");}}public static void main( String[] args) {Model model = new Model();// insert a post (using HTTP post method)post("/posts", (request, response) -> {try {ObjectMapper mapper = new ObjectMapper();NewPostPayload creation = mapper.readValue(request.body(), NewPostPayload.class);if (!creation.isValid()) {response.status(HTTP_BAD_REQUEST);return "";}int id = model.createPost(creation.getTitle(), creation.getContent(), creation.getCategories());response.status(200);response.type("application/json");return id;} catch (JsonParseException jpe) {response.status(HTTP_BAD_REQUEST);return "";}});// get all post (using HTTP get method)get("/posts", (request, response) -> {response.status(200);response.type("application/json");return dataToJson(model.getAllPosts());});}
}

使用PostMan尝试应用程序

如果您更喜欢命令行,则可能要改用curl。 我喜欢不必转义JSON并拥有基本的编辑器,因此可以使用PostMan(Chrome插件)。

让我们插入一个帖子。 我们将所有字段指定为插入到请求正文中的Json对象的一部分。 我们获取创建的帖子的ID。

Screen-Shot-2015-03-30-at-17.25.22

然后,我们可以获得帖子列表。 在这种情况下,我们使用GET(请求中没有正文),并获取所有帖子的数据(仅是我们在上面插入的帖子)。

Screen-Shot-2015-03-30-at-17.30.33

结论

我不得不说,我对该项目感到非常惊讶。 我已经准备好了变得更糟:这是一种需要基本逻辑和大量管道的应用程序。 我发现Python,Clojure和Ruby在解决此类问题方面都做得很好,而当我用Java编写简单的Web应用程序时,逻辑就被样板代码淹没了。 好吧,事情可能会有所不同。 Spark,Lombok,Jackson和Java 8的结合确实很诱人。 我非常感谢这些软件的作者,他们确实在改善Java开发人员的生活。 我认为这也是一个教训:出色的框架可以经常改进很多事情,而这超出了我们的想象。

编辑:我从reddit的好人那里收到了一个改进示例的建议。 谢谢! 请保持良好的建议来!

翻译自: https://www.javacodegeeks.com/2015/08/getting-started-with-spark-it-is-possible-to-create-lightweight-restful-application-also-in-java.html

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

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

相关文章

前端全栈大佬是如何使用javaScript实现一个轮播图

效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title>轮播图</title><style>ul,li{list-style: none;}#outer{width: 400px;height: 300px;position: relative;margin:…

Win7\xp添加虚拟网Microsoft Loopback Adapter

Win7\xp添加虚拟网Microsoft Loopback Adapter Microsoft Loopback Adapter &#xff08;微软回环网卡&#xff09;&#xff0c;做为IT网络的人员应该都知道是什么吧。安装一个 loopbackp 虚拟网卡对于一般的网络测试都有不少作用。下面本经验就给大家演示一下win7 XP如何添加微…

CentOS7重置root密码

忘记了root用户密码&#xff0c;有几种方法可以可以解决&#xff0c;分享给大家~ 这几种方法不会使系统中的任何资料丢失 亲测有效&#xff01;&#xff01;&#xff01; 第一种方法&#xff1a; 1&#xff09;开启虚拟机 2&#xff09;在弹出这个界面时&#xff0c;按上下键防…

mongodb 监控权限_运维监控产品分析篇

开源运维监控系统篇1.zabbix用户群&#xff1a;85%以上的泛互联网企业。 优点&#xff1a;支持多平台的企业级分布式开源监控软件 安装部署简单&#xff0c;多种数据采集插件灵活集成 功能强大&#xff0c;可实现复杂多条件告警&#xff0c; 自带画图功能&#xff0c;得到的…

前端全栈大佬是如何使用javaScript实现一个无缝轮播

效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title>无缝轮播图</title><style>ul,li{list-style: none;}#outer{width: 400px;height: 300px;position: relative;mar…

iOS消息推送机制的实现

iOS消息推送的工作机制可以简单的用下图来概括&#xff1a; Provider是指某个iPhone软件的Push服务器&#xff0c;APNS是Apple Push Notification Service的缩写&#xff0c;是苹果的服务器。 上图可以分为三个阶段&#xff1a; 第一阶段&#xff1a;应用程序把要发送的消息、目…

导出镜像备份阿里ECS并在本地虚拟机中运行

概述 事情是这样的&#xff0c;阿里云原先的云翼计划没有了&#xff0c;云翼机器也无法再按价续费&#xff0c;而通过新的开发者计划购买的轻量应用服务器又不支持从ECS迁移&#xff0c;因此为了备份数据&#xff0c;避免服务器过期后资源被释放造成不可逆损失&#xff0c;故尝…

graph面板x轴模式包括哪些_发那科数控车床面板讲解

数控机床操作面板是数控机床的重要组成部件&#xff0c;是操作人员与数控机床(系统)进行交互的工具&#xff0c;主要有显示装置、NC键盘、MCP、状态灯、手持单元等部分组成。数控车床的类型和数控系统的种类很多&#xff0c;以及各生产厂家设计的操作面板也不尽相同&#xff0c…

前端全栈大佬是如何使用javaScript实现一个无缝轮播优化

效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title>优化后的无缝轮播图</title><style>body{-webkit-user-select: none; }ul,li{list-style: none;}#outer{width: 4…

74cms 5.0.1版本文件包含漏洞复现

漏洞成因&#xff1a;由于74CMS 某些函数存在过滤不严格&#xff0c;攻击者通过构造恶意请求&#xff0c;配合文件包含漏洞可在无需登录的情况下执行任意代码&#xff0c;控制服务器。 下载地址&#xff1a; http://www.74cms.com/download/index.html下载后解压到phpstudy的根…

给Java程序猿们推荐一些值得一看的好书

学习的最好途径就是看书 "学习的最好途径就是看书"&#xff0c;这是我自己学习并且小有了一定的积累之后的第一体会。个人认为看书有两点好处&#xff1a; 1、能出版出来的书一定是经过反复的思考、雕琢和审核的&#xff0c;因此从专业性的角度来说&#xff0c;一本好…

pr基本图形模板无法使用_PR模板21个时尚排版竖屏封面图形标题动画【资源分享1218】...

AE特效PR剪辑C4D动画影视后期全世界只有不到1%的人关注了你是个很特别的人AE影视后期定期推送「AEPRC4D 影视特效合成 婚庆剪辑调色 电视广告包装 微电影制作 SpeedGrade达芬奇专业调色 摄影等」打造影视后期高端学习平台影视后期 ID&#xff1a;AEPRC4D6【PR模板信息】适用软件…

前端全栈大佬是如何使用javaScript实现一个无缝轮播(最终版)

效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title>优化后的无缝轮播图</title><style>body{-webkit-user-select: none; }ul,li{list-style: none;}#outer{width: 4…

通达OA系统11.2漏洞

以通达OA系统11.2版本为案例的Web渗透 1. 渗透背景&#xff1a;2. 存在漏洞3. 漏洞复现3.1 前台任意用户登录漏洞3.1.1 漏洞原理&#xff1a;3.1.2 手工抓包复现&#xff1a;3.1.3 POC自动获取复现&#xff1a; 3.2 前台未授权访问漏洞3.3 管理后台文件上传漏洞3.4 后台SQL注入…

小白如何从零开始设计并开发一个微信小程序?

背景:微信小程序的出现,让更多的中小型企业初期不再以APP为首选,小程序的天然优势让他备受关注,也因此诞生了专门的小程序开发岗位,让前端有机会继续蚕食其他岗位的份额。 但微信小程序也会很多缺点,最大的就是监管太霸道,各种限制行业进入和权限,未开发的行业还是不能…

mvc2 mvc_每个人都知道MVC…

mvc2 mvc从一个最近的博客中&#xff0c;您可能会发现我最近一直在进行一些采访&#xff0c;就像他们对Web应用程序开发人员所说的那样&#xff0c;我问的一个问题是“您能解释一下MVC模式是什么吗&#xff1f;”&#xff0c;值得赞扬的是&#xff0c;每个候选人知道答案。 对于…

移动端 长按事件_Flutter事件监听

一. 事件监听 在大前端的开发中&#xff0c;必然存在各种各样和用户交互的情况&#xff1a;比如手指点击、手指滑动、双击、长按等等。在Flutter中&#xff0c;手势有两个不同的层次&#xff1a;第一层&#xff1a;原始指针事件(Pointer Events)&#xff1a;描述了屏幕上由触摸…

在CSDN的博文中如何添加博主名片

前言&#xff1a;以前看到很多大佬博文中都有自己的名片&#xff0c;我以为是他们自己打字打上去的&#xff0c;自己打上去样式却不理想。今天终于发现了新大陆。分享给你们。 效果图&#xff1a; 设置方法如图&#xff1a;找到创作权益——博主名片——展示博文详情页&#xf…

vscode中文设置不生效_VSCode详细安装教程

1.下载https://code.visualstudio.com/download 是Microsoft&#xff08;微软的产品&#xff09;User Installer版&#xff1a;会安装在当前计算机帐户目录,意味着如果使用另一个帐号登陆计算机将无法使用别人安装的vscode。System Installer版&#xff1a;安装在非用户目录,例…

毛绒材质渲染_学室内设计必进,建模渲染那都不是事儿

近年来&#xff0c;室内设计从业人员需求量和薪酬持续增长带来的是室内设计行业的飞速发展&#xff0c;而设计能力也成为“创新与创造”的不可或缺。设计能力是多方面能力的综合体现而室内效果图作为设计成果的最主要表现手段&#xff0c;是最基础也是最重要的技能之一。那么持…