The recent project uses the Dropwizard framework, the personal feeling is also good, then starts from their official website, then adds own realization step lets everybody preliminary understand this framework.
The official website's definition of DW (Dropwizard) spans the boundaries between a library and a frame. His goal is to provide a reliable implementation of all the required performance of a production-ready Web application. So this may be a bit of a detour, and I personally understand that he can dispense with the many steps we have to deploy Web apps. Since this feature is extracted to reusable libraries, our applications remain largely streamlined and centralized, which can reduce the time and maintenance burden of our programs.
Jetty for HTTP because Web applications are unlikely to be missing HTTP,DW use the Jetty HTTP library to embed a very good HTTP server into our project. DW is not submitting your program to a complex server, DW has a main method to start our server, DW is our application as a simple thread running, eliminating the Java production environment some very complex annoying process, and allows us to use all existing UNIX process management tools.
Jersey for REST
To define restful Web applications, we find that there is nothing comparable to Jersey in terms of performance and features. It allows you to write clean, testable classes that gracefully map HTTP requests to simple Java objects. It supports stream output, matrix URL parameters, conditional get requests, and more.
Jackson for JSON
In terms of data format, JSON has become a common language for the web, and Jackson is the leader of JSON in the JVM. In addition to being as fast as lightning, he has a complex object map that allows you to directly export your domain model.
Metrics for Metrics
The Metrics library rounds things up and provides you with unique insights in your production environment. (That is, this is used to monitor) so here, our overall impression of DW should have been almost, the following I combined the actual operation of the official website.
I developed using MAVEN and idea, the project name is: Dw_demo. There is no explanation for how to create a MAVEN project, after you create the project as shown in the figure:
Then open our Pom.xml file and join the DW dependency (the following is not a full pom file, only the show section):
<properties>
<dropwizard.version>0.9.2</dropwizard.version>
</properties>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactid>dropwizard-core</ artifactid>
<version>${dropwizard.version}</version>
</dependency>
creating A Configuration Class
Each DW application has its own subclass: Configuration, which specifies specific parameters in the environment. These parameters are specified in a configuration file of type Yaml, which is deserialized into an instance of the application configuration class and validated. (this means that the parameters specified in this configuration file are mapped to a class of our project) and we are going to build a HelloWorld high-performance service. One of our requirements is that we need to be able to say hello in different contexts. We need to specify at least two items before we start: A hello template also has a default name in case the user forgets to specify it.
So I'll start by creating my profile here:
The contents are as follows:
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;
}
}
When this class is deserialized from the Yaml configuration file, he gets two root-level variables from the Yaml object: template is used to say HelloWorld templates. DefaultName the default name. Template and DefaultName are annotated with @notempty, so if there is a null value in the YAML configuration file or if you forget one, the exception will be thrown and our application will not be started.
Both the get and set methods of DefaultName and template are @jsonproperty labeled, which not only allows Jackson to deserialize from Yaml configuration file, but also allows it to be serialized.
Then we create a YAML configuration file:
The contents are as follows:
Template:hello,%s!
Defaultname:stranger
As you can see, it corresponds to the variable one by one in our configuration class, and I'm sure a lot of people will see it here.
Creating an application Class
Combining the configuration subclasses of our project, our application subclasses form the core of our DW application. Application's subclasses pull together different packages and commands that provide a wide variety of features.
Now, let's start building our application subclass:
Its contents are as follows:
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
As we can see, Helloworldapplication uses the configuration of the application for parameterization. (because it uses our helloworldconfiuration, and it's a configuration subclass).
The Initialize method is used to configure the application before it is formally started: package, configuration source, and so on. At the same time we need to add a main method, which is the entrance to our application. So far, we haven't implemented any functionality, so our run method is a bit boring, so let's start enriching it.
creating A representation Class
Before we begin to continue our program, we need to stop and think about the API of our program. Fortunately, our application needs to conform to industry standards. RFC 1149 (Don't ask me what it is, I don't even know it, I don't know). He specifies the following JSON expression for HelloWorld saying:
{
"id": 1, "
content": "hi!"
}
The ID field is a unique identifier for the syntax. Content is the specific contents of the said.
To model this representation, we need to create a representation class:
The contents of the class are as follows:
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;
}
}
This is a very simple pojo, but there are some areas that need attention.
First of all, he is not to be changed. This makes saying very easy to infer in multi-threaded environments and single-threaded environments. Second, it uses Java JavaBean to hold the ID and content attributes. This allows Jackson to serialize him to the JSON we need. The Jackson object's mapping code will populate the JSON object's ID field with the object returned by GetID (), with the same content. Finally, the bean uses validation to ensure that the content is not greater than 3.
creating A Resource Class
Jersey resources are the meat and potatoes of the DW application (I am also drunk with this analogy). Each resource class is associated with a URL (this is important, as it is said later). For our applications, we need a resources to return the new saying instance object via Url:/helloworld.
Now we are starting to build the resource:
The contents of the class are as follows:
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_jsonpublic 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 V
Alue = String.Format (template, Name.or (DefaultName));
return new saying (Counter.incrementandget (), value); }
}
Helloworldresource has two statements: @Path and @produces. The @Path ("/hello-world") tells Jersey that the resource can be accessed through the "/hello-world" URL.
@Produces (Mediatype.application_json) Let Jersey's content negotiation code know that this resource produces Application/json.
The Helloworldresource constructor receives two parameters, creates the template of the saying, and the default name when the user does not specify a name. Atomiclong provides us with a thread-safe, easy way to generate (ish) IDs.
SayHello method is this kind of meat, but also a very simple method. The @QueryParam ("name") tells Jersey to map name in the query parameter to name in the method. If a client sends a request to: The/hello-world?name=dougie,sayhello method will be invoked with Optional.of ("Dougie"). If there is no Name,sayhello in the query parameter, it will be invoked with Optional.absent ().
In the SayHello method, we increase the value of the counter, use String.Format to format the template, and return a new saying instance. Because SayHello is @timed annotated, the DW will automatically call his duration and rate record as the metric timer.
Once SayHello returns, Jersey takes an instance of saying and looks for a provider class to write the saying instance as: Application/json.
Registering A Resource
Before these formal jobs, we need to get into the helloworldapplication and join the new resouce, In the Run method we can read the template and DefaultName instances of helloworldconfiguration, create a new Helloworldresource instance, and add it to the New Jersey environment.
The new run method in our helloworldapplication is as follows:
@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 use the parameters in the configuration file to create a new instance of the resource class and pass it to environment.
In the Pom file, add:
<build> <plugins> <plugin> <GROUPID>ORG.APACHE.MAVEN.PLUGINS</GROUPID&G
T <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <con Figuration> <createDependencyReducedPom>true</createDependencyReducedPom> &
lt;filters> <filter> <artifact>*:* </artifact> <excludes> <exclude>meta-inf/*. Sf</exclude> <exclude>meta-inf/*. Dsa</exclude> <exclude>meta-inf/*. rsa</exclude> </excludes> </filter> </fil
ters> </configuration> <executions> <execution> <phase>paCkage</phase> <goals> <goal>shade</goal>
</goals> <configuration> <transformers> <transformer implementation= "Org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"
/> <transformer