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
聯合使用,查詢參數在請求中如果不存在,List
、Set
或者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) {
//
}