在开始之前我们需要准备一些环境,以下为本次所需相关工具:
系统:windows 7
JDK:1.8
开发工具:IntelliJ IDEA 2017.2.5
Maven:idea自带最新版本,采用本地化setting.xml(可以参考阿里巴巴的源配置,这样创建项目时自动下载要快很多倍)

本次编写demo参考依据为Dropwizard官网

下面我们开始进入正题,创建第一个基于Dropwizard的Hello World

一、创建一个maven的web项目

1.png

2.png

3.png

4.png

这里在创建时因为我本地已经存在了settings.xml,因此选择本地化配置文件,如果采用默认的则不需要进行选择。

5.png

6.png

点击图中标记的位置,将相关包进行下载并加入引用中,其实默认就一个junit包引用而已。

二、开始进行创建基础包路径

image.png

image.png

创建一个java目录,并设置该目录为根目录。

三、在pom.xml中引入dependency基础包。

<properties>
    <dependency.version>1.2.0</dependency.version>
  </properties>
  <dependencies>
    <!-- Dropwizard基础包 -->
    <dependency>
      <groupId>io.dropwizard</groupId>
      <artifactId>dropwizard-core</artifactId>
      <version>${dependency.version}</version>
    </dependency>

  </dependencies>

四、创建基础yml配置文件

image.png
该demo1.yml文件中的内容为:

#要打印的基础语句,其中%s是占位符。
template: Hello, %s!
#默认引用时的名字,这里名字叫做Stranger
defaultName: Stranger
在这里开始进入Dropwizard特性的一些编写了。
yml配置文件在官方解释中是这样说的:

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.
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时就直接按照上面说的来了。word在模板里面先用占位符,这样就可以[hello,小明]了o(╯□╰)o

五、创建基础Configuration,用于进行反序列化。

package com.demo1.helloworld.configuration;

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

/**
 * <b>TODO(com.demo1.helloworld.configuration @TODO)</b><br>
 * 版权所有 <a href="http://www.whndj.com">中国,華少</a><br>
 * 本软件仅对本次教程负责,其版权归属cnHuaShao,如需引用,请申明其版权所有人。
 *
 * @Description: 
 * @CreateDate 2017 2017/11/4 10:31 11 修改人:
 * <a href="mailto:[email protected]">cnHuaShao</a>
 * 修改备注:
 * @since V1.0
 */
public class HelloWorldConfiguration extends Configuration {

    /**
     * NotEmpty注解表示该变量不可以为空,之前我们在demo1.yml中已经编写了该变量对应的值,这个类主要是将其进行反序列化
     */
    @NotEmpty
    private String template;

    /**
     * NotEmpty注解表示该变量不可以为空,之前我们在demo1.yml中已经编写了该变量对应的值,这个类主要是将其进行反序列化
     * 默认值直接写入Stranger,这里根据自己的demo1.yml中defaultName默认值写的是什么就直接赋值什么,当然也可以不赋值,等具体引用时在赋值,不过建议还是写上去一个默认值,防止它出错。
     * 如果这两个值是空,则抛出系统异常
     */
    @NotEmpty
    private String defaultName = "Stranger";

    /**
     * 这里get set进行注解JsonProperty主要是为了对yml进行反序列化使用
     * @return
     */
    @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;
    }

}

官方给出的解释是:

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

六、进行创建基础Application

package com.demo1.helloworld.application;

import com.demo1.helloworld.configuration.HelloWorldConfiguration;
import io.dropwizard.Application;
import io.dropwizard.setup.Environment;

/**
 * <b>TODO(com.demo1.helloworld.application @TODO)</b><br>
 * 版权所有 <a href="http://www.whndj.com">中国,華少</a><br>
 * 本软件仅对本次教程负责,其版权归属cnHuaShao,如需引用,请申明其版权所有人。
 *
 * @Description: 
 * @CreateDate 2017 2017/11/4 10:58 11 修改人:
 * <a href="mailto:[email protected]">cnHuaShao</a>
 * 修改备注:
 * @since V1.0
 */
public class HelloWorldApplication  extends Application<HelloWorldConfiguration> {

    /**
     * 基础核心启动方法。dropwizard应用的核心方法。主要进行处理具体的业务逻辑的类
     * @param configuration
     * @param environment
     * @throws Exception
     */
    public void run(HelloWorldConfiguration configuration, Environment environment) throws Exception {

    }

    @Override
    public String getName() {
        return "hello-world";
    }
}

七、创建一个基础表示类,其需要使其转成JSON时遵循RFC 1149

package com.demo1.helloworld.api;

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

/**
 * <b>TODO(com.demo1.helloworld.api @TODO)</b><br>
 * 版权所有 <a href="http://www.whndj.com">中国,華少</a><br>
 * 本软件仅对本次教程负责,其版权归属cnHuaShao,如需引用,请申明其版权所有人。
 *
 * @Description: 
 * @CreateDate 2017 2017/11/4 11:07 11 修改人:
 * <a href="mailto:[email protected]">cnHuaShao</a>
 * 修改备注:
 * @since V1.0
 */
public class Saying {

    private long id;

    /**
     * 内容最大长度不可以超过10
     */
    @Length(max = 10)
    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;
    }
}

八、创建Resource 类

package com.demo1.helloworld.resources;

import com.codahale.metrics.annotation.Timed;
import com.demo1.helloworld.api.Saying;

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;
import java.util.Optional;

/**
 * <b>TODO(com.demo1.helloworld.resources @TODO)</b><br>
 * 版权所有 <a href="http://www.whndj.com">中国,華少</a><br>
 * 本软件仅对本次教程负责,其版权归属cnHuaShao,如需引用,请申明其版权所有人。
 *
 * @Description: 
 * @CreateDate 2017 2017/11/4 11:19 11 修改人:
 * <a href="mailto:[email protected]">cnHuaShao</a>
 * 修改备注:
 * @since V1.0
 */
@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();
    }

    /**
     * @Timed dropwizard会自动记录时间和它的调用率作为度量定时器
     * @param name
     * @return
     * @QueryParam 为URL链接后面的参数(url ?{参数名} = {参数值} 的格式)
     */
    @GET//客户端访问时只能通过get方法访问
    @Timed
    public Saying sayHello(@QueryParam("name") Optional<String> name) {
        //如果name参数没有传入,则调用defaultName的值,如果传入了,则采用name的值
        final String value = String.format(template, name.orElse(defaultName));
        //返回Saying对象
        return new Saying(counter.incrementAndGet(), value);
    }
}

九、修改第六步时创建的Application中的run方法。

public void run(HelloWorldConfiguration configuration, Environment environment) throws Exception {
        //声明一个resource,并传入初始化的值,该值由configuration读取的yml配置文件中的值。
        //可以启动多个resource
        final HelloWorldResource resource = new HelloWorldResource(
                configuration.getTemplate(),
                configuration.getDefaultName()
        );

        environment.jersey().register(resource);
    }

十、创建一个HealthCheck类

package com.demo1.helloworld.health;

import com.codahale.metrics.health.HealthCheck;

/**
 * <b>TODO(com.demo1.helloworld.health @TODO)</b><br>
 * 版权所有 <a href="http://www.whndj.com">中国,華少</a><br>
 * 本软件仅对本次教程负责,其版权归属cnHuaShao,如需引用,请申明其版权所有人。
 *
 * @Description: 
 * @CreateDate 2017 2017/11/4 11:37 11 修改人:
 * <a href="mailto:[email protected]">cnHuaShao</a>
 * 修改备注:
 * @since V1.0
 */
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, "模板测试");
        if (!saying.contains("模板测试")) {
            return Result.unhealthy("该模板不包含名称");
        }
        return Result.healthy();
    }


}

官方给出的解释是这样的:

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.
其实这个是可有可无的,为了安全起见,这里先加上。(官方例子中要求加上o(╯□╰)o)

十一、再次修改第六步时创建的Application中的run方法。

public void run(HelloWorldConfiguration configuration, Environment environment) throws Exception {
        //声明一个resource,并传入初始化的值,该值由configuration读取的yml配置文件中的值。
        //可以启动多个resource
        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);
    }

十一、创建一个main方法。

package com.demo1.helloworld.main;

import com.demo1.helloworld.application.HelloWorldApplication;

/**
 * <b>TODO(com.demo1.helloworld.main @TODO)</b><br>
 * 版权所有 <a href="http://www.whndj.com">中国,華少</a><br>
 * 本软件仅对本次教程负责,其版权归属cnHuaShao,如需引用,请申明其版权所有人。
 *
 * @Description: 
 * @CreateDate 2017 2017/11/4 11:00 11 修改人:
 * <a href="mailto:[email protected]">cnHuaShao</a>
 * 修改备注:
 * @since V1.0
 */
public class HelloWorldMain {

    public static void main(String[] args) throws Exception {
        //启动helloworld
        new HelloWorldApplication().run(args);
    }
}

官方例子中main方法写在Application类中,我这里将其提出来了,方便大家理解。

至此,我们这个例子基本上写完了,开始进行打包。

十二、修改maven的pom.xml文件

<plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
              </configuration>
          </plugin>
          <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.demo1.helloworld.main.HelloWorldMain</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>

十三、开始进行打包

image.png

image.png

image.png

image.png

image.png

image.png

image.png

十四、开始启动

image.png

image.png

image.png

image.png

看到上面的日志,则表明启动成功,打开浏览器访问:

http://localhost:8080/hello-world

image.png

http://localhost:8080/hello-world?name=xiaoming

image.png

至此,本次的Hello World编写完成。

所有代码均可以通过我的GItHub进行获取到,如有需要可以点击我的GitHub下载。