Dropwizard Getting Start

原文鏈接: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

查看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客戶端,數據庫客戶端,視圖等),所有這些都在用戶手冊中介紹。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容