成都设计网站的公司,广西人才网官方网站,wordpress内容页不显示图片,wordpress plugins插件免责声明 #xff1a;这篇文章是关于名为Spark的Java微型Web框架的#xff0c;而不是关于数据处理引擎Apache Spark的 。 在此博客文章中#xff0c;我们将看到如何使用Spark构建简单的Web服务。 如免责声明中所述#xff0c;Spark是受Ruby框架Sinatra启发的Java微型Web框… 免责声明 这篇文章是关于名为Spark的Java微型Web框架的而不是关于数据处理引擎Apache Spark的 。 在此博客文章中我们将看到如何使用Spark构建简单的Web服务。 如免责声明中所述Spark是受Ruby框架Sinatra启发的Java微型Web框架。 Spark的目的是简化操作仅提供最少的功能集。 但是它提供了用几行Java代码构建Web应用程序所需的一切。 入门 假设我们有一个带有一些属性的简单域类和一个提供一些基本CRUD功能的服务 public class User {private String id;private String name;private String email;// getter/setter
}public class UserService {// returns a list of all userspublic ListUser getAllUsers() { .. }// returns a single user by idpublic User getUser(String id) { .. }// creates a new userpublic User createUser(String name, String email) { .. }// updates an existing userpublic User updateUser(String id, String name, String email) { .. }
} 现在我们希望将UserService的功能公开为RESTful API为简单起见我们将跳过REST的超媒体部分。 为了访问创建和更新用户对象我们要使用以下URL模式 得到 /用户 获取所有用户的列表 得到 / users / id 获取特定用户 开机自检 /用户 创建一个新用户 放 / users / id 更新用户 返回的数据应为JSON格式。 要开始使用Spark我们需要以下Maven依赖项 dependencygroupIdcom.sparkjava/groupIdartifactIdspark-core/artifactIdversion2.0.0/version
/dependency
dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-simple/artifactIdversion1.7.7/version
/dependency Spark使用SLF4J进行日志记录因此我们需要SLF4J活页夹才能查看日志和错误消息。 在此示例中我们为此目的使用slf4j-simple依赖项。 但是您也可以使用Log4j或您喜欢的任何其他绑定程序。 在类路径中使用slf4j-simple足以在控制台中查看日志输出。 我们还将使用GSON生成JSON输出并使用JUnit编写简单的集成测试。 您可以在完整的pom.xml中找到这些依赖项。 返回所有用户 现在该创建一个负责处理传入请求的类了。 我们首先实现GET / users请求该请求应返回所有用户的列表。 import static spark.Spark.*;public class UserController {public UserController(final UserService userService) {get(/users, new Route() {Overridepublic Object handle(Request request, Response response) {// process requestreturn userService.getAllUsers();}});// more routes}
} 注意第一行中的spark.Spark。*的静态导入。 这使我们可以访问各种静态方法包括getpostput等。 在构造函数中get方法用于注册一个Route该Route侦听/ users上的GET请求。 路由负责处理请求。 每当发出GET / users请求时都会调用handle方法。 在handle内部我们返回一个应发送给客户端的对象在本例中为所有用户的列表。 Spark从Java 8 Lambda表达式中受益匪浅。 Route是一个功能接口仅包含一种方法因此我们可以使用Java 8 Lambda表达式来实现它。 使用Lambda表达式上面的Route定义如下所示 get(/users, (req, res) - userService.getAllUsers()); 要启动该应用程序我们必须创建一个简单的main方法。 在main内部我们创建服务的实例并将其传递给我们新创建的UserController public class Main {public static void main(String[] args) {new UserController(new UserService());}
} 如果现在运行mainSpark将启动一个侦听端口4567的嵌入式Jetty服务器。我们可以通过启动GET http// localhost4567 / users请求来测试我们的第一个路由。 如果服务返回包含两个用户对象的列表则响应主体可能如下所示 [com.mscharhag.sparkdemo.User449c23fd, com.mscharhag.sparkdemo.User437b26fe] 显然这不是我们想要的回应。 Spark使用名为ResponseTransformer的接口将路由返回的对象转换为实际的HTTP响应。 ReponseTransformer看起来像这样 public interface ResponseTransformer {String render(Object model) throws Exception;
} ResponseTransformer具有一个方法该方法接受一个对象并返回此对象的String表示形式。 ResponseTransformer的默认实现只是在传递的对象上调用toString它创建如上所示的输出。 由于我们要返回JSON因此我们必须创建一个ResponseTransformer将传递的对象转换为JSON。 为此我们使用带有两个静态方法的小型JsonUtil类 public class JsonUtil {public static String toJson(Object object) {return new Gson().toJson(object);}public static ResponseTransformer json() {return JsonUtil::toJson;}
} toJson是使用GSON将对象转换为JSON的通用方法。 第二种方法利用Java 8方法引用来返回ResponseTransformer实例。 ResponseTransformer还是一个功能接口因此可以通过提供适当的方法实现toJson来满足它。 因此每当调用json时我们都会获得一个新的ResponseTransformer它利用了我们的toJson方法。 在我们的UserController中我们可以将ResponseTransformer作为第三个参数传递给Spark的get方法 import static com.mscharhag.sparkdemo.JsonUtil.*;public class UserController {public UserController(final UserService userService) {get(/users, (req, res) - userService.getAllUsers(), json());...}
} 再次注意第一行中JsonUtil。*的静态导入。 这使我们可以选择仅通过调用json来创建新的ResponseTransformer。 现在我们的响应如下所示 [{id: 1866d959-4a52-4409-afc8-4f09896f38b2,name: john,email: johnfoobar.com
},{id: 90d965ad-5bdf-455d-9808-c38b72a5181a,name: anna,email: annafoobar.com
}] 我们还有一个小问题。 返回的响应带有错误的Content-Type 。 为了解决这个问题我们可以注册一个设置JSON Content-Type的Filter after((req, res) - {res.type(application/json);
}); 过滤器还是一个功能接口因此可以通过一个简短的Lambda表达式实现。 在我们的Route处理完请求后过滤器会将每个响应的Content-Type更改为application / json。 我们还可以使用before代替after来注册过滤器。 然后在路由处理请求之前将调用过滤器。 GET / users请求现在应该可以工作了 返回特定用户 要返回特定用户我们只需在UserController中创建一条新路由 get(/users/:id, (req, res) - {String id req.params(:id);User user userService.getUser(id);if (user ! null) {return user;}res.status(400);return new ResponseError(No user with id %s found, id);
}, json()); 使用req.params“id”我们可以从URL获取id路径参数。 我们将此参数传递给我们的服务以获取相应的用户对象。 如果未找到具有传递ID的用户则假定服务返回null。 在这种情况下我们将HTTP状态代码更改为400错误请求并返回一个错误对象。 ResponseError是一个小的帮助程序类我们用于将错误消息和异常转换为JSON。 看起来像这样 public class ResponseError {private String message;public ResponseError(String message, String... args) {this.message String.format(message, args);}public ResponseError(Exception e) {this.message e.getMessage();}public String getMessage() {return this.message;}
} 现在我们可以使用以下请求查询单个用户 GET / users / 5f45a4ff-35a7-47e8-b731-4339c84962be 如果存在具有此ID的用户我们将收到如下所示的响应 {id: 5f45a4ff-35a7-47e8-b731-4339c84962be,name: john,email: johnfoobar.com
} 如果我们使用无效的用户ID将创建ResponseError对象并将其转换为JSON。 在这种情况下响应如下所示 {message: No user with id foo found
}创建和更新用户 创建和更新用户非常容易。 就像返回所有用户的列表一样这是通过单个服务调用完成的 post(/users, (req, res) - userService.createUser(req.queryParams(name),req.queryParams(email)
), json());put(/users/:id, (req, res) - userService.updateUser(req.params(:id),req.queryParams(name),req.queryParams(email)
), json()); 要为HTTP POST或PUT请求注册路由我们只需使用Spark的静态post和put方法。 在Route内部我们可以使用req.queryParams访问HTTP POST参数。 为了简单起见并显示另一个Spark功能我们不在路由内进行任何验证。 相反我们假定如果传入无效值则服务将引发IllegalArgumentException。 Spark为我们提供了注册ExceptionHandlers的选项。 如果在处理路由时引发Exception则将调用ExceptionHandler。 ExceptionHandler是我们可以使用Java 8 Lambda表达式实现的另一个单一方法接口 exception(IllegalArgumentException.class, (e, req, res) - {res.status(400);res.body(toJson(new ResponseError(e)));
}); 在这里我们创建一个ExceptionHandler如果抛出IllegalArgumentException则调用它。 捕获的Exception对象作为第一个参数传递。 我们将响应代码设置为400并在响应正文中添加一条错误消息。 如果当email参数为空时服务抛出IllegalArgumentException我们可能会收到如下响应 {message: Parameter email cannot be empty
} 控制器的完整资源可以在这里找到。 测试中 由于Spark的简单性质因此为示例应用程序编写集成测试非常容易。 让我们从基本的JUnit测试设置开始 public class UserControllerIntegrationTest {BeforeClasspublic static void beforeClass() {Main.main(null);}AfterClasspublic static void afterClass() {Spark.stop();}...
} 在beforeClass中我们通过简单地运行main方法来启动应用程序。 所有测试完成后我们调用Spark.stop。 这将停止运行我们的应用程序的嵌入式服务器。 之后我们可以在测试方法中发送HTTP请求并验证我们的应用程序返回了正确的响应。 一个发送创建新用户请求的简单测试如下所示 Test
public void aNewUserShouldBeCreated() {TestResponse res request(POST, /users?namejohnemailjohnfoobar.com);MapString, String json res.json();assertEquals(200, res.status);assertEquals(john, json.get(name));assertEquals(johnfoobar.com, json.get(email));assertNotNull(json.get(id));
} request和TestResponse是两个小型的自制测试实用程序。 request将HTTP请求发送到传递的URL并返回TestResponse实例。 TestResponse只是一些HTTP响应数据的小包装。 request和TestResponse的源包含在GitHub上的完整测试类中 。 结论 与其他Web框架相比Spark仅提供了少量功能。 但是它是如此简单您可以在几分钟之内构建小型Web应用程序即使您以前从未使用过Spark。 如果您想研究Spark则应该清楚地使用Java 8它减少了您必须编写的代码量。 您可以在GitHub上找到示例项目的完整源代码。 翻译自: https://www.javacodegeeks.com/2014/06/building-a-simple-restful-api-with-spark.html