美文网首页
HI, Jersey - Restful webservice

HI, Jersey - Restful webservice

作者: 崔小妖 | 来源:发表于2017-11-03 11:07 被阅读0次

    一. 概念 rest

    全称 (Resource) REpresentational State Transfer (表现层状态转移)
    rest 描述的是 client 到 server的一种交互形式
    Resource 资源 代表了数据
    REpresentational 资源的表现形式 如json xml text...
    State 状态
    State Transfer 状态转变化 主要通过 http 的一系列操作实现

    二. 概念 restful

    restful 是API的一种设计风格,这个风格里面规定资源的操作CRUD(create, reach, update, delete)通过Http方法 post get put
    delete 来实现:

    rest http des
    create post 添加
    reach get 获取
    update put 更新
    delete delete 删除

    在restful 里面 万物皆资源,那要操作这些资源,怎么对这些资源进行定位呢? 答: 通过url.

    通常情况下 我们写url 如下

    method api des
    get api/getUser 获取用户
    post api/addUser 添加用户
    post api/updateUser 更新用户信息
    post api/deleteUser 删除用户

    这是不符合restful 风格的, rest 不建议在url 中使用动词如表格中的get/add...来表述你的意图

    那符合rest的url是什么样子的呢

    method api des
    get api/user 获取用户
    post api/user 添加用户
    put api/user 更新用户信息
    delete api/user 删除用户

    通俗点来讲就是 通过url就可以知道你想要的资源 通过http method就可以知道你想要的操作 通过http status 就可以知到操作的结果,并约束get 的操作不能改变资源的状态

    推荐使用名词复数来定义所有资源
    api/users  代替 api/user
    
    使用子资源来表达资源间的关系

    example: id 为12的用户下的所有订单

    api/users/12/orders  
    

    HATEOAS 约束

    HATEOAS(Hypermedia as the engine of application state) 一种比较复杂的约束,我们通常的做法是和服务器端约定好接口的定义,然后接口连接hardcode在本地 需要的时候调用,这种方式使客户端和服务器端的耦合加重,如果服务器端修改了接口定义,那么客户端也要跟着修改,在 HATEOAS 资源的uri都是动态的所以当接口定义发生改变时 客户端并不需要做任何的修改。
    example: 请求用户列表

    {
      "users": [
       {
        "id": "23",
        "name": "Stefan Jauker",
        "links": [
         {
         "rel": "self",
         "href": "/api/v1/users/23"
        }
       ]
      }
     ]
    }
    
    Tips:
    可以参考git接口定义
    https://developer.github.com/v3/git/commits/
    
    HATEOAS说明 
    https://en.wikipedia.org/wiki/HATEOAS 
    
    Http 状态码说明
    https://en.wikipedia.org/wiki/List_of_HTTP_status_codes 
    

    从上到下 我们已经涵盖了Rest 的四种成熟度, 下面我们来看一下什么是Rest 的成熟度模型
    1.第一个层次(Level 0)的 Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形式。SOAP 和 XML-RPC 都属于此类。

    Tips: RPC SOAP REST 对比
    https://www.cnblogs.com/bellkosmos/p/5213491.html
    

    2.第二个层次(Level 1)的 Web 服务引入了资源的概念。每个资源有对应的标识符和表达。
    3.第三个层次(Level 2)的 Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用 HTTP 状态码来表示不同的结果。如 HTTP GET 方法来获取资源,HTTP DELETE 方法来删除资源。
    4.第四个层次(Level 3)的 Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。

    talk is cheap show me the code

    ---------------------------------我是漂亮的分割线-----------------------------

    下面篇文章介绍怎样使用jersey 实现restful api
    遵循rest 风格的框架辣么多 为啥用jersey 呢?

    为啥要用jersey?
    因为简单呀 哇哈哈哈。。。。
    首先附上 restful api 设计指南
    http://www.ruanyifeng.com/blog/2014/05/restful_api.html

    首先介绍几个annotation:

    @GET @POST @PUT @ DELETE Http method
    @Path 标识路径url
    @Consumes 要求输入的数据类型 MediaType (application/json ...)
    @Produces 接口返回的数据类型 MediaType (同上)
    @PathParam 路径参数: /user /{param}
    @QueryParam get请求url 参数 /user?id=12
    @FormParam 表单参数

    以上是常用的几个注解, 下面开始讲实际操作
    准备好原料 eclipse/ tomcat /jersey libs

    一 新建web项目

    不会的找度娘

    二 将lib是里面的jar 包全部复制到 web-info lib & ext下, 对就是那么暴力 。。。
    image.png
    三 新建package

    例如 com.demo.api

    全局配置

    @ApplicationPath("/rest")
    public class RestResourceConfig extends ResourceConfig {
        
        public RestResourceConfig() {
            packages("com.rest.demo.resource");
            register(UserRest.class);
        }
    }
    
    

    或者通过 web.xml 中配置
    如果是基于web 3.0 新建的项目的话 是没有web.xml 的, 那么你需要新建一个web.xml 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>HiJersey</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
      </welcome-file-list>
      
        <servlet>
            <servlet-name>Way REST Service</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer
            </servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>com.demo.api</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Way REST Service</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    新建类

    
    @Path("/manager")
    public class ManagerResource {
    }
    

    这样就简单的暴露了 一个resource
    ps: @path 不是必须的, /不是必须的

    下面我们来实现一个简单的get service

    @GET 
    public String sayHi() {
        return "hi jersey";
    }
    

    run on server 打开浏览器访问

    http://localhost:8080/HiJersey/rest/manager
    

    可以看到结果

    image.png

    很简单有木有
    下面我们来实现稍微复杂一点的api

    1.get 请求 带路径参数和查询参数

    @GET
    @Path("/user/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User getUser(@PathParam("id") String id, @QueryParam("name") String name) {
            User user = new User(id, 18, name);
            return user;
    }
    

    注意 这边返回的是一个自定义类 那需要在User 类上注释@XmlRootElement 如下

    @XmlRootElement
    public class User implements Serializable{
    }
    

    同样可以返回 List & Map 类型的数据

    1. post 请求 接收对象参数
    @POST
    @Path("user")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public User addUser(User user) {
        return user;
    }
    
    1. post 接收表单数据
        @POST
        @Path("login")
        @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
        @Produces(MediaType.APPLICATION_JSON)
        public User login(MultivaluedMap<String, String> formParams) {
            User user = new User();
            user.setName(formParams.getFirst("name").toString());
            user.setPassword(formParams.getFirst("password").toString());
            
            return user;
        }
        
        @Path("login2")
        @POST
        @Produces(MediaType.APPLICATION_JSON)
        @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
        public User login(@FormParam("name") String name, @FormParam("password") String password) {
            User user = new User();
            user.setName(name);
            user.setPassword(password);
            return user;
        }
    

    put delete 方式传参和返回数据同上

    1. 文件上传
        @POST
        @Path("file")
        @Consumes({MediaType.MULTIPART_FORM_DATA})
        @Produces({MediaType.APPLICATION_JSON})
        public List<String>  upload(@Context HttpServletRequest request, @Context HttpServletResponse response) {
             String path = "D:"+File.separator+"imgs" + File.separator;
              return FileUtil.upload(path, request);
        }
    

    第二种方式 so easy

        @POST
        @Path("file2")
        @Consumes(MediaType.MULTIPART_FORM_DATA)
        public String upload2(
                @FormDataParam("file") InputStream input,
                @FormDataParam("file") FormDataContentDisposition d) {
            FileUtil.saveFile(input, "D:"+File.separator+"imgs" + File.separator+d.getFileName());
            return d.getFileName();
        }
    
    

    注意这种方式需要配置 xml 并且需要加入multipart 和 mimepull包

    <init-param>
      <param-name>jersey.config.server.provider.classnames</param-name>
      <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
    </init-param>
    

    *注意: form 要设置成enctype='multipart/form-data'

    5.获取所有路径参数 和查询参数

        @GET
        @Path("{version}")
        public String get(@Context UriInfo ui) {
            MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
            MultivaluedMap<String, String> pathPatams = ui.getPathParameters();
            for(String key : queryParams.keySet()) {
                System.out.println(key +"  " + queryParams.getFirst(key));
            }
            
            for(String key : pathPatams.keySet()) {
                System.out.println(key +"  " + pathPatams.getFirst(key));
            }
            return "success";
        }
    

    以上就是jersey 的最基础的用法 over

    点我 下载demo


    相关文章

      网友评论

          本文标题:HI, Jersey - Restful webservice

          本文链接:https://www.haomeiwen.com/subject/kdlapxtx.html