dropwizard框架学习

来源:互联网 发布:淘宝点外卖 编辑:程序博客网 时间:2024/05/16 16:16

Dropwizard:


Overview:

Dropwizard straddles the line between being a library and a framework. 

跨越了库和框架之间的界限。


Jetty for Http:

由于不能成为一个没有HTTP的web应用程序,Dropwizard使用Jetty HTTP库将一个HTTP服务器嵌入到项目中。与把应用程序交给复杂的应用程序服务器不同,Dropwizard有个main方法来启动我们的服务器。运行应用程序是一个简单的过程消除了很多Java令人讨厌的生产方面的过程(没有PermGen问题,应用服务器配置和维护,没有晦涩难懂的部署工具,没有类装入器问题,没有隐藏应用程序日志,没有试图优化一个垃圾收集器与多个应用程序工作负载),允许使用现有的Unix进程管理工具。


Jersery for REST:

为了构建基于rest的web应用程序,我们在特性或性能方面没有发现任何优于Jersey(jax - rs参考实现)的东西。它允许您编写干净的、可测试的类,将HTTP请求优雅地映射到简单的Java对象。它支持流输出、矩阵URI参数、条件GET请求,以及更多

 jersey是基于Java的一个轻量级RESTful风格的WebServices框架.


Jackson for JSON:

就数据格式而言,JSON已经成为web的通用语言,而Jackson是JVM中的JSON之王。除了闪电般的快速,它还有一个复杂的对象映射器,允许直接导出领域模型。


Metrics for metrics:

度量库将事情进行了分析,为在生产环境中的代码行为提供了无与伦比的洞察。


简而言之:

Dropwizard是一个开源的Java框架,用于开发OPS友好、高性能的基于REST的后端,提供同类最佳的Java库到一个嵌入式应用程序包。有几下几个部分:

1、嵌入式Jetty:每一个应用程序被打包成一个jar(而不是war)文件,并开始自己的嵌入式Jetty容器。没有任何war文件和外部servlet容器。(每个Dropwizard应用程序有一个启动Jetty容器的主程序。这意味着,完全可以把应用程序作为一个主程序在IDE中运行和调试。所以就没有重新编译或部署war文件

2、JAX-RS:Jersey是用来写基于REST的Web服务的。

3、JSON:REST服务用的是JSON,Jackson库用来做所有的JSON处理。

4、Hibernate验证:Dropwizard使用Hibernate验证API进行声明性验证。

5、指标:Dropwizard支持监控使用标准库,它在监控代码方面有无与伦比的洞察力。

6、日志:使用Logback和SLF4J完成。


开发:

1、pom.xml文件:

<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>
2、Configuration类

每个Dropwizard应用都有一个Configuration的子类,指定环境相关的参数。这些参数在一个YAML配置文件中指定。该配置会被反序列化,得到应用配置对应的Configuration实例并进行验证。这个配置文件中指定的参数,会被映射到我们项目的一个类。

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() {        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
3、Application类
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进行参数化。

initialize方法用于配置应用在正式启动之前所需:包,配置源等。同时我们需要加入一个main方法,这是我们应用的入口。

4、Representation类(POJO类)

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() {        return id;    }    @JsonProperty    public String getContent() {        return content;    }}
这是一个非常简单的POJO,有几点需要注意。首先,它不可更改,这使得它在多线程和单线程环境中很容易推断出实例。其次,它使用javabean来表示id和content属性,这允许jackson把它序列化为我们所需的json。jackson对象的映射代码将会使用getId()返回的对象来填充JSON对象的id字段,content同理。bean利用验证来确保content不大于3。

5、Resource Class(可以调用的接口api)

Jersey资源是DW应用程序的肉和土豆。每个资源类都与URL相关联。对于应用程序来说,需要一个resources来通过url:/helloworld来返回新的Saying实例对象。

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。
@QueryParam("name")告诉Jersey把在查询参数中的name映射到方法中的name中。如果一个客户发送请求到:/hello-world?name=Dougie,sayHello 方法将会伴随Optional.of("Dougie")被调用。如果查询参数中没有name,sayHello将会伴随着Optional.absent()被调用。

在sayHello方法里面,我们增加计数器的值,使用String.format来格式化模板,返回一个新的Saying实例。因为sayHello被@Timed注释,DW将会自动调用他的持续时间和速率记录为度量定时器。

6、Registering A Resource

在HelloworldApplication中写run方法:

@Overridepublic void run(HelloWorldConfiguration configuration,                Environment environment) {    final HelloWorldResource resource = new HelloWorldResource(        configuration.getTemplate(),        configuration.getDefaultName()    );    environment.jersey().register(resource);}
当我们的应用程序启动时,我们将从配置文件中创建一个新的资源类实例,并将其交给环境,它就像一个注册表,您的应用程序可以做的所有事情。

7、Health Check
Health Check提供了一种方法,可以在应用程序中添加小测试,以验证应用程序在生产中是否正常运行。强烈建议您的所有应用程序至少有最少的Health Check集。

由于在应用程序运行时,格式化字符串不太可能失败(不像数据库连接池),因此需要在这里获得一点创造性。

模板:

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();    }}
TemplateHealthCheck检查两件事:所提供的模板实际上是格式良好的格式字符串,而模板实际上是使用给定的名称产生输出。
添加Health Check:

@Overridepublic 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);}
8、Building Fat JARs

在pom.xml中加入:

<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>app.WeChatApplication</mainClass>                                </transformer>                            </transformers>                        </configuration>                    </execution>                </executions>            </plugin>            <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>        </plugins>    </build>
在项目目录运行 mvn package,接着运行java-jartarget/hello-world-0.0.1-SNAPSHOT.jar serverhello-world.yml

原创粉丝点击