zoukankan      html  css  js  c++  java
  • 非常棒的Java REST服务器栈

    Dropwizard 是一个开源的Java框架,用于开发OPS友好、高性能的基于REST的后端。它是由Yammer开发的,来驱动基于JVM的后端。

    Dropwizard提供同类最佳的Java库到一个嵌入式应用程序包。它由以下部分组成:

    嵌入式Jetty:每一个应用程序被打包成一个jar(而不是war)文件,并开始自己的嵌入式Jetty容器。没有任何war文件和外部servlet容器。
    JAX-RS:Jersey(JAX-RS的参考实现)是用来写基于REST的Web服务的。
    JSON:REST服务用的是JSON,Jackson库用来做所有的JSON处理。
    日志:使用Logback和SLF4J完成。
    Hibernate验证:Dropwizard使用Hibernate验证API进行声明性验证。
    指标:Dropwizard支持监控使用标准库,它在监控代码方面有无与伦比的洞察力。
     
     
     
    1、配置maven以导入jar包。
     
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
      
        <groupId>com.shekhar</groupId>
        <artifactId>blog</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
      
        <name>blog</name>
        <url>http://maven.apache.org</url>
      
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
      
        <dependencies>
            <dependency>
                <groupId>com.yammer.dropwizard</groupId>
                <artifactId>dropwizard-core</artifactId>
                <version>0.6.2</version>
            </dependency>
      
        </dependencies>
      
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
      
      
            </plugins>
        </build>
    </project>
     
    2、创建配置类
     
    每个Dropwizard应用程序都有一个配置类,它指定特定的环境参数。文章后面会将如主机、端口和数据库名之类的MongoDB的配置参数添加给它。这个类扩展了 com.yammer.dropwizard.config.Configuration类。
     
    import com.yammer.dropwizard.config.Configuration;
      
    public class BlogConfiguration extends Configuration{
      
    }
     
     
    3、创建服务类
     
    该Dropwizard项目由一个服务类自举。这个类将各种提供基本功能的捆绑和命令集合在一块,它还启动嵌入式Jetty服务器并延伸com.yammer.dropwizard.Service。
     
    import com.yammer.dropwizard.Service;
    import com.yammer.dropwizard.config.Bootstrap;
    import com.yammer.dropwizard.config.Environment;
      
    public class BlogService extends Service<BlogConfiguration> {
      
        public static void main(String[] args) throws Exception {
            new BlogService().run(new String[] { "server" });
        }
      
        @Override
        public void initialize(Bootstrap<BlogConfiguration> bootstrap) {
            bootstrap.setName("blog");
        }
      
        @Override
        public void run(BlogConfiguration configuration, Environment environment) throws Exception {
      
        }
      
    }
    上面的这些服务类可以:
     
    有一个作为服务入口点的main方法。在main方法里面,创建BlogService的实例,并调用run方法。我们将服务器命令作为参数传递,服务器命令将启动嵌入式Jetty服务器。
    初始化方法在服务运行方法之前被调用。
    接下来,服务运行时将调用它的run方法,文章后面会将JAX-RS源加到这个方法里。
     
    4、写IndexResource
     
    写一个当GET请求指向“/” URL时会被调用的源,创建一个新的JAX-RS源(此资源将列出所有的博客),如下:
     
    import java.util.Arrays;
    import java.util.List;
      
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
      
    import com.yammer.metrics.annotation.Timed;
      
    @Path("/")
    public class IndexResource {
      
        @GET
        @Produces(value = MediaType.APPLICATION_JSON)
        @Timed
        public List<Blog> index() {
            return Arrays.asList(new Blog("Day 12: OpenCV--Face Detection for Java Developers",
                    "https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers"));
        }
    }
    上面这段代码是一个标准的JAX-RS资源类。它添加@ Path注释和定义index()方法,这个index()会返回一个博客集合,这些博客将被转换为JSON文档。
     
    上面提到IndexResource是用博客表示的。下面这段则表明该博客使用Hibernate验证器注解,以确保内容是有效的。例如,使用@URL注释,以确保只有合法的URL存储在MongoDB数据库。
     
    import java.util.Date;
    import java.util.UUID;
      
    import org.hibernate.validator.constraints.NotBlank;
    import org.hibernate.validator.constraints.URL;
      
    public class Blog {
      
        private String id = UUID.randomUUID().toString();
      
        @NotBlank
        private String title;
      
        @URL
        @NotBlank
        private String url;
      
        private final Date publishedOn = new Date();
      
        public Blog() {
        }
      
        public Blog(String title, String url) {
            super();
            this.title = title;
            this.url = url;
        }
      
        public String getId() {
            return id;
        }
      
        public String getTitle() {
            return title;
        }
      
        public String getUrl() {
            return url;
        }
      
        public Date getPublishedOn() {
            return publishedOn;
        }
    }
    接下来,在服务类的run方法注册IndexResource。用下面的方式更新BlogService run方法。
     
    @Override
    public void run(BlogConfiguration configuration, Environment environment) throws Exception {
       environment.addResource(new IndexResource());
    }
    现在,可以将BlogService类​​作为一个主程序来运行(右键点击>运行方式> Java应用程序),这将启动嵌入式Jetty容器,我们可以看到程序在 http://localhost:8080/ 里运行。
     
    $ curl http://localhost:8080
      
    [{"id":"9bb43d53-5436-4dac-abaa-ac530c833df1","title":"Day 12: OpenCV--Face Detection for Java Developers","url":"https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers","publishedOn":1384090975372}]
    The administrative interface is available at http://localhost:8081/.
     
    现在可以通过点击“指标(Metrics)”检查IndexResource的指标,该数据是可用的JSON格式。
     
    "com.shekhar.blog.IndexResource" : {
        "index" : {
          "type" : "timer",
          "duration" : {
            "unit" : "milliseconds",
            "min" : 17.764,
            "max" : 17.764,
            "mean" : 17.764,
            "std_dev" : 0.0,
            "median" : 17.764,
            "p75" : 17.764,
            "p95" : 17.764,
            "p98" : 17.764,
            "p99" : 17.764,
            "p999" : 17.764
          },
          "rate" : {
            "unit" : "seconds",
            "count" : 1,
            "mean" : 7.246537731991882E-4,
            "m1" : 2.290184897291144E-12,
            "m5" : 3.551918562683463E-5,
            "m15" : 2.445031498756583E-4
          }
        }
      },
     
     
    5、配置MongoDB
     
    在pom.xml 里加入 mongo-jackson-mapper 的依赖。
     
    <dependency>
        <groupId>net.vz.mongodb.jackson</groupId>
        <artifactId>mongo-jackson-mapper</artifactId>
        <version>1.4.2</version>
    </dependency>
    用MongoDB数据库的详细信息(如主机、端口和数据库名等)更新BlogConfiguration类。
     
    import javax.validation.constraints.Max;
    import javax.validation.constraints.Min;
      
    import org.codehaus.jackson.annotate.JsonProperty;
    import org.hibernate.validator.constraints.NotEmpty;
      
    import com.yammer.dropwizard.config.Configuration;
      
    public class BlogConfiguration extends Configuration {
      
        @JsonProperty
        @NotEmpty
        public String mongohost = "localhost";
      
        @JsonProperty
        @Min(1)
        @Max(65535)
        public int mongoport = 27017;
      
        @JsonProperty
        @NotEmpty
        public String mongodb = "mydb";
    }
    接下来,创建一个名为MongoManaged的新类,它将允许你在应用程序启动和停止时管理程序资源。这样就实现了com.yammer.dropwizard.lifecycle.Managed。
     
    import com.mongodb.Mongo;
    import com.yammer.dropwizard.lifecycle.Managed;
      
    public class MongoManaged implements Managed {
      
        private Mongo mongo;
      
        public MongoManaged(Mongo mongo) {
            this.mongo = mongo;
        }
      
        @Override
        public void start() throws Exception {
        }
      
        @Override
        public void stop() throws Exception {
            mongo.close();
        }
      
    }
     
    在上面的代码中,关闭了stop方法中的MongoDB连接。
    下一步,写一个MongoHealthCheck来检查MongoDB的连接与否。
     
    import com.mongodb.Mongo;
    import com.yammer.metrics.core.HealthCheck;
      
    public class MongoHealthCheck extends HealthCheck {
      
        private Mongo mongo;
      
        protected MongoHealthCheck(Mongo mongo) {
            super("MongoDBHealthCheck");
            this.mongo = mongo;
        }
      
        @Override
        protected Result check() throws Exception {
            mongo.getDatabaseNames();
            return Result.healthy();
        }
      
    }
    现在,更新BlogService类​​,将MongoDB的配置包含进来。
     
    package com.shekhar.blog;
      
    import com.mongodb.Mongo;
    import com.yammer.dropwizard.Service;
    import com.yammer.dropwizard.config.Bootstrap;
    import com.yammer.dropwizard.config.Environment;
      
    public class BlogService extends Service<BlogConfiguration> {
      
        public static void main(String[] args) throws Exception {
            new BlogService().run(new String[] { "server" });
        }
      
        @Override
        public void initialize(Bootstrap<BlogConfiguration> bootstrap) {
            bootstrap.setName("blog");
        }
      
        @Override
        public void run(BlogConfiguration configuration, Environment environment) throws Exception {
            Mongo mongo = new Mongo(configuration.mongohost, configuration.mongoport);
            MongoManaged mongoManaged = new MongoManaged(mongo);
            environment.manage(mongoManaged);
      
            environment.addHealthCheck(new MongoHealthCheck(mongo));
      
            environment.addResource(new IndexResource());
        }
      
    }
    上面这段代码:
     
    使用BlogConfiguration对象创建了一个新的Mongo实例。
    一个新的MongoManaged实例被创建并添加到环境中。
    健康检查被添加。
    运行该应用程序作为主程序。你可以到本地的 http://localhost:8081/healthcheck 健康检查页面去检验MongoDB是否在运行,如果MongoDB没有运行,会看到一个异常堆栈跟踪。
     
    ! MongoDBHealthCheck: ERROR
    !  can't call something : Shekhars-MacBook-Pro.local/192.168.1.101:27017/admin
      
    com.mongodb.MongoException$Network: can't call something : Shekhars-MacBook-Pro.local/192.168.1.101:27017/admin
        at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:227)
        at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:305)
        at com.mongodb.DB.command(DB.java:160)
        at com.mongodb.DB.command(DB.java:183)
        at com.mongodb.Mongo.getDatabaseNames(Mongo.java:327)
        at com.shekhar.blog.MongoHealthCheck.check(MongoHealthCheck.java:17)
        at com.yammer.metrics.core.HealthCheck.execute(HealthCheck.java:195)
        at
    Caused by: java.io.IOException: couldn't connect to [Shekhars-MacBook-Pro.local/192.168.1.101:27017] bc:java.net.ConnectException: Connection refused
        at com.mongodb.DBPort._open(DBPort.java:228)
        at com.mongodb.DBPort.go(DBPort.java:112)
        at com.mongodb.DBPort.call(DBPort.java:79)
        at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:218)
        ... 33 more
      
    * deadlocks: OK
    现在启动MongoDB,可以看到:
     
    * MongoDBHealthCheck: OK
    * deadlocks: OK
     
     
    6、创建BlogResource
     
    现在写BlogResource类,它负责创建博客条目。
     
    import java.util.ArrayList;
    import java.util.List;
      
    import javax.validation.Valid;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
      
    import net.vz.mongodb.jackson.DBCursor;
    import net.vz.mongodb.jackson.JacksonDBCollection;
      
    import com.yammer.metrics.annotation.Timed;
      
    @Path("/blogs")
    @Produces(value = MediaType.APPLICATION_JSON)
    @Consumes(value = MediaType.APPLICATION_JSON)
    public class BlogResource {
      
        private JacksonDBCollection<Blog, String> collection;
      
        public BlogResource(JacksonDBCollection<Blog, String> blogs) {
            this.collection = blogs;
        }
      
        @POST
        @Timed
        public Response publishNewBlog(@Valid Blog blog) {
            collection.insert(blog);
            return Response.noContent().build();
        }
    }
    下一步,更新BlogService run方法,将BlogResource也加进来。
     
     @Override
        public void run(BlogConfiguration configuration, Environment environment) throws Exception {
            Mongo mongo = new Mongo(configuration.mongohost, configuration.mongoport);
            MongoManaged mongoManaged = new MongoManaged(mongo);
            environment.manage(mongoManaged);
      
            environment.addHealthCheck(new MongoHealthCheck(mongo));
      
            DB db = mongo.getDB(configuration.mongodb);
            JacksonDBCollection<Blog, String> blogs = JacksonDBCollection.wrap(db.getCollection("blogs"), Blog.class, String.class);
      
            environment.addResource(new IndexResource());
      
            environment.addResource(new BlogResource(blogs));
        }
    将BlogService类作为一个Java应用程序运行。为了测试BlogResource,做一个curl请求:
     
    $ curl -i -X POST -H "Content-Type: application/json" -d '{"title":"Day 12: OpenCV--Face Detection for Java Developers","url":"https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers"}' http://localhost:8080/blogs
      
      
    HTTP/1.1 204 No Content
    Date: Sun, 10 Nov 2013 14:08:03 GMT
    Content-Type: application/json
     
    7、更新IndexResource
     
    现在,更新IndexResource index()方法来从MongoDB获取所有的博客文件。
     
    import java.util.ArrayList;
    import java.util.List;
      
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
      
    import net.vz.mongodb.jackson.DBCursor;
    import net.vz.mongodb.jackson.JacksonDBCollection;
      
    import com.yammer.metrics.annotation.Timed;
      
    @Path("/")
    public class IndexResource {
      
        private JacksonDBCollection<Blog, String> collection;
      
        public IndexResource(JacksonDBCollection<Blog, String> blogs) {
            this.collection = blogs;
        }
      
        @GET
        @Produces(value = MediaType.APPLICATION_JSON)
        @Timed
        public List<Blog> index() {
            DBCursor<Blog> dbCursor = collection.find();
            List<Blog> blogs = new ArrayList<>();
            while (dbCursor.hasNext()) {
                Blog blog = dbCursor.next();
                blogs.add(blog);
            }
            return blogs;
        }
      
    }
    更新BlogService run方法将博客集合传递给IndexResource。
     
     @Override
        public void run(BlogConfiguration configuration, Environment environment) throws Exception {
            Mongo mongo = new Mongo(configuration.mongohost, configuration.mongoport);
            MongoManaged mongoManaged = new MongoManaged(mongo);
            environment.manage(mongoManaged);
      
            environment.addHealthCheck(new MongoHealthCheck(mongo));
      
            DB db = mongo.getDB(configuration.mongodb);
            JacksonDBCollection<Blog, String> blogs = JacksonDBCollection.wrap(db.getCollection("blogs"), Blog.class, String.class);
      
            environment.addResource(new IndexResource(blogs));
      
            environment.addResource(new BlogResource(blogs));
        }
    将BlogService类作为一个Java应用程序运行。为了测试BlogResource,做一个curl请求:
     
    $ curl http://localhost:8080
      
    [{"id":"527f9806300462bbd300687e","title":"Day 12: OpenCV--Face Detection for Java Developers","url":"https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers","publishedOn":1384093702592}]
     
     
    8、部署到云端
     
    这里有一篇文章,教你如何在OpenShift部署Dropwizard应用,打开http://dmly.github.io/blog/2013/05/01/diy-java-app-server-on-openshift-so-far-so-good/。
  • 相关阅读:
    中国石油昆仑加油卡
    157 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 02 异常内容简介
    156 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 01 Java常用工具类简介
    155 01 Android 零基础入门 02 Java面向对象 07 Java多态 07 多态知识总结 01 多态总结
    154 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 05 匿名内部类
    153 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 04 方法内部类
    152 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 03 静态内部类
    151 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 02 成员内部类
    150 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类概述 01 内部类概述
    149 01 Android 零基础入门 02 Java面向对象 07 Java多态 05 接口(重点)07 接口的继承
  • 原文地址:https://www.cnblogs.com/skyay/p/4347413.html
Copyright © 2011-2022 走看看