<b>2.5 處理響應</b>
rest的響應處理結果應包括響應頭中http狀态碼,響應實體中媒體參數類型和傳回值類型,以及異常情況處理。jax-rs2支援4種傳回值類型的響應,分别是無傳回值、傳回response類執行個體、傳回genericentity類執行個體和傳回自定義類執行個體。如下,逐一講述這4種傳回值類型。
閱讀指南
本節示例源代碼位址:https://github.com/feuyeux/jax-rs2-guide-ii/tree/master/2.simple-service-3。
相關包:com.example.response。
<b>2.5.1 傳回類型</b>
1. void
在傳回值類型是void的響應中,其響應實體為空,http狀态碼為204。在前面的delete方法講述中已經介紹過,再來看一下這種類型的資源方法。
@delete
@path("{s}")
//關注點1:無傳回值的delete方法
public void
delete(@pathparam("s") final string s) {
logger.debug(s);
}
因為delete操作無須傳回更多的關于資源表述的資訊,是以該方法沒有傳回值,即傳回值類型為void,見關注點1。
2. response
在傳回值類型為response的響應中,響應實體為response類的entity()方法定義的實體類執行個體。如果該内容為空,則http狀态碼為204,否則http狀态碼為200 ok,示例代碼如下。
@post
@path("c")
public response get(final string s) {
//response.nocontent().build();
//關注點1:建構無傳回值的響應執行個體
return response.ok().entity("char[]:" + s).build();
在這段代碼中,response首先定義了http的狀态碼為ok,然後填充實體資訊,最後調用build()方法建構response執行個體,見關注點1。
3. genericentity
通用實體類型作為傳回值的情況并不常用。其形式是構造一個統一的實體執行個體并将其傳回,實體執行個體作為第一個參數、該實體類型作為第二個參數,示例代碼如下。
@path("b")
public string get(final byte[] bs) {
for (final byte b : bs) {
logger.debug(b);
}
return "byte[]:" + new string(bs);
/*
public genericentity<string>
get(final byte[] bs) {
//關注點1:建構genericentity執行個體
return new genericentity<string>("byte[]:" + new
string(bs), string.class);
*/
在這段代碼中,genericentity的第一個是由byte數組執行個體作為參數建構的字元串執行個體,第二個參數是字元串類,見關注點1。
4. 自定義類型
jdk中的類(比如file、string等)都可以作為傳回值類型,更常用的是傳回自定義的pojo類型,前述多個例子就是這樣做的,再來看一個示例。
@path("f")
//關注點1:get方法的傳回類型為file
public file get(final file f) throws
filenotfoundexception, ioexception {
try (bufferedreader br = new bufferedreader(new filereader(f))) {
string s;
do {
s = br.readline();
} while (s != null);
return f;
@consumes({mediatype.application_xml,mediatype.application_json})
@produces(mediatype.application_xml)
//關注點2:post方法的傳回值是自定義類book
public book getentity(book book) {
logger.debug(book.getbookname());
return book;
//關注點3:post方法的傳回值是自定義類book
public book
getentity(jaxbelement<book> bookelement) {
book book = bookelement.getvalue();
在這段代碼中,傳回值類型有來自jdk的file類型,見關注點1,也有自定義的pojo類型,見關注點2和關注點3。
<b>2.5.2 處理異常</b>
實作rest的資源方法時應使其具有良好的異常處理能力,這包括異常的定義和錯誤狀态碼的正确傳回。
1. 處理狀态碼
首先通過表2-7了解下rest中常用的http狀态碼,應當在處理異常的同時,為rest請求的用戶端提供對應的錯誤碼。
表2-7 http常用狀态碼清單
狀态碼 含 義
200 ok 伺服器正常響應
201 created 建立新實體,響應頭location指定通路該實體的url
202 accepted 伺服器接受請求,處理尚未完成。可用于異步處理機制
204 no content 伺服器正常響應,但響應實體為空
301 moved permanently 請求資源的位址發生永久變動,響應頭location指定新的url
302 found 請求資源的位址發生臨時變動
304 not modified 用戶端緩存資源依然有效
400 bad request 請求資訊出現文法錯誤
401 unauthorized 請求資源無法授權給未驗證使用者
403 forbidden 請求資源未授權目前使用者
404 not found 請求資源不存在
405 method not allowed 請求方法不比對
406 not acceptable 請求資源的媒體類型不比對
500 internal server error 伺服器内部錯誤,意外終止響應
501 not implemented 伺服器不支援目前請求
jax-rs2規定的rest式的web服務的基本異常類型為運作時異常webapplicationexception類。該類包含3個主要的子類分别對應如下内容。
http狀态碼為3xx的重定向類redirectionexception;
http狀态碼為4xx的請求錯誤類clienterrorexception;
http狀态碼為5xx的伺服器錯誤類servererrorexception。
它們各自的子類對照http狀态碼再細分,比如常見的http狀态碼404錯誤,對應的錯誤類為notfoundexception,如圖2-4所示。
除了jersey提供的标準異常類型,我們也可以根據業務需要自定義相關的業務異常類,示例如下。
//關注點1:定義webapplicationexception接口實作類
public class jaxrs2guidenotfoundexception
extends webapplicationexception {
public jaxrs2guidenotfoundexception() {
//關注點2:定義http狀态
super(javax.ws.rs.core.response.status.not_found);
public jaxrs2guidenotfoundexception(string message) {
super(message);
在這段代碼中,jaxrs2guidenotfoundexception類繼承自jax-rs2的webapplication-exception類,見關注點1。其預設構造子提供了http狀态碼,其值為response.status.not_found,見關注點2。
圖2-4 jersey定義的異常類型
2. exceptionmapper
jersey架構為我們提供了更為通用的異常處理方式。通過實作exceptionmapper接口并使用@provider注解将其定義為一個provider,可以實作通用的異常的面向切面處理,而非針對某一個資源方法的異常處理,示例如下。
@provider
public class entitynotfoundmapper
implements
exceptionmapper<jaxrs2guidenotfoundexception>{
//關注點1:定義exceptionmapper接口實作類
@override
public response toresponse(final jaxrs2guidenotfoundexception ex) {
//關注點2:攔截并傳回新的響應執行個體
return response.status(404).entity(ex.getmessage()).type("text/plain").build();
在這段代碼中,entitynotfoundmapper實作了exceptionmapper接口,并提供了泛型類型為前述剛定義的jaxrs2guidenotfoundexception類,見關注點1;當響應中發生了jaxrs2guidenotfoundexception類型的異常,響應流程就會被攔截并補充http狀态碼和異常消息,以文本作為媒體格式傳回給用戶端,見關注點2。