Dropwizard框架入门

简介: 最近项目用到了Dropwizard框架,个人感觉还不错,那么这里就从他们官网入手,然后加上自己的实现步骤让大家初步了解这个框架。   官网对DW(Dropwizard)的定义是跨越了一个库和框架之间的界限。

最近项目用到了Dropwizard框架,个人感觉还不错,那么这里就从他们官网入手,然后加上自己的实现步骤让大家初步了解这个框架。

 

官网对DW(Dropwizard)的定义是跨越了一个库和框架之间的界限。他的目标是提供一个生产就绪的web应用程序所需的一切性能可靠的实现。那么这句话可能有些绕,我个人理解就是他能免去我们部署web应用的很多步骤。由于这个功能被提取到可以重复使用的库中,我们的应用程序保持很大程度的精简和集中,这样可以减少我们程序的上线时间和维护负担。

 

 

Jetty for HTTP

由于Web应用不可能缺少HTTP,DW使用Jetty Http库将一个非常棒的HTTP服务器嵌入到我们的项目中。DW不是将你的程序提交到复杂的服务器上,DW上有个main方法来启动我们的服务器,DW是将我们的应用作为一个简单的线程来跑,消去了Java生产环境中一些非常复杂令人讨厌的过程,并且允许我们使用所有现有的Unix进程管理工具。

 

 

Jersey for REST

 

为了定义Restful的web应用,我们发现在性能和特性方面没有什么能比得过Jersey。它允许你编写干净的,可以测试的类,这个类可以优雅的将http请求映射成为简单的Java对象。它支持流输出,矩阵URL参数,条件GET请求,还有更多。

 

 

Jackson for JSON

 

在数据格式方面,JSON已经成为了网络的通用语,Jackson在jvm中就是Json的龙头老大。除了像闪电一样快速,他有一个复杂的对象映射,允许你直接导出你的域模型。

 

 

Metrics for metrics

 

 

Metrics库对事物进行舍入,在你的生产环境中,为你提供独一无二的洞察力。(也就是说这个是用来监控)那么到了这里,我们关于DW的总体印象应该已经差不多了,下面我结合官网实际操作。

我使用maven和idea进行开发,项目名字为:dw_demo。关于如何创建maven项目不解释,创建完项目后如图所示:

然后打开我们的pom.xml文件,加入dw的依赖(以下并非完全pom文件,仅展现部分):

 

<properties>
    <dropwizard.version>0.9.2</dropwizard.version>
</properties>
<dependencies>
<dependency>
    <groupId>io.dropwizard</groupId>
    <artifactId>dropwizard-core</artifactId>
    <version>${dropwizard.version}</version>
</dependency>
</dependencies>

Creating A Configuration Class

 
每个DW应用都有他自己的子类:Configuration,这个类指定环境中特定的参数。这
些参数在YAML类型的配置文件中被指定,其被反序列化为应用程序配置类的实例并验
证。(这句话的意思就是这个配置文件中指定的参数,会被映射到我们项目的一个类)
我们将要构建的是一个helloworld高性能服务。我们的一个要求就是我们需要能够在不同
的环境中让它说hello。在开始之前我们需要指定至少两个内容:一个说hello的模板 还有
一个默认的名字以防用户忘记指定。
 
那么我下面开始创建我的配置文件:
 
 

 

内容如下:

 

 

package com.config;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.Configuration;
import org.hibernate.validator.constraints.NotEmpty;

/**
 * Created by moon on 2017/1/13.
 */
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() {
        return defaultName;
    }

    @JsonProperty
    public void setDefaultName(String name) {
        this.defaultName = name;
    }
}

当这个类被从YAML配置文件反序列化的时候,他会从YAML对象中获取两个根层次的变量:template 用来说helloworld的模板。defaultName 默认的名字。template和defaultName都用@NotEmpty被注释,所以在YAML配置文件中如果有空值或者忘了其中一者,异常将会被抛出,我们的应用将不会被启动。

 

defaultName和template的get 和set 方法都被@JsonProperty标注,这不止允许jackson从YAML配置文件反序列化,同样允许它序列化。

 

然后我们创建一个YAML的配置文件:

 

 

里面的内容如下:

 

 

template: Hello, %s!
defaultName: Stranger

 

大家可以看到,与我们的配置类中的变量一一对应,相信很多人看到这里就明白了。

 

 

 

Creating An Application Class

 

 

结合我们项目中的Configuration子类,我们的Application的子类形成了我们DW的应用的核心。Application的子类把不同的提供各式各样功能的包和命令拉取到了一起。

 

现在,我们开始建立我们的Application子类:

 

 

其内容如下:

 

 

package com.app;

import com.config.HelloWorldConfiguration;
import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;

/**
 * Created by moon on 2017/1/13.
 */
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方法有点无趣,让我们开始丰富它。

 

 

 

Creating A Representation Class

 

 

在我们开始继续我们的程序之前,我们需要停下来思考一下我们程序的API。幸运的是,我们的应用需要符合行业标准。RFC 1149(别问我这是什么,连这个都不知道,我tm也不知道)。他指定了helloworld saying的如下json表达形式:

 

{
  "id": 1,
  "content": "Hi!" }

 

id字段是语法的唯一标识符。content是说的具体内容。

 

 

为了建模这个表示,我们需要创建一个表示类 :

 

 

该类的内容如下:

 

 

package com.api;

import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.Length;

/**
 * Created by moon on 2017/1/13.
 */
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() {
        return id;
    }

    @JsonProperty
    public String getContent() {
        return content;
    }
}

这是一个非常简单的POJO,但是有些需要注意的地方。

 

 

首先,他是不可更改的。这使得saying在多线程环境和单线程环境非常容易被推理。其次,它使用java的JavaBean来保存id和content属性。这允许jackson把他序列化为我们需要的JSON。jackson对象的映射代码将会使用getId()返回的对象来填充JSON对象的id字段,content同理。最后,bean利用验证来确保内容不大于3。

 

 

Creating A Resource Class

 

 

Jersey资源是DW应用程序的肉和土豆(这种比喻我也是醉了)。每个资源类都与URL相关联(这个很重要,后面有说)。对于我们的应用程序来说,我们需要一个resources来通过url:/helloworld来返回新的Saying实例对象。

 

现在我们开始建立的Resource:

 

 

类的内容如下:

 

 

package com.resource;

import com.api.Saying;
import com.codahale.metrics.annotation.Timed;
import com.google.common.base.Optional;

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;

/**
 * Created by moon on 2017/1/13.
 */
@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。

 

 

Registering A 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.

 

 

在pom文件中加入:

 

 

<build>
    <plugins>
        <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.app.HelloWorldApplication</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>

    </plugins>
</build>

然后打包:

 

 

 

打包成功后,在我们的target目录下面会出现我们所需的包:

 

 

然后我们开始运行:

 

 

这里面官方为我们提供两个参数,我们需要启动服务,所以后面加入server参数,重新启动如下:

 

 

这说明我们的项目已经启动了,那么让我们访问一下url看是否正确:



返回结果正常,没毛病。

以上仅仅是DW的初步,还有许多其他功能,由于时间关系,不做详细介绍,如果

有时间我会再奉上一版深度版的。链接为:

DW官网深层次内容

希望这次的讲解对大家有帮助,感谢开源。

相关文章
|
6月前
|
JavaScript Java
14 SpringBoot的Web开发简介
14 SpringBoot的Web开发简介
34 0
|
11天前
|
XML 监控 Java
Springboot框架入门和学习
Springboot框架入门和学习
|
4月前
|
JavaScript Java 测试技术
SpringBoot原理分析 | 开源框架:Swagger集成
SpringBoot原理分析 | 开源框架:Swagger集成
29 0
BXA
|
11月前
|
设计模式 开发框架 监控
Spring Framework构建优雅简洁的Java应用
Spring Framework是一个开源的Java开发框架,提供了一系列底层的架构和模式帮助Java开发人员简化企业级应用的开发过程。
BXA
614 0
|
XML 开发框架 Java
SpringBoot 框架入门
SpringBoot是基于 Spring 开发的一种轻量级的全新框架,不仅继承了 Spring 框架原有的优秀特性,而且还通过简化配置来进一步简化了 Spring 应用的整个搭建和开发过程。
192 0
SpringBoot 框架入门
|
XML Java 测试技术
testNG框架从入门到精通
testNG框架从入门到精通
testNG框架从入门到精通
|
前端开发 NoSQL Java
19、SpringBoot2.0中响应式编程和 WebFlux 入门(十九)
Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕。
208 0
19、SpringBoot2.0中响应式编程和 WebFlux 入门(十九)
|
Java 开发工具 git
插件式编程SBP框架极简教程(基于SpringBoot)
插件式编程SBP框架极简教程(基于SpringBoot)
500 0
插件式编程SBP框架极简教程(基于SpringBoot)
|
XML 开发框架 前端开发
【重温SSM框架系列】1 - Spring快速入门(配置文件及API详解)
1 - Spring快速入门(配置文件及API详解)
117 0
【重温SSM框架系列】1 - Spring快速入门(配置文件及API详解)