zoukankan      html  css  js  c++  java
  • Rest API By JAX-RS 实现接口发布

    原文地址:http://www.cnblogs.com/oopsguy/p/7503589.html

    JAX-RS

    我们在 JAX-RS 示例中使用相同的模型和 DAO,我们所需要做的只有更改 StormtroooperController 类的注解。

    由于 JAX-RS 是一个 API 规范,您需要选择一个实现,在本示例中,我们将使用 Jersey 作为实现。虽然可以创建一个没有直接依赖于特定 JAX-RS 实现的 JAX-RS 应用程序,但这将使得示例更加啰嗦。

    我选择 Jersey 有几个原因,主要是因为我可以不用绕圈子就可以轻松地获得简单的依赖注入,毕竟我们是把它在和 Spring 做对比。Apache Shiro 有一个示例,可在 JerseyRestEasyApache CXF 上运行相同的代码,如果你感兴趣不妨看一看。

    此示例与 Spring Boot 不同之处在于,它打包成 WAR,而 Spring Boot 是单个 JAR。此示例也可以打包进可执行的 jar 中,但此内容不在本文范围之内。

    在 JAX-RS 中与 SpringBootApplication 相当的是一个 Application 类。Jersey 的 Application 子类 ResourceConfig 添加了一些便捷的实用方法。以下代码配置 classpath 扫描以检测我们的各个资源类,并将 DefaultStormtrooperDao 实例绑定到 StromtrooperDao 接口。

    @ApplicationPath("/")
    public class JaxrsApp extends ResourceConfig {
    
        public JaxrsApp() {
    
            // scan the resources package for our resources
            packages(getClass().getPackage().getName() + ".resources");
    
            // use @Inject to bind the StormtrooperDao
            register(new AbstractBinder() {
                @Override
                protected void configure() {
                    bind(stormtrooperDao()).to(StormtrooperDao.class);
                }
            });
        }
    
        private StormtrooperDao stormtrooperDao() {
            return new DefaultStormtrooperDao();
        }
    }

    另外要指出的是,在上面的类中,@ApplicationPath 注解将这个类标记为一个 JAX-RS 应用程序并绑定到一个特定的 url 路径,这匹配了上面的 Spring 例子,我们只使用了根路径:/。资源包中检测到的每个资源都将被追加到该基本路径。

    JAX-RS 资源实现看起来非常类似于上述的 Spring 版本(重命名为 StormtroooperResource,以符合命名约定):

    @Path("/troopers")
    @Produces("application/json")
    public class StormtroooperResource {
    
        @Inject
        private StormtrooperDao trooperDao;
    
        @Path("/{id}")
        @GET
        public Stormtrooper getTrooper(@PathParam("id") String id) throws NotFoundException {
    
            Stormtrooper stormtrooper = trooperDao.getStormtrooper(id);
            if (stormtrooper == null) {
                throw new NotFoundException();
            }
            return stormtrooper;
        }
    
        @POST
        public Stormtrooper createTrooper(Stormtrooper trooper) {
            return trooperDao.addStormtrooper(trooper);
        }
    
        @Path("/{id}")
        @POST
        public Stormtrooper updateTrooper(@PathParam("id") String id,
                                          Stormtrooper updatedTrooper) throws NotFoundException {
            return trooperDao.updateStormtrooper(id, updatedTrooper);
        }
    
        @Path("/{id}")
        @DELETE
        public void deleteTrooper(@PathParam("id") String id) {
            trooperDao.deleteStormtrooper(id);
        }
    
        @GET
        public Collection<Stormtrooper> listTroopers() {
            return trooperDao.listStormtroopers();
        }
    }

    我们先来分解以下片段:

    @Path("/troopers")
    @Produces("application/json")
    public class StormtroooperResource {

    类似于上面的 Spring 示例,类级别上的 @Path 表示此类中的每个注解方法都将位于 /troopers 基本路径下。@Produces 注解定义了默认响应内容类型(除非被其他方法的注解所覆盖)。

    与 Spring 示例不同,其中 @RequestMapping 注解定义了请求的路径、方法和其他属性,在 JAX-RS 资源中,每个属性都使用单独的注解。与上述类似,如果我们分解了 updateTrooper() 方法:

    @Path("/{id}")
    @POST
    public Stormtrooper updateTrooper(@PathParam("id") String id,
                                      Stormtrooper updatedTrooper) throws NotFoundException {
        return trooperDao.updateStormtrooper(id, updatedTrooper);
    }

    我们看到 @Path("/{id}") 以及 @PathParam("id") 允许将路径的 id 部分转换为方法参数。与 Spring 示例不同的是,Stromtrooper 参数和返回值不需要额外的注解,由于此类上的 @Produces("application/json") 注解,它们将自动序列化/反序列化为 JSON。

    运行 JAX-RS 示例

    进入 Jersey 目录,使用 maven 命令:mvn jetty:run 运行此示例。

    发出与上述相同的两个请求,我们可以发出 GET 请求列出所有 trooper:

    $ curl http://localhost:8080/troopers
    
    HTTP/1.1 200 OK
    Content-Length: 3944
    Content-Type: application/json
    Date: Tue, 08 Nov 2016 21:57:55 GMT
    Server: Jetty(9.3.12.v20160915)
    
    [
        {
            "id": "FN-2187",
            "planetOfOrigin": "Unknown",
            "species": "Human",
            "type": "Basic"
        },
        {
            "id": "FN-0064",
            "planetOfOrigin": "Naboo",
            "species": "Nikto",
            "type": "Sand"
        },
        {
            "id": "FN-0069",
            "planetOfOrigin": "Hoth",
            "species": "Twi'lek",
            "type": "Basic"
        },
        {
            "id": "FN-0169",
            "planetOfOrigin": "Felucia",
            "species": "Kel Dor",
            "type": "Jump"
        },
    
        ...
    

    或者 GET 一个特定的资源:

    $ curl http://localhost:8080/troopers/FN-2187
    
    HTTP/1.1 200 OK
    Content-Length: 81
    Content-Type: application/json
    Date: Tue, 08 Nov 2016 22:00:02 GMT
    Server: Jetty(9.3.12.v20160915)
    
    {
        "id": "FN-2187",
        "planetOfOrigin": "Unknown",
        "species": "Human",
        "type": "Basic"
    }

    现在我们已经看到了基本相同的代码在 Spring 和 JAX-RS 应用程序中运行,只需更改注解即可。我更喜欢 JAX-RS 的注解,他们更简洁。既然如此,为什么要在两者选择呢?Jersey 和 RestEasy 都支持 Spring(以及 Guice 和 CDI/Weld)。让我们来创建一个结合了这两者的第三个例子。

    JAX-RS 与 Spring 整合

    针对此示例,我们需要三个类:Spring Boot 应用类、Jersey 配置类和我们的资源类。

    我们的 SpringBootAppStormtrooperResource 类与之前的版本相同,唯一的区别就是 Jersey 配置类:

    @Component
    public class JerseyConfig extends ResourceConfig {
    
        public JerseyConfig() {
    
            // scan the resources package for our resources
            packages(getClass().getPackage().getName() + ".resources");
        }
    }

    该类与之前的示例有点类似。首先,您可能注意到了用于标记此类由 Spring 管理的 `@Configuration 注解。剩下的就是指示 Jersey 再次扫描资源包,其余的都是您的处理逻辑。

    进入 spring-jaxrs 目录中,使用 mvn spring-boot:run 命令启动此示例。

    Spring 与 JAX-RS 对照表

    为了帮助您在 Spring 和 JAX-RS 的之间作出区分,这里给出了一份对照表。尽管不是很详尽,但它包含最常见的注解。

    Spring AnnotationJAX-RS Annotation
    @RequestMapping(path = "/troopers") @Path("/troopers")
    @PostMapping @POST
    @PutMapping @PUT
    @GetMapping @GET
    @DeleteMapping @DELETE
    @ResponseBody N/A
    @RequestBody N/A
    @PathVariable("id") @PathParam("id")
    @RequestParam("xyz") @QueryParam("xyz")
    @RequestParam(value="xyz") @FormParam("xyz")
    @RequestMapping(produces = {"application/json"}) @Produces("application/json")
    @RequestMapping(consumes = {"application/json"}) @Consumes("application/json")

    何时在 Spring 上使用 JAX-RS?

    在我看来,它应该这样分解:

    如果你已经是一个 Spring 用户,就使用 Spring 吧。如果你正在创建一个对象 JSON/XML REST 层,那么您选择的 DI 框架(如 Spring、Guice 等)支持 JAX-RS 资源可能是一个不错的选择。服务器端渲染页面并不是 JAX-RS 规范的一部分(虽然它是扩展支持的)。我曾在 Jersey 中使用了 Thymeleaf 视图,但我认这是 Spring MVC 该做的。

    目前为止,我们还没有把 Spring Boot 应用程序与 WAR 打包的应用程序进行详细地对比。Dropwizard(使用嵌入式 Jetty 容器和 Jersey)可能是与 Spring Boot 应用程序最接近的。希望这篇文章能给你带来一些灵感,您可以做自己的对比。如果您有任何问题,欢迎 Twitter @briandemers!

    示例代码

    https://github.com/oktadeveloper/jaxrs-spring-blog-example

  • 相关阅读:
    关于${pageContext.request.contextPath}的理解
    Spring中的八大设计模式
    mybatis pagehelper分页插件使用
    什么是JavaConfig
    springboot优缺点
    Redis持久化的两种方式和配置
    未能加载文件或程序集“System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。
    关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案
    C#关于微信昵称中存在的表情图标乱码解决
    移动端调用相机拍照上传图片
  • 原文地址:https://www.cnblogs.com/boonya/p/7504523.html
Copyright © 2011-2022 走看看