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文件:
0.9.2
io.dropwizard
dropwizard-core
${dropwizard.version}
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 {
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
}
}
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 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。
在sayHello方法里面,我们增加计数器的值,使用String.format来格式化模板,返回一个新的Saying实例。因为sayHello被@Timed注释,DW将会自动调用他的持续时间和速率记录为度量定时器。
6、Registering A Resource
在HelloworldApplication中写run方法:
@Override
public 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检查两件事:所提供的模板实际上是格式良好的格式字符串,而模板实际上是使用给定的名称产生输出。
@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);
}
8、Building Fat JARs
在pom.xml中加入:
org.apache.maven.plugins
maven-shade-plugin
2.3
true
*:*
META-INF/*.SF
META-INF/*.DSA
META-INF/*.RSA
package
shade
app.WeChatApplication
org.apache.maven.plugins
maven-jar-plugin
2.4
true
在项目目录运行
mvn package,接着运行java -jar target/hello-world-0.0.1-SNAPSHOT.jar
server
hello
-
world
.yml