原文链接:http://www.dropwizard.io/1.2.0/docs/getting-started.html
Getting Start
Getting Startedwill guide you through the process of creating a simple Dropwizard Project: Hello World. Along the way, we’ll explain the various underlying libraries and their roles, important concepts in Dropwizard, and suggest some organizational techniques to help you as your project grows. (Or you can just skip to the fun part.)
入门指南将会引导你完成创建一个简单的Dropwizard项目:Hello Word。整个过程中,我们会介绍其引用的底层类库和作用,Zropwizard框架的重要概念,在项目实现过程中介绍一些组织性的技术。(你也可以跳过Getting Start步骤)
Overview
Dropwizard straddles the line between being a library and a framework. Its goal is to provide performant, reliable implementations of everything a production-ready web application needs. Because this functionality is extracted into a reusable library, your application remains lean and focused, reducing both time-to-market and maintenance burdens.
Dropwizard跨越了类库和框架之间的界限。其目的是为Web应用程序提供一种可靠的实现方案。由于此功能被提取到可重用的类库中,因此你的应用程序仍然精简和集中,从而缩短上市时间和维护负担。
Jetty for HTTP
Because you can’t be a web application without HTTP, Dropwizard uses the Jetty HTTP library to embed an incredibly tuned HTTP server directly into your project. Instead of handing your application off to a complicated application server, Dropwizard projects have a main method which spins up an HTTP server. Running your application as a simple process eliminates a number of unsavory aspects of Java in production (no PermGen issues, no application server configuration and maintenance, no arcane deployment tools, no class loader troubles, no hidden application logs, no trying to tune a single garbage collector to work with multiple application workloads) and allows you to use all of the existing Unix process management tools instead.
Web应用程序离不开HTTP,Zropwizard框架直接将Jetty Http插件(Http服务器)嵌入到你的Web应用程序中。你不需要将项目交给一个复杂的Web服务器,Zropwizard项目提供一个main方法快速启动一个HTTP服务器(Jetty)。通过一个简单的过程运行你的Java应用程序而排除一系列复杂的事情。(没有PermGen问题,没有应用服务器配置和维护,没有复杂的部署工具,没有类加载器的困扰,没有隐藏的应用日志,不用调试垃圾回收器来解决多应用负载),允许使用所有现成的Unix进程管理工具。
Jersey for REST
For building RESTful web applications, we’ve found nothing beats Jersey(the JAX-RS reference implementation) in terms of features or performance. It allows you to write clean, testable classes which gracefully map HTTP requests to simple Java objects. It supports streaming output, matrix URI parameters, conditional GET requests, and much, much more.
构建RESTful风格的Web应用程序,我们没有发现任何能够打败Jersey的框架。它允许您编写简洁,可测试的类,将HTTP请求正确地映射到简单的Java对象。它支持流输出,解析URI参数,条件GET请求等等。
Jackson for JSON
In terms of data formats, JSON has become the web’s lingua franca, and Jackson is the king of JSON on the JVM. In addition to being lightning fast, it has a sophisticated object mapper, allowing you to export your domain models directly.
目前的数据格式,JSON已经是一种通用的数据结构,Jackson是JVM解析JSON数据的霸主。除了速度快,Jackson还有一套对象映射器,允许你直接导出你的数据模型。
Metrics for metrics
The Metrics library rounds things out, providing you with unparalleled insight into your code’s behavior in your production environment.
Metrics插件让你代码执行透明化,对你生产环境的代码提供无与伦比的观察能力。
And Friends
In addition to Jetty,Jersey, andJackson, Dropwizard also includes a number of libraries to help you ship more quickly and with fewer regrets.
除了Jetty、Jersey、Jackson之外,Dropwizard还包括许多其他类库帮助你的应用开发,减少烦恼。
Guava, which, in addition to highly optimized immutable data structures, provides a growing number of classes to speed up development in Java.
除了高度优化的不可变数据结构之外,Guava还提供了越来越多的类库来加速Java开发。
Logback and slf4j for performant and flexible logging.
Logback和slf4j用于执行和灵活的日志记录。
Hibernate Validator, the JSR 349 reference implementation, provides an easy, declarative framework for validating user input and generating helpful and i18n-friendly error messages.
Hibernate Validator,JSR 349参考实现,为验证用户输入提供了一个简单的声明框架,并生成有用的和易于使用的I18n友好的错误消息。
The Apache HttpClient and Jersey client libraries allow for both low- and high-level interaction with other web services.
Apache HttpClient和Jersey客户端库允许与其他Web服务进行低级和高级别的交互。
JDBI is the most straightforward way to use a relational database with Java.
JDBI是使用Java的关系数据库最直接的方法。
Liquibase is a great way to keep your database schema in check throughout your development and release cycles, applying high-level database refactorings instead of one-off DDL scripts.
在开发和发布周期中,Liquibase是保持数据库模式的重要方法,应用高级数据库重构而不是一次性DDL脚本。
Freemarker and Mustache are simple templating systems for more user-facing applications.
Freemarker和Mustache是简单的系统模板,适用于面向更多用户的应用程序。
Joda Time is a very complete, sane library for handling dates and times.
Joda Time是一个非常完整明智的类库 ,用于处理日期和时间。
Now that you’ve gotten the lay of the land, let’s dig in!
现在你已经得到了这片土地,让我们开始吧!
Setting Up Using Maven
We recommend you use Maven for new Dropwizard applications. If you’re a big Ant/Ivy,Buildr,Gradle,SBT,Leiningen, or Gant fan, that’s cool, but we use Maven, and we’ll be using Maven as we go through this example application. If you have any questions about how Maven works,Maven: The Complete Reference should have what you’re looking for.
我们推荐你使用Maven创建一个新的Dropwizard应用。如果你是一个Ant/lvy、Buildr、Gradle、SBT、Leiningen或者Grnt的忠实粉丝,这是非常酷的事情,但是我们事例这里使用Maven。如果你有任何关于Maven的疑问,你可以查询Maven官方文档。
You have three alternatives from here:
你有以下三个选择:
1、Create a project using dropwizard-archetype
使用dropwizard-archetype(原型)创建项目
mvn archetype:generate -DarchetypeGroupId=io.dropwizard.archetypes -DarchetypeArtifactId=java-simple -DarchetypeVersion=[REPALCE WITH A VALID DROPWIZARD VERSION]
2、Look at the dropwizard-example
3、Follow the tutorial below to see how you can include it in your existing project
在你的项目中遵循以下原则
Tutorial
First, add adropwizard.versionproperty to your POM with the current version of Dropwizard (which is 1.2.0):
首先,为你的项目POM中添加一个dropwizard.version属性,使用当前版本的Dropwizard(即1.2.0)
<properties>
<dropwizard.version>INSERT VERSION HERE</dropwizard.version>
</properties>
Add the dropwizard-core library as a dependency:
添加dropwizard-core类库:
<dependencies>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
</dependencies>
Alright, that’s enough XML. We’ve got a Maven project set up now, and it’s time to start writing real code.
好了,足够的XML。我们已经拥有了一个Maven项目,可以开始写代码了。
Creating A Configuration Class
Each Dropwizard application has its own subclass of the Configuration class which specifies environment-specific parameters. These parameters are specified in a YAML configuration file which is deserialized to an instance of your application’s configuration class and validated.
每个Dropwizard应用都有自己指定环境参数的配置类。在一个YAML配置文件中指定参数,yaml文件会被反序列化为应用配置类的实例并进行验证。
The application we’ll be building is a high-performance Hello World service, and one of our requirements is that we need to be able to vary how it says hello from environment to environment. We’ll need to specify at least two things to begin with: a template for saying hello and a default name to use in case the user doesn’t specify their name.
我们将要构建的应用是一个高性能的Hello World服务,要求我们需要改变从环境到环境的去调用hello服务。我们至少要说明两件事情:一个是hello服务的模版和一个特定的服务名称。
Here’s what our configuration class will look like, full example conf here:
以下是我们配置类的例子:
packagecom.example.helloworld;
import io.dropwizard.Configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
public class HelloWorldConfiguration extends Configuration {
@NotEmpty
private String template;
@NotEmpty
private String defaultName="Stranger";
@JsonProperty
public String getTemplate() {
return template;
}
@JsonProperty
public void setTemplate(String template) {
this.template=template;
}
@JsonProperty
public String getDefaultName() { returndefaultName;
}
@JsonProperty
public void setDefaultName(Stringname) {
this.defaultName=name;
}
}
There’s a lot going on here, so let’s unpack a bit of it.
接下来有很多事情要做,让我们开始去尝试它。
When this class is deserialized from the YAML file, it will pull two root-level fields from the YAML object:template, the template for our Hello World saying, and defaultName, the default name to use. Both template and defaultName are annotated with @NotEmpty, so if the YAML configuration file has blank values for either or is missing template entirely an informative exception will be thrown, and your application won’t start.
这个配置类从YAML配置文件反序列化,将从YAML文件中匹配根节点字段:template,Hello World服务模板以及默认名称。template和defaultName都使用了@NotEmpty注解,所以如果你的YAML配置文件中没有对应的值或者没有模板信息,你的应用将会出错并且不能运行。
Both the getters and setters for template and defaultName are annotated with @JsonProperty, which allows Jackson to both deserialize the properties from a YAML file but also to serialize it.
template和defaultName属性的setter和getter方法都使用了@JsonProperty注解,允许Jackson反序列化属性值从YAML配置文件中,也可以序列化。
Note
The mapping from YAML to your application’s Configuration instance is done by Jackson. This means your Configuration class can use all of Jackson’s object-mapping annotations. The validation of @NotEmpty is handled by Hibernate Validator, which has a wide range of built-in constraints for you to use.
注:
YAML配置文件信息通过Jackson映射到应用配置实例上,这意味着你的配置类可以使用所有的Jackson的映射注解。@NotEmpty注解的由Hibernate Validator验证,具有广泛的内置约束。
Our YAML file will then look like the below, full example yml here:
我们示例的YAML文件如下,完整的yaml文件:
template:Hello, %s!
defaultName:Stranger
Dropwizard has many more configuration parameters than that, but they all have sane defaults so you can keep your configuration files small and focused.
Dropwizard有更多的配置参数,但是都有合适的默认值,因此你的配置文件可以保持小而简洁。
So save that YAML file in the directory you plan to run the fat jar from (see below) as hello-world.yml, because we’ll be getting up and running pretty soon, and we’ll need it. Next up, we’re creating our application class!
因此可以把你的YAML配置文件hello-world.yml保存在你运行目录下(参考下文),我们运行项目需要使用配置文件。接下来,我们开始创建一个应用主要类文件。
Creating An Application Class
Combined with your project’s Configuration subclass, its Application subclass forms the core of your Dropwizard application. The Application class pulls together the various bundles and commands which provide basic functionality. (More on that later.) For now, though, our HelloWorld Application looks like this:
结合项目配置类,这个应用程序主类是Dropwizard应用程序的核心,Application主类将各种绑定和命令结合在一起提供基本的功能。(稍后)现在,我们HelloWorld服务的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 {
public static void main(String [] args) throws Exception {
new HelloWorldApplication().run(args);
}
@Override
public String getName() {
return "hello-world";
}
@Override
public void initialize(Bootstrap bootstrap) {
// nothing to do yet
}
@Override
public void run(HelloWorldConfiguration configuration,Environment environment) {
// nothing to do yet
}
}
As you can see,HelloWorld Application is parameterized with the application’s configuration type,HelloWorld Configuration. An initialize method is used to configure aspects of the application required before the application is run, like bundles, configuration source providers, etc. Also, we’ve added a static main method, which will be our application’s entry point. Right now, we don’t have any functionality implemented, so our run method is a little boring. Let’s fix that!
正如你多看到的,HelloWorld服务配置参数使用Application配置类来完成参数参数化。在应用启动之前完成应用所需的参数初始化工作,比如绑定,配置源等。此外,我们提供一个静态main方法,将是我们应用的入口。现在我们没有任何功能实现,我们的应用显得有点无聊。让我们去完善我们的应用!
Creating A Representation Class
Before we can get into the nuts-and-bolts of our Hello World application, we need to stop and think about our API. Luckily, our application needs to conform to an industry standard,RFC 1149, which specifies the following JSON representation of a Hello World saying:
在我们深入了解Hello World服务之前,我们需要停下来去思考我们的API。幸运的是,我们的应用需要遵从行业规范RFC 1149,规范规定了Hello World服务的JSON数据形式:
{
"id":1,
"content":"Hi!"
}
The id field is a unique identifier for the saying, and contentis the textual representation of the saying. (Thankfully, this is a fairly straight-forward industry standard.)
id字段是术语独一无二的标识符,content是术语的表示形式。(这是一个行业标准规范)
To model this representation, we’ll create a representation class:
为了构建这样的数据形式,我们将创建一个数据模类:
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=3)
private String content;
public Saying()
{
// Jackson deserialization
}
public Saying(long id, String content) {
this.id=id;
this.content=content;
}
@JsonProperty
public long getId() {
returnid;
}
@JsonProperty
public String getContent() {
return content;
}
}
This is a pretty simple POJO, but there are a few things worth noting here.
这是一个非常简单的POJO类,但是也有很多值得注意的地方。
First, it’s immutable. This makes Saying instances very easy to reason about in multi-threaded environments as well as single-threaded environments. Second, it uses the JavaBeans standard for the id and content properties. This allows Jackson to serialize it to the JSON we need. The Jackson object mapping code will populate the id field of the JSON object with the return value of #getId(), like wise with content and #getContent(). Lastly, the bean leverages validation to ensure the content size is no greater than 3.
首先,Saying实例是不可变的。这使得Saying实例在多线程和单线程环境都容易理解。其次,使用了JavaBeans标准的属性id和content,允许Jackson序列化实例成我们需要的JSON数据。Jackson映射对象将通过getID()方法返回值填充id字段,同样的方式使用getContent()方法返回值填充content字段。最后bean通过验证保证content内容长度不大于3。
Note
The JSON serialization here is done by Jackson, which supports far more than simple JavaBean objects like this one. In addition to the sophisticated set of annotations, you can even write your custom serializers and deserializers.
注:
JSON序列化通过Jackson实现,能够支持更多这样的简单JavaBean对象。除了这些注解外,你还能自定义序列化和反序列化器。
Now that we’ve got our representation class, it makes sense to start in on the resource it represents.
现在我们有实体类了,它所代表的资源数据是有意义的。
Creating A Resource Class
Jersey resources are the meat-and-potatoes of a Dropwizard application. Each resource class is associated with a URI template. For our application, we need a resource which returns new Saying instances from the URI/hello-world, so our resource class looks like this:
Jersey资源是Dropwizard应用程序的主要核心。每个资源类都与一个URI模版关联。对我们应用,我们需要一个资源类去返回一个Saying对象从URI/hello-world,因此我们的资源类如下:
package com.example.helloworld.resources;
import com.example.helloworld.api.Saying;
import com.codahale.metrics.annotation.Timed;
import javax.ws.rs.GET;importjavax.ws.rs.Path;
import javax.ws.rs.Produces;importjavax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Optional;
@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 = newAtomicLong();
}
@GET
@Timed
public Saying sayHello(@QueryParam("name") Optional<name>) {
final Stringvalue = String.format(template,name.orElse(defaultName));
return new Saying(counter.incrementAndGet(),value);
}
}
Finally, we’re in the thick of it! Let’s start from the top and work our way down.
最后,我们开始从浅到深地了解他。
HelloWorldResource has two annotations:@Pathand@Produces.@Path("/hello-world") tells Jersey that this resource is accessible at the URI/hello-world, and @Produces(MediaType.APPLICATION_JSON) lets Jersey’s content negotiation code know that this resource produces representations which areapplication/json.
HelloWorldResource有两个注解:@Path和@Produces。@Path("/hello-world")告诉Jersey这个resource能够通过URI/hello-world路径访问到,@Produces(MediaType.APPLICATION_JSON)让Jersey’s知道这个资源处理数据表示方式是json格式。
HelloWorldResource takes two parameters for construction: the template it uses to produce the saying and the defaultName used when the user declines to tell us their name. An AtomicLong provides us with a cheap, thread-safe way of generating unique(ish) IDs.
HelloWorldResource两个参数的构造器:template参数用来处理saying的内容,defaultName用来返回默认值当用户拒绝告诉我们name参数的时候。AtomicLong提供一个简洁线程安全全局唯一的ID生产器。
Warning
Resource classes are used by multiple threads concurrently. In general, we recommend that resources be stateless/immutable, but it’s important to keep the context in mind.
警告:
Resource类是多线程并发使用。一般情况下,我们推荐resources为不可变模式,这是非常重要的。
#sayHello(Optional<name>) is the meat of this class, and it’s a fairly simple method. The @QueryParam("name") annotation tells Jersey to map the name parameter from the query string to the name parameter in the method. If the client sends a request to /hello-world?name=Dougie,sayHello will be called with Optional.of("Dougie"); if there is no name parameter in the query string,sayHello will be called with Optional.absent(). (Support for Guava’s Optional is a little extra sauce that Dropwizard adds to Jersey’s existing functionality.)
#sayHello(Optional)是这个resource类的主要核心,是一个简单的方法。@QueryParam("name")注解告诉Jersey映射name参数从这个方法的查询字符串中的name参数。 如果用户发送请求/hello-world?name=Dougie,sayHello将会被调用Optional.of("Dougie");如果请求中没有name参数,sayHello将会被调用Optional.absent()。(支持Guava’s Optional类库增强了Jersey已有的功能)
Note
If the client sends a request to /hello-world?name=,sayHello will be called with Optional.of(""). This may seem odd at first, but this follows the standards (an application may have different behavior depending on if a parameter is empty vs nonexistent). You can swap Optional parameter with NonEmpty String Param if you want /hello-world?name= to return “Hello, Stranger!” For more information on resource parameters see the documentation
注:
如果客户端发送请求/hello-world?name=,sayHello将被调用Optional.of("")。这看起来奇怪,但是符合标准(服务可能有不同的行为依据传入参数是否为空不存在)。如果你想/hello-world?name=返回“Hello, Stranger!”你可以使用非空字符参数替换 Optional<String>,更多的资源参数信息参考官方文档。
In side the sayHello method, we increment the counter, format the template using String.format(String,Object...), and return a new Saying instance.
在sayHello方法中,我们增加了计数器,使用String.format(String,Object...)格式化template,返回一个Saying实例。
Because sayHello is annotated with@Timed, Dropwizard automatically records the duration and rate of its invocations as a Metrics Timer.
因为sayHello带有@Timed注解,Dropwizard自动记录方法服务持续的时间和方法服务速率。
Once sayHello has returned, Jersey takes the Saying instance and looks for a provider class which can write Saying instances as application/json. Dropwizard has one such provider built in which allows for producing and consuming Java objects as JSON objects. The provider writes out the JSON and the client receives a 200OK response with a content type of application/json.
一旦sayHello有返回结果,Jersey就会采用Saying实例并寻找一个可以将Saying实例写为application / json的提供者类。Dropwizard内置了一个这样的提供者,它允许生成和使用Java对象作为JSON对象。提供者写出JSON对象,客户端接收到200的结果和application/json类型的数据内容。
Registering A Resource
Before that will actually work, though, we need to go back to HelloWorldApplication and add this new resource class. In its run method we can read the template and default name from the HelloWorldConfiguration instance, create a new HelloWorldResource instance, and then add it to the application’s Jersey environment:
在启动项目提供服务之前,我们需要回到HelloWorldApplication类中添加一个资源类。在run方法中我们读取template和default name属性从HelloWorldConfiguration实例,创建一个新的 HelloWorldResource实例并将其注册到Jersey环境中:
@Override
public void run(HelloWorldConfiguration configuration, Environment environment) { final HelloWorldResource resource = new HelloWorldResource( configuration.getTemplate(),
configuration.getDefaultName()
);
environment.jersey().register(resource);
}
When our application starts, we create a new instance of our resource class with the parameters from the configuration file and hand it off to the Environment, which acts like a registry of all the things your application can do.
当应用运行后,我们为resource类创建一个新的实例并注入configuration 文件实例的参数,像是一个可做事情的列表一样。
Note
A Dropwizard application can contain many resource classes, each corresponding to its own URI pattern. Just add another @Path-annotated resource class and call register with an instance of the new class.
注:
Dropwizard应用包含很多的resource类,每个resource类都有特定的uri模版。只需添加另一个@ Path注释的资源类,并使用新类的实例调用注册。
Before we go too far, we should add a health check for our application.
在此,我们需要为应用添加健康检查。
Creating A Health Check
Health checks give you a way of adding small tests to your application to allow you to verify that your application is functioning correctly in production. We strongly recommend that all of your applications have at least a minimal set of health checks.
健康检查提供一种向应用添加小型测试的方法以验证应用程序正常。我们强烈推荐每个应用都至少添加一个精简的健康检查。
Note
We recommend this so strongly, in fact, that Dropwizard will nag you should you neglect to add a health check to your project.
注:
我们建议如此强烈,事实上,Dropwizard将会频繁提示你应该为你的项目添加健康检查。
Since formatting strings is not likely to fail while an application is running (unlike, say, a database connection pool), we’ll have to get a little creative here. We’ll add a health check to make sure we can actually format the provided template:
由于格式化字符串在应用程序运行时不可能失败(不像数据库连接池),所以我们不得不有所创意。我们将增加一个健康检查确保我们能够格式化提供者模版:
package com.example.helloworld.health;
import com.codahale.metrics.health.HealthCheck;
public class TemplateHealthCheck extends HealthCheck {
private final String template;
public TemplateHealthCheck(String template) { this.template = template;
}
@Override
protected Result check() throws Exception {
final String saying = String.format(template, "TEST");
if (!saying.contains("TEST")) {
return Result.unhealthy("template doesn't include a name");
}
return Result.healthy();
}
}
Template HealthCheckchecks for two things: that the provided template is actually a well-formed format string, and that the template actually produces output with the given name.
健康检查做的两件事:一是提供者模版确定能够正确格式化字符,二是模版能够正确生产数据使用我们输入的参数。
If the string is not a well-formed format string (for example, someone accidentally putHello,%s%in the configuration file), thenString.format(String,Object...)will throw an IllegalFormatExceptionand the health check will implicitly fail. If the rendered saying doesn’t include the test string, the health check will explicitly fail by returning an unhealthyResult.
如果字符串不是一个格式正确的格式字符串(例如,有人不小心把配置文件中的%s%),那么String.format(String,Object ...)将抛出一个IllegalFormatException,应用绝对性失败。如果渲染的语句不包含测试字符串,健康状况检查将通过返回不健康的结果而明确失败。
Adding A Health Check
As with most things in Dropwizard, we create a new instance with the appropriate parameters and add it to the Environment:
与Dropwizard中的大多数事情一样,我们使用适当的参数创建一个新实例,并将其添加到环境中:
@Override
public void run(HelloWorldConfiguration configuration, Environment environment) { final HelloWorldResource resource = new HelloWorldResource( configuration.getTemplate(),
configuration.getDefaultName() );
final TemplateHealthCheck healthCheck = new TemplateHealthCheck(configuration.getTemplate()); environment.healthChecks().register("template", healthCheck); environment.jersey().register(resource);
}
Now we’re almost ready to go!
现在我们可以准备出发了!
Building Fat JARs
We recommend that you build your Dropwizard applications as “fat” JAR files — single.jar files which contain all of the. class files required to run your application. This allows you to build a single deployable artifact which you can promote from your staging environment to your QA environment to your production environment without worrying about differences in installed libraries. To start building our Hello World application as a fat JAR, we need to configure a Maven plugin calledmaven-shade. In thesection of yourpom.xmlfile, add this:
我们推荐你构建Dropwizard项目为一个简单的jar包文件。jar包中包含了你项目所有的class文件。这使可以构建一个可部署的jar文件,您可以从暂存环境将您的QA环境升级到生产环境,而无需担心已安装库的差异。要开始构建我们的Hello World应用程序jar包,我们需要配置Maven插件。 在你的pom.xml文件的部分中添加:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.helloworld.HelloWorldApplication</mainClass>
</transformers>
</configuration>
</execution>
</executions>
This configures Maven to do a couple of things during its package phase:
Maven做的事情如下:
Produce a pom.xml file which doesn’t include dependencies for the libraries whose contents are included in the fat JAR.
生成一个pom.xml文件,其内容包含在jar包中。
Exclude all digital signatures from signed JARs. If you don’t, then Java considers the signature invalid and won’t load or run your JAR file.
排除jar中所有的数字标签。如果不这么做,Java会认为无效不加载或者运行jar包。
Collate the various META-INF/services entries in the JARs instead of overwriting them. (Neither Dropwizard nor Jersey works without those.)
整理JAR中的各种 META-INF/services 条目而不是覆盖它们。 (没有这些Dropwizard和Jersey都不能工作)
Set com.example.helloworld.HelloWorldApplication as the JAR’s MainClass. This will allow you to run the JAR using java-jar.
将com.example.helloworld.HelloWorldApplication设置为Jar包的主要类。将允许你使用java-jar去运行这个jar包。
Warning
If your application has a dependency which must be signed (e.g., a JCA/JCE provider or other trusted library), you have to add an exclusion to the maven-shade-plugin configuration for that library and include that JAR in the classpath.
警告
如果您的应用程序具有必须签名的依赖项(例如,JCA / JCE提供程序或其他可信库),则必须为该库的maven-shade-plugin配置添加一个排除项,并将该JAR包含在classpath中。
Warning
Since Dropwizard is using the Java ServiceLoader functionality to register and load extensions, the minimizeJaroption of the maven-shade-plugin will lead to non-working application JARs.
警告
由于Dropwizard使用Java ServiceLoader功能来注册和加载扩展,maven-shade-plugin的minimizeJar选项将导致非工作的应用程序JAR。
Versioning Your JARs
Dropwizard can also use the project version if it’s embedded in the JAR’s manifest as the Implementation-Version. To embed this information using Maven, add the following to thesection of yourpom.xmlfile:
如果你讲版本潜入jar实现中Dropwizard项目可以使用项目版本。要使用Maven嵌入这些信息,请将以下内容添加到pom.xml文件的部分:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
This can be handy when trying to figure out what version of your application you have deployed on a machine.
当试图找出你在一台机器上部署的应用程序的版本时,这会很方便。
Once you’ve got that configured, go into your project directory and run mvn package(or run the package goal from your IDE). You should see something like this:
完成配置后,进入项目目录并运行mvn软件包(或从IDE运行软件包目标)。 你应该看到这样的东西:
[INFO] Including org.eclipse.jetty:jetty-util:jar:7.6.0.RC0 in the shaded jar.
[INFO] Including com.google.guava:guava:jar:10.0.1 in the shaded jar.
[INFO] Including com.google.code.findbugs:jsr305:jar:1.3.9 in the shaded jar.
[INFO] Including org.hibernate:hibernate-validator:jar:4.2.0.Final in the shaded jar. \
[INFO] Including javax.validation:validation-api:jar:1.0.0.GA in the shaded jar.
[INFO] Including org.yaml:snakeyaml:jar:1.9 in the shaded jar.
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing /Users/yourname/Projects/hello-world/target/hello-world-0.0.1-SNAPSHOT.jar with /Users/yourname/Projects/hello-world/target/hello-world-0.0.1-SNAPSHOT-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.415s
[INFO] Finished at: Fri Dec 02 16:26:42 PST 2011
[INFO] Final Memory: 11M/81M
[INFO] ------------------------------------------------------------------------
Congratulations!You’ve built your first Dropwizard project! Now it’s time to run it!
恭喜你!你已经完成构建第一个Dropwizard项目,可以运行了!
Running Your Application
Now that you’ve built a JAR file, it’s time to run it.
现在构建一个jar文件,然后运行它。
In your project directory, run this:
在项目目录中,运行一下命令:
java -jar target/hello-world-0.0.1-SNAPSHOT.jar
You should see something like the following:
你应该看到以下信息:
usage: java -jar hello-world-0.0.1-SNAPSHOT.jar
[-h] [-v] {server} ...
positional arguments:
{server} available commands
optional arguments:
-h, --help show this help message and exit
-v, --version show the service version and exit
Dropwizard takes the first command line argument and dispatches it to a matching command. In this case, the only command available isserver, which runs your application as an HTTP server. Theservercommand requires a configuration file, so let’s go ahead and give it the YAML file we previously saved:
Dropwizard接受第一个命令行参数并将其分派到匹配的命令。 在这种情况下,唯一可用的命令是server,它作为HTTP服务器运行你的应用程序。 服务器命令需要一个配置文件,所以让我们继续,并给它我们以前保存的YAML文件:
java -jar target/hello-world-0.0.1-SNAPSHOT.jar server hello-world.yml
You should see something like the following:
你应该看到以下信息:
INFO [2011-12-03 00:38:32,927] io.dropwizard.cli.ServerCommand: Starting hello-world
INFO [2011-12-03 00:38:32,931] org.eclipse.jetty.server.Server: jetty-7.x.y-SNAPSHOT
INFO [2011-12-03 00:38:32,936] org.eclipse.jetty.server.handler.ContextHandler: started o.e.j.s.ServletContextHandler{/,null}
INFO [2011-12-03 00:38:32,999] com.sun.jersey.server.impl.application.WebApplicationImpl: Initiating Jersey application, version 'Jersey: 1.10 11/02/2011 03:53 PM'
INFO [2011-12-03 00:38:33,041] io.dropwizard.setup.Environment:
GET /hello-world (com.example.helloworld.resources.HelloWorldResource)
INFO [2011-12-03 00:38:33,215] org.eclipse.jetty.server.handler.ContextHandler: started o.e.j.s.ServletContextHandler{/,null}
INFO [2011-12-03 00:38:33,235] org.eclipse.jetty.server.AbstractConnector: Started BlockingChannelConnector@0.0.0.0:8080 STARTING
INFO [2011-12-03 00:38:33,238] org.eclipse.jetty.server.AbstractConnector: Started SocketConnector@0.0.0.0:8081 STARTING
Your Dropwizard application is now listening on ports 8080 for application requests and 8081 for administration requests. If you press ^C, the application will shut down gracefully, first closing the server socket, then waiting for in-flight requests to be processed, then shutting down the process itself.
你的Dropwizard应用现在监听8080端口的应用请求和8081端口上的管理请求。如果你按^C组合键,应用将会优雅地关闭,首先关闭服务通信,然后等待进行中的请求执行完毕,最后关闭进程。
However, while it’s up, let’s give it a whirl! Click here to say hello!Click here to get even friendlier!
但是,当它出现的时候,让我们来一个旋转吧!
So, we’re generating sayings. Awesome. But that’s not all your application can do. One of the main reasons for using Dropwizard is the out-of-the-box operational tools it provides, all of which can be found on the admin port.
我们正在产生sayings服务。但是,这不是你的应用程序可以做的。 使用Dropwizard的主要原因之一是它提供的开箱即用的操作工具,所有这些都可以在管理端口找到。
If you click through to the metrics resource, you can see all of your application’s metrics represented as a JSON object.
如果你点击查看metrics resource,能够看到应用的metrics的json格式的数据。
The threads resource allows you to quickly get a thread dump of all the threads running in that process.
线程资源允许您快速获取该进程中运行的所有线程的线程转储。
Hint
When a Jetty worker thread is handling an incoming HTTP request, the thread name is set to the method and URI of the request. This can be very helpful when debugging a poorly-behaving request.
暗示 当Jetty工作线程正在处理传入的HTTP请求时,线程名称将被设置为请求的方法和URI。 这在调试性能不佳的请求时非常有用。
The healthcheck resource runs the health check class we wrote. You should see something like this:
健康检查资源运行我们编写的健康检查类。 你应该看到这样的东西:
* deadlocks: OK
* template: OK
template here is the result of your TemplateHealthCheck, which unsurprisingly passed.deadlocksis a built-in health check which looks for deadlocked JVM threads and prints out a listing if any are found.
这里的模板是您的TemplateHealthCheck的结果,毫不意外地通过。 死锁是一个内置的健康检查,它会查找死锁的JVM线程,并在找到任何列表时打印列表。
Next Steps
Well, congratulations. You’ve got a Hello World application ready for production (except for the lack of tests) that’s capable of doing 30,000-50,000 requests per second. Hopefully, you’ve gotten a feel for how Dropwizard combines Jetty, Jersey, Jackson, and other stable, mature libraries to provide a phenomenal platform for developing RESTful web applications.
那么恭喜你 您已经准备好了一个适用于生产的Hello World应用程序(除了缺少测试),它能够每秒处理30,000-50,000个请求。 希望您已经了解了Dropwizard如何将Jetty,Jersey,Jackson和其他稳定,成熟的库结合起来,为开发RESTful Web应用程序提供一个强大的平台。
There’s a lot more to Dropwizard than is covered here (commands, bundles, servlets, advanced configuration, validation, HTTP clients, database clients, views, etc.), all of which is covered by the User Manual.
Dropwizard还有很多内容(命令,软件包,servlet,高级配置,验证,HTTP客户端,数据库客户端,视图等),所有这些都在用户手册中介绍。