HI, Jersey - Restful webservice

一. 概念 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下, 对就是那么暴力 。。。
HI, Jersey - Restful webservice_第1张图片
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 文件



  HiJersey
  
    index.html
  
  
    
        Way REST Service
        org.glassfish.jersey.servlet.ServletContainer
        
        
            jersey.config.server.provider.packages
            com.demo.api
        
        1
    
    
        Way REST Service
        /rest/*
    

新建类


@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

可以看到结果

HI, Jersey - Restful webservice_第2张图片
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 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  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包


  jersey.config.server.provider.classnames
  org.glassfish.jersey.media.multipart.MultiPartFeature

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

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

    @GET
    @Path("{version}")
    public String get(@Context UriInfo ui) {
        MultivaluedMap queryParams = ui.getQueryParameters();
        MultivaluedMap 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)