Dropwizard简单入门
Dropwizard:一个简洁的RESTful Web框架
Dropwizard跨越了开发库与框架的界限,旨在为Web应用所需的功能提供高性能、可靠的实现。Dropwizard将这些功能抽象为可重用的开发库,因此应用程序可以保持精简与专注,从而大大减少产品面世的时间以及维护负担。
Jetty HTTP库
Web应用都离不开HTTP,Dropwizard使用Jetty HTTP库为项目嵌入HTTP服务器。与复杂的应用服务器不同,Dropwizard项目通过main方法加快HTTP服务器处理。在生产环境独立进程中运行Java应用程序会减少很多麻烦(没有PermGen问题,没有应用服务器配置和维护,没有神秘的部署工具、没有类加载器问题、没有隐藏的应用程序日期、没有多个应用程序负载的垃圾回收器调优)。不仅如此,你还可以使用现成的Unix进程管理工具。
Jersey REST库
我们发现,要构建RESTful Web应用程序,从性能和功能角度考虑Jersey(JAX-RS参考实现)是最佳选择。你可以编写整洁、易于测试的类,将HTTP请求映射到简单的Java对象。Jersey REST库支持流输出、URI参数矩阵、条件GET请求等功能。
Jackson JSON库
如果说JSON是Web领域的通用数据格式,那么Jackson就是JVM平台JSON处理的王者。除了处理速度飞快,Jackson还支持复杂的对象映射器,可以直接导出领域模型。
Metrics度量库
Metrics库更加全面,它提供了无论伦比的视角,可以更好地了解代码在生产环境下的行为。
其它开发库
除了Jetty、Jersey 和 Jackson,Dropwizard还包含了很多其它非常有帮助的开发库:
- Guava:支持不可变数据结构,提供日益丰富的Java工具类加速开发。
- Logback 和 slf4j 可以提供高效灵活的日志功能。
- Hibernate Validator(
JSR-349
_ 参考实现)提供了简洁、声明式的用户输入验证框架,生成非常有用支持i18n的错误信息。 - Apache HttpClient 和 Jersey 客户端开发库提供了与其它Web服务的底层和高层交互。
- JDBI:为Java关系数据库提供了最直接的方式交互。
- Liquibase:在开发和发布周期中,为数据库schema提供全程检查。支持高层数据库重构,取代了一次性DDL脚本。
- Freemarker 和 Mustache为面向用的应用程序提供了简单的模板系统。
- Joda Time:完整强大的时间日期处理开发库。
简单示例
推荐使用Maven构建新的Dropwizard应用,首先,在POM中加入 dropwizard.version 属性及最新版本:
<properties>
<dropwizard.version>INSERT VERSION HERE</dropwizard.version>
</properties>
把 dropwizard-core 加为依赖项:
<dependencies>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
</dependencies>
1. 新建Configuration类
每个DW应用都有他自己的子类:Configuration,这个类指定环境中特定的参数。这些参数在YAML类型的配置文件中被指定,其被反序列化为应用程序配置类的实例并验证。(这句话的意思就是这个配置文件中指定的参数,会被映射到我们项目的一个类)我们将要构建的是一个helloworld高性能服务。我们的一个要求就是我们需要能够在不同的环境中让它说hello,在开始之前我们需要指定至少两个内容:一个说hello的模板 还有一个默认的名字以防用户忘记指定。
package com.example.helloworld; import com.example.helloworld.core.Template;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
import io.dropwizard.Configuration;
import io.dropwizard.db.DataSourceFactory;
import org.hibernate.validator.constraints.NotEmpty; import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.Map; public class HelloWorldConfiguration extends Configuration {
@NotEmpty
private String template; @NotEmpty
private String defaultName = "Stranger"; @Valid
@NotNull
private DataSourceFactory database = new DataSourceFactory(); @NotNull
private Map<String, Map<String, String>> viewRendererConfiguration = Collections.emptyMap(); @JsonProperty
public String getTemplate() {
return template;
} @JsonProperty
public void setTemplate(String template) {
this.template = template;
} @JsonProperty
public String getDefaultName() {
return defaultName;
} @JsonProperty
public void setDefaultName(String defaultName) {
this.defaultName = defaultName;
} public Template buildTemplate() {
return new Template(template, defaultName);
} @JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
return database;
} @JsonProperty("database")
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
this.database = dataSourceFactory;
} @JsonProperty("viewRendererConfiguration")
public Map<String, Map<String, String>> getViewRendererConfiguration() {
return viewRendererConfiguration;
} @JsonProperty("viewRendererConfiguration")
public void setViewRendererConfiguration(Map<String, Map<String, String>> viewRendererConfiguration) {
final ImmutableMap.Builder<String, Map<String, String>> builder = ImmutableMap.builder();
for (Map.Entry<String, Map<String, String>> entry : viewRendererConfiguration.entrySet()) {
builder.put(entry.getKey(), ImmutableMap.copyOf(entry.getValue()));
}
this.viewRendererConfiguration = builder.build();
}
}
template: Hello, %s!
defaultName: Stranger
2. 新建Application类
package com.example.helloworld; import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import com.example.helloworld.resources.HelloWorldResource;
import com.example.helloworld.health.TemplateHealthCheck; public class HelloWorldApplication extends Application<HelloWorldConfiguration> {
public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
} @Override
public String getName() {
return "hello-world";
} @Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
// nothing to do yet
} @Override
public void run(HelloWorldConfiguration configuration,
Environment environment) {
// nothing to do yet
} }
正如我们所看到的,HelloWorldApplication使用应用程序的configuration进行参数化,(因为用了我们的HelloWorldConfiuration,而它是Configuration的子类),initialize方法用于配置应用在正式启动之前所需:包,配置源等,同时我们需要加入一个main方法,这是我们应用的入口,到目前为止,我们并没有实现任何的功能,所以我们的run方法有点无趣,让我们开始丰富它。
3. 新建Representation类
在我们开始继续我们的程序之前,我们需要停下来思考一下我们程序的API。幸运的是,我们的应用需要符合行业标准RFC 1149,它指定了helloworld saying的如下json表达形式:
{
"id": ,
"content": "Hi!"
}
id字段是唯一标识,content是文字内容。下面是representation实现,一个简单的POJO类:
package com.example.helloworld.api; import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.Length; public class Saying {
private long id; @Length(max = )
private String content; public Saying() {
// Jackson deserialization
} public Saying(long id, String content) {
this.id = id;
this.content = content;
} @JsonProperty
public long getId() {
return id;
} @JsonProperty
public String getContent() {
return content;
}
}
这是一个非常简单的POJO,但是有些需要注意的地方。首先,他是不可更改的。这使得saying在多线程环境和单线程环境非常容易被推理。其次,它使用java的JavaBean来保存id和content属性。这允许jackson把他序列化为我们需要的JSON。jackson对象的映射代码将会使用getId()返回的对象来填充JSON对象的id字段,content同理。最后,bean利用验证来确保内容不大于3。
4. 新建Resource类
Jersey资源是DW应用程序的主要内容,每个资源类都与URL相关联(这个很重要,后面有说),对于我们的应用程序来说,我们需要一个resources来通过url:/helloworld来返回新的Saying实例对象。
package com.example.helloworld.resources; import com.example.helloworld.api.Saying;
import com.google.common.base.Optional;
import com.codahale.metrics.annotation.Timed; import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.concurrent.atomic.AtomicLong; @Path("/hello-world")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
private final String template;
private final String defaultName;
private final AtomicLong counter; public HelloWorldResource(String template, String defaultName) {
this.template = template;
this.defaultName = defaultName;
this.counter = new AtomicLong();
} @GET
@Timed
public Saying sayHello(@QueryParam("name") Optional<String> name) {
final String value = String.format(template, name.or(defaultName));
return new Saying(counter.incrementAndGet(), value);
}
}
HelloWorldResource有两个声明:@Path和@Produces。@Path("/hello-world")告诉Jersey这个resource可以通过 "/hello-world"URL被访问。
@Produces(MediaType.APPLICATION_JSON)让Jersey的内容协商代码知道这个资源产生的是application/json.
HelloWorldResource构造器接收两个参数,创建saying的template和当用户没有指明名字时的默认名称,AtomicLong为我们提供一种线程安全,简易的方式去生成(ish)ID。sayHello方法是这个类的肉,也是一个非常简单的方法。@QueryParam("name")告诉Jersey把在查询参数中的name映射到方法中的name中。如果一个客户发送请求到:/hello-world?name=Dougie,sayHello 方法将会伴随Optional.of("Dougie")被调用。如果查询参数中没有name,sayHello将会伴随着Optional.absent()被调用。在sayHello方法里面,我们增加计数器的值,使用String.format来格式化模板,返回一个新的Saying实例。因为sayHello被@Timed注释,DW将会自动调用他的持续时间和速率记录为度量定时器。一旦sayHello返回,Jersey将会采用Saying的实例,并寻找一个提供程序类来将Saying实例写为:application/json。
5. 注册Resource
在这些正式工作之前,我们需要到HelloWorldApplication中,并将新的resouce加入其中,在run方法中我们可以读取到HelloWorldConfiguration的template和defaultName实例,创建一个新的HelloWorldResource实例,并将其加入到新的Jersey环境中。我们HelloWorldApplication中新的run方法如下:
@Override
public void run(HelloWorldConfiguration configuration,
Environment environment) {
final HelloWorldResource resource = new HelloWorldResource(
configuration.getTemplate(),
configuration.getDefaultName()
);
environment.jersey().register(resource);
}
当我们的应用启动的时候,我们使用配置文件中的参数创建一个新的资源类实例,并传递给environment.
转自:http://blog.csdn.net/qq_23660243/article/details/54406075 以及 http://hao.jobbole.com/dropwizard/
Dropwizard简单入门的更多相关文章
- 用IntelliJ IDEA创建Gradle项目简单入门
Gradle和Maven一样,是Java用得最多的构建工具之一,在Maven之前,解决jar包引用的问题真是令人抓狂,有了Maven后日子就好过起来了,而现在又有了Gradle,Maven有的功能它都 ...
- [原创]MYSQL的简单入门
MYSQL简单入门: 查询库名称:show databases; information_schema mysql test 2:创建库 create database 库名 DEFAULT CHAR ...
- Okio 1.9简单入门
Okio 1.9简单入门 Okio库是由square公司开发的,补充了java.io和java.nio的不足,更加方便,快速的访问.存储和处理你的数据.而OkHttp的底层也使用该库作为支持. 该库极 ...
- emacs最简单入门,只要10分钟
macs最简单入门,只要10分钟 windwiny @2013 无聊的时候又看到鼓吹emacs的文章,以前也有几次想尝试,结果都是玩不到10分钟就退出删除了. 这次硬着头皮,打开几篇文章都看完 ...
- 【java开发系列】—— spring简单入门示例
1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控制反转 ...
- Docker 简单入门
Docker 简单入门 http://blog.csdn.net/samxx8/article/details/38946737
- Springmvc整合tiles框架简单入门示例(maven)
Springmvc整合tiles框架简单入门示例(maven) 本教程基于Springmvc,spring mvc和maven怎么弄就不具体说了,这边就只简单说tiles框架的整合. 先贴上源码(免积 ...
- git简单入门
git简单入门 标签(空格分隔): git git是作为程序员必备的技能.在这里就不去介绍版本控制和git产生的历史了. 首先看看常用的git命令: git init git add git comm ...
- 程序员,一起玩转GitHub版本控制,超简单入门教程 干货2
本GitHub教程旨在能够帮助大家快速入门学习使用GitHub,进行版本控制.帮助大家摆脱命令行工具,简单快速的使用GitHub. 做全栈攻城狮-写代码也要读书,爱全栈,更爱生活. 更多原创教程请关注 ...
随机推荐
- C# cs文件表头模版
设置位置:C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplatesCache\CSharp\Web\2 ...
- Aria2 Axel wget curl 四个下载命令
经常由于不同需求使用下载管理器从互联网下载文件,它给我和其他人提供了很多帮助.我们都想要一个超级快速的下载管理器来完成下载尽可能多的任务,以便我们可以节省时间来进一步地工作.有很多可以加速下载的下载管 ...
- subversion commit 报错A checksum mismatch occurred
期望: 2bea3643d1ea67bfa032af9dd649b1d5 实际: 5693bd753ac9ab1ddfcdd9a644b6bd02 在eclipse工程中出现此问题,则 1.com ...
- eclipse的Maven项目pom.xml错误信息提示missingxxxjar解决方案
今天在学习的时候需要用到maven工程,当时找完所依赖的包的三要素就开始下载了,写完pom.xml需要一段时间下载这些jar包,就躺在一边等了.可能是笔记本有节能功能这个原因导致我醒来时断网发现满屏m ...
- 关于Struts2的action的execute方法
这个方法必须要有一个String类型的返回值,所以如果写很多if else的话,记得要在最后加一个else,就是无论如何就会放回一个字符串,否则编译会报错,在execute方法名字下面有红线.
- 下载最新android adt的方法
作为一名android开发人员,需要经常更新最新版本的 android adt,但是直接到官网去找很难找到下载的链接,通过下面现成的链接,你就能够直接下载最新的android adt了, 网址是:de ...
- hdu 5044 树区间操作最后输出/ lca+dfs
题意:一棵树,俩种操作:1 有路径上的全部点加vi,2全部边加vi. 先离线求出全部询问的lca,再遍历询问一次,点+vi,lca-2*vi ,最后dfs从叶子扫上来一次,最后再祖先点补上就可以.用了 ...
- bootstrap table使用指南
Bootstrap table是国人开发的一款基于 Bootstrap 的 jQuery 表格插件,通过简单的设置,就可以拥有强大的单选.多选.排序.分页,以及编辑.导出.过滤(扩展)等等的功能. 目 ...
- Servlet+Ajax实现搜索智能提示
一般在百度搜索框输入关键词时,会弹出一些相关信息提示,方便点选: 页面(search.jsp): <input type="text" name="keyWords ...
- python小工具
http://blog.csdn.net/pipisorry/article/details/46754515 python复制.删除文件代码.python代码出错重新启动 python遍历和删除指定 ...