REST+Jersey学习笔记(二)--根资源及注解

时间:2022-09-27 13:14:03

Jersey的依赖

一个使用 Jersey 的应用,依赖于 Jersey 的模块,但是如果使用了第三方模块,那么 Jersey可能反过来依赖第三方模块。Jersey 是插件化的组件结构,所以不同的应用可能依赖不同的
模块。

基于 Servlet 的 GlassFish 应用

使用 GlassFish 应用服务,不需要打包任何东西,所有的一切都已经包含在其中了。只需要在应用中声明依赖使用 JAX-RS API 即可。


JAX-RS应用,资源和子资源

Root Resource Classes 根资源类

Root Resource Classes 是带有 @PATH 注解的,包含至少一个 @PATH 注解的方法或者方法带有 @GET、@PUT、 @POST、 @DELETE 资源方法指示器的 POJO。资源方法是带有资源方法指示器(resource method designator)注解的方法。

使用 Java对象内的注解创建一个 Jersey 的 RESTful 服务。
为了项目更加清晰,建立net.huadong.idev.tpl.privilege.lhy.entity包,在该包下面创建一个对象 Cadets:

package net.huadong.idev.tpl.privilege.lhy.entity;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;

/** * Cadets实体类 * @author liuhuiyan * */
@Entity
@Table(name = "CADETS_TEST_TABLE", catalog = "", schema = "IDEV7")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Cadets.findAll", query = "SELECT c FROM Cadets c")
    , @NamedQuery(name = "Cadets.findByCadetName", query = "SELECT c FROM Cadets c WHERE c.cadetName = :cadetName")
    , @NamedQuery(name = "Cadets.findByCadetBirth", query = "SELECT c FROM Cadets c WHERE c.cadetBirth = :cadetBirth")
    , @NamedQuery(name = "Cadets.findByCadetAge", query = "SELECT c FROM Cadets c WHERE c.cadetAge = :cadetAge")
    , @NamedQuery(name = "Cadets.findByCadetDate", query = "SELECT c FROM Cadets c WHERE c.cadetDate = :cadetDate")
    , @NamedQuery(name = "Cadets.findByCadetSchool", query = "SELECT c FROM Cadets c WHERE c.cadetSchool = :cadetSchool")
    , @NamedQuery(name = "Cadets.findByCadetSal", query = "SELECT c FROM Cadets c WHERE c.cadetSal = :cadetSal")
    , @NamedQuery(name = "Cadets.findByCadetDept", query = "SELECT c FROM Cadets c WHERE c.cadetDept = :cadetDept")
    , @NamedQuery(name = "Cadets.findByCadetId", query = "SELECT c FROM Cadets c WHERE c.cadetId = :cadetId")})
public class Cadets implements Serializable {

    private static final long serialVersionUID = 1L;
    @Basic(optional = false)
    @Column(name = "CADET_NAME", nullable = false, length = 20)
    private String cadetName;
    @Basic(optional = false)
    @Lob
    @Column(name = "CADET_SEX", nullable = false)
    private String cadetSex;
    @Basic(optional = false)
    @Column(name = "CADET_BIRTH", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date cadetBirth;
    @Basic(optional = false)
    @Column(name = "CADET_AGE", nullable = false)
    private BigInteger cadetAge;
    @Column(name = "CADET_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date cadetDate;
    @Basic(optional = false)
    @Column(name = "CADET_SCHOOL", nullable = false, length = 20)
    private String cadetSchool;
    @Basic(optional = false)
    @Column(name = "CADET_SAL", nullable = false)
    private BigInteger cadetSal;
    @Basic(optional = false)
    @Column(name = "CADET_DEPT", nullable = false, length = 20)
    private String cadetDept;
    @Id
    @Basic(optional = false)
    @Column(name = "CADET_ID", nullable = false, length = 36)
    private String cadetId;

    public Cadets() {
    }

    public Cadets(String cadetId) {
        this.cadetId = cadetId;
    }

    public Cadets(String cadetId, String cadetName, String cadetSex, Date cadetBirth, BigInteger cadetAge, String cadetSchool, BigInteger cadetSal, String cadetDept) {
        this.cadetId = cadetId;
        this.cadetName = cadetName;
        this.cadetSex = cadetSex;
        this.cadetBirth = cadetBirth;
        this.cadetAge = cadetAge;
        this.cadetSchool = cadetSchool;
        this.cadetSal = cadetSal;
        this.cadetDept = cadetDept;
    }

    public String getCadetName() {
        return cadetName;
    }

    public void setCadetName(String cadetName) {
        this.cadetName = cadetName;
    }

    public Object getCadetSex() {
        return cadetSex;
    }

    public void setCadetSex(String cadetSex) {
        this.cadetSex = cadetSex;
    }

    public Date getCadetBirth() {
        return cadetBirth;
    }

    public void setCadetBirth(Date cadetBirth) {
        this.cadetBirth = cadetBirth;
    }

    public BigInteger getCadetAge() {
        return cadetAge;
    }

    public void setCadetAge(BigInteger cadetAge) {
        this.cadetAge = cadetAge;
    }

    public Date getCadetDate() {
        return cadetDate;
    }

    public void setCadetDate(Date cadetDate) {
        this.cadetDate = cadetDate;
    }

    public String getCadetSchool() {
        return cadetSchool;
    }

    public void setCadetSchool(String cadetSchool) {
        this.cadetSchool = cadetSchool;
    }

    public BigInteger getCadetSal() {
        return cadetSal;
    }

    public void setCadetSal(BigInteger cadetSal) {
        this.cadetSal = cadetSal;
    }

    public String getCadetDept() {
        return cadetDept;
    }

    public void setCadetDept(String cadetDept) {
        this.cadetDept = cadetDept;
    }

    public String getCadetId() {
        return cadetId;
    }

    public void setCadetId(String cadetId) {
        this.cadetId = cadetId;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (cadetId != null ? cadetId.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Cadets)) {
            return false;
        }
        Cadets other = (Cadets) object;
        if ((this.cadetId == null && other.cadetId != null) || (this.cadetId != null && !this.cadetId.equals(other.cadetId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "javaapplication4.Cadets[ cadetId=" + cadetId + " ]";
    }

}

拓展:POJO

POJO(Plain Ordinary Java Object)简单的Java对象,方便使用数据库中的数据表,可以方便的将POJO类当做对象来进行使用,也可以方便的调用其get,set方法。

  • POJO中有一些属性及其getter setter方法的类

  • 没有业务逻辑

  • 不允许有业务方法,也不能携带有connection之类的方法

POJO对象也被称为Data对象,应用于表现现实中的对象。


JSON 处理

我们想把这个Cadets对象返回给客户端,在net.huadong.idev.tpl.privilege.lhy.resources 资源下,写了:

package net.huadong.idev.tpl.privilege.lhy.resources;

@Path("login/lhy")
public class CadetsResource extends HdAbstractResource<CadetsFacade> {

    // 初始化上下文环境,获得系统的相关信息
    @Context
    private UriInfo context;

    /* 构造函数 */
    public CadetsResource() {
        super(Constants.HD_PRIVILEGE_EJB_URI, CadetsFacade.class);
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("find")
    public Response ezuiFind(HdEzuiQueryParams params) {
        return super.find(params);
    }
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("save")
    public Response ezuiSave(HdEzuiSaveDatagridData<Cadets> menu) {
        List<Cadets> insertRows = menu.getInsertedRows();
        for (Cadets entity : insertRows) {

        }
        List<Cadets> updateRows = menu.getUpdatedRows();
        for (Cadets entity : updateRows) {

        }
        return super.save(menu, SecurityUtils.getSubject().getPrincipal().toString());
    }
    /** * 刷新参数缓存 * @return */
    @GET
    @Path("flush")
    public Response flushCache() {
        SysParamsHelper.flush();
        return Response.ok().build();
    }

}

JAX-RS 里面的几个注解

- @Path

    URI的相对路径。

上面设置的是本地的 URI的@Path(“login/lhy”) 。

URI 的路径模版是由 URIs 和嵌入 URI 语法的变量组成

变量在运行时将会被匹配到的 URI的那部分多代替。比如:

@Path("/users/{username}")

按照这个例子,一个用户就能会方便的填写他的名字,那么 Jersey 服务器也会按照这个UIR 路径模板响应到这个请求。
例如:用户输入了名字“lhy”,那么服务器就会响应

http://example.com/users/lhy

指定的URI路径参数
为了接收到用户名变量,@PathParam 用在接收请求的方法的参数上,例如:

@Path("/users/{username}")
public class UserResource {
    @GET
    @Produces("text/xml")
    public String getUser(@PathParam("username") String userName) {
...
}
}

它规定匹配正则表达式式要精确到大小写的,如果填写的话会覆盖默认的表达式 [^/]+?

例如

@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")

这个正则表达式匹配由大小写字符、横杠和数字组成的字符串,如果正则校验不通过,则返回 404 (没有找到资源)。

  • 一个 @Path的内容是否以”/”开头都没有区别
  • 同样是否以”/”结尾也没有什么区别

@GET, @PUT, @POST, @DELETE(HTTP 方法)

  • @GET
  • @PUT
  • @POST
  • @DELETE
  • @HEAD

是JAX-RS 定义的注解,非常类似与 HTTP的方法名。

@Produces

@Produces是定义返回值给客户端的 MIME 媒体类型。

CadetsResource里面,将会返回一个对应于MediaType.APPLICATION_XML 的 MIME 媒体类型,意思是以 JSON 形式将对象返回给客户端。

  • @Produces 既可以应用在类上,也可以作用于方法 上。

  • 方法水平层面的@Produces 会覆盖类层面的@Produces

如果一个资源类是能够生产多个 MIME 媒体类型,资源的方法的响应将会对应对于客户端来说最可接受的媒体类型。

HTTP 请求头部宣布接受什么是最容易被接受的

@Produces 可以定义多个返回类型,比如:

@GET
@Produces({"application/xml", "application/json"})
public String doGetAsXmlOrJson() {
...
}
  • 无论 application/xml 或者 application/json 哪个匹配上了,都会执行 doGetAsXmlOrJson
  • 如果两个都匹配了,那么会选择首先匹配的那个

@Consumes

用来指定表示可由资源消耗的 MIME 媒体类型。
  • @Consumes既可以应用在类的水平上
  • 也可以作用与方法的水平,声明可以不止一种类型

Parameter Annotations (@*Param) 参数注解

资源方法中,带有基于参数注解的参数可以从请求中获取信息。
  • 查询参数
    • @PathParam 来获取 URL 请求中的路径参数
    • @QueryParam 用于从请求 URL 的查询组件中提取查询参数
@Path("smooth")
@GET
public Response smooth(
@DefaultValue("2") @QueryParam("step") int step,
@DefaultValue("true") @QueryParam("min-m") boolean hasMin,
@DefaultValue("true") @QueryParam("max-m") boolean hasMax,
@DefaultValue("true") @QueryParam("last-m") boolean hasLast,
@DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
@DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
@DefaultValue("red") @QueryParam("last-color") ColorParam lastColor) {
...
}
  • 如果 @DefaultValue不与 @QueryParam联合使用,查询参数在请求中如果不存在,ListSet 或者 SortedSet 类型将会是空值集合,对象类型将为空,Java 的定义默认为原始类型

  • @PathParam 和其他参数注解

    • @MatrixParam@HeaderParam@CookieParam@FormParam遵循与@QueryParam一样的规则

      • @MatrixParam 从 URL 路径提取信息。

      • @HeaderParam 从 HTTP 头部提取信息。

      • @CookieParam从关联在 HTTP 头部的 cookies 里提取信息

HTML表格处理

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(@FormParam("name") String name) {

}

从查询参数或者路径获取 Map

@GET
public String get(@Context UriInfo ui) {
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
MultivaluedMap<String, String> pathParams = ui.getPathParameters();
}

header 和 cookie 参数用法

  • 从头部参数获取 Map

        @Context 一般可以用于获得一个Java类型关联请求或响应的上下文。
    
@GET
public String get(@Context HttpHeaders hh) {
MultivaluedMap<String, String> headerParams = hh.getRequestHeaders();
Map<String, Cookie> pathParams = hh.getCookies();
}
  • form 表单参数 获取 Map

    因为 form 表单参数(不像其他消息的一部分)是实体,就是说,不需要@Context注解。
    
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// 
}