日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

用 Java 技术创建 RESTful Web 服务--转载

發(fā)布時(shí)間:2025/4/5 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用 Java 技术创建 RESTful Web 服务--转载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡介

JAX-RS (JSR-311) 是為 Java EE 環(huán)境下的 RESTful 服務(wù)能力提供的一種規(guī)范。它能提供對(duì)傳統(tǒng)的基于 SOAP 的 Web 服務(wù)的一種可行替代。

在本文中,了解 JAX-RS 的主要組件。本文用一個(gè)例子展示了一個(gè)企業(yè)如何使用 JAX-RS 內(nèi)的功能以一種 Restful 的方式公開員工的聯(lián)系信息。

背景

多年來,開發(fā)人員使用各種工具在其 Java 應(yīng)用程序內(nèi)創(chuàng)建 RESTful 服務(wù)。由于 REST 架構(gòu)的簡單性,主要需求 — 接收 HTTP 消息和頭部的能力 — 可以由一個(gè)簡單的 Java Web 容器實(shí)現(xiàn)。

Java servlets 常被用來開發(fā) RESTful 應(yīng)用程序。如何使用 servlet 并沒有固定的模式。通常,servlet 會(huì)接受請(qǐng)求并自己解析這個(gè) HTTP 請(qǐng)求 URI,以將此請(qǐng)求與一個(gè)已知資源相匹配。對(duì)于 REST 服務(wù)開發(fā),這個(gè)簡單的 servlet 模型以更為正式的 API 得到擴(kuò)展。但是,因?yàn)檫@些 API 是在 servlet 模型之上開發(fā)的,所以這些 API 中沒有一個(gè)是作為正式的標(biāo)準(zhǔn)開發(fā)的。

隨著 REST 越來越多地被采用為一種架構(gòu),Java Community Process (JCP) 計(jì)劃在未來的 Java Enterprise Edition 6 發(fā)布版中包括對(duì) REST 的正式支持。JSR-311 也已創(chuàng)建好,并已有了 JAX-RS 1.0 規(guī)范,提供了一種新的基于注釋的方式來開發(fā) RESTful 服務(wù)。與 servlet 模型相比,JAX-RS 注釋讓您能集中于您的資源和數(shù)據(jù)對(duì)象。并且,您不必再開發(fā)通訊層(通過 servlet)。

Java 資源

JAX-RS 建立了一種特殊的語言來描述資源,正如由其編程模型所表示的。有五種主要條目:根資源、子資源、資源方法、子資源方法以及子資源定位器。

根資源

根資源是由?@Path?注釋的 Java 類。@Path?注釋提供了一個(gè)?value?屬性,用來表明此資源所在的路徑。value?屬性可以是文本字符、變量或變量外加一個(gè)定制的正則表達(dá)式。清單 1 給出了一個(gè)例子。

清單 1. JAX-RS 根資源
package com.ibm.jaxrs.sample.organization;import javax.ws.rs.Path;@Path(value="/contacts") public class ContactsResource {... }

子資源

子資源是作為?subresource locator?調(diào)用的結(jié)果返回的 Java 類。它們類似于根資源,只不過它們不是由?@Path?注釋的,因它們的路徑是由子資源定位器給出的。子資源通常包含由 HTTP 請(qǐng)求方法指示符(designator)注釋的方法以便服務(wù)此請(qǐng)求。如果它們不包含如此注釋的方法,那么它們將會(huì)通過指派給合適的子資源定位器來進(jìn)一步解析此資源處理請(qǐng)求。

清單 2. JAX-RS 子資源
package com.ibm.jaxrs.sample.organization;import javax.ws.rs.GET;public class Department {@GETpublic String getDepartmentName() {...}}

如上所示的清單 2 展示了由?ContactsResource.getContactDepartment?方法返回的子資源。在這個(gè)例子中,如果一個(gè) HTTP GET 請(qǐng)求被發(fā)送給?/contact/{contactName}/department?路徑,那么?Department?子資源內(nèi)的?getDepartmentName?資源方法就會(huì)處理此請(qǐng)求。

資源方法

資源方法是根資源或子資源內(nèi)綁定到 HTTP 方法的 Java 方法。綁定是通過諸如?@GET?這樣的注釋完成的。

清單 3. JAX-RS 資源方法
package com.ibm.jaxrs.sample.organization;import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path;@Path(value="/contacts") public class ContactsResource {@GETpublic List<ContactInfo> getContacts() {...}}

在清單 3 的例子中,發(fā)送到?/contacts?路徑的 HTTP GET 請(qǐng)求將會(huì)由?getContacts()?資源方法處理。

子資源方法

子資源方法非常類似于資源方法;惟一的區(qū)別是子資源方法也是由?@Path?注釋的,此注釋進(jìn)一步限定了該方法的選擇。

清單 4. JAX-RS 子資源方法
package com.ibm.jaxrs.sample.organization;import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path;@Path(value="/contacts") public class ContactsResource {@GETpublic List<ContactInfo> getContacts() {...}@GET@Path(value="/ids")public List<String> getContactIds() {...}}

在清單 4 中,發(fā)送到?/contacts/ids?路徑的 HTTP GET 請(qǐng)求將會(huì)由?getContactIds()?子資源方法處理。

子資源定位器

子資源定位器是能進(jìn)一步解析用來處理給定請(qǐng)求的資源的一些方法。它們非常類似于子資源方法,因它們具備一個(gè)?@Path?注釋,但不具備 HTTP 請(qǐng)求方法指示符,比如?@GET?注釋。

清單 5. JAX-RS 子資源定位器
package com.ibm.jaxrs.sample.organization;import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam;@Path(value="/contacts") public class ContactsResource {@GETpublic List<ContactInfo> getContactss() {...}@GET@Path(value="/ids")public List<String> getContactIds() {...}@Path(value="/contact/{contactName}/department")public Department getContactDepartment(@PathParam(value="contactName") String contactName) {...}}

在上述例子中,對(duì)?/contact/{contactName}/department?路徑的任何 HTTP 請(qǐng)求都將由?getContactDepartment?子資源定位器處理。{contactName}?部分表明?contact?路徑部分之后可以是任何合法的 URL 值。

注釋

本節(jié)將會(huì)探討一些重要的注釋及其使用。對(duì)于由 JAX-RS 規(guī)范提供的注釋的完整列表,可以參考本文的?參考資料?部分給出的 JSR-311 鏈接。

@Path

@Path?注釋被用來描述根資源、子資源方法或子資源的位置。value?值可以包含文本字符、變量或具有定制正則表達(dá)式的變量。清單 6 的例子展示了?@Path?注釋的主要應(yīng)用。

清單 6. @Path 的使用
package com.ibm.jaxrs.sample.organization;import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam;@Path(value="/contacts") public class ContactsResource {@GET@Path(value="/{emailAddress:.+@.+\\.[a-z]+}")public ContactInfo getByEmailAddress(@PathParam(value="emailAddress") String emailAddress) {...}@GET@Path(value="/{lastName}")public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) {...} }

ContactsResource?類上的注釋表明對(duì)?/contacts?路徑的所有請(qǐng)求都將由?ContactsResource?根資源處理。getByEmailAddress?上的?@Path注釋則表明任何發(fā)送到?/contacts/{emailAddress}?的請(qǐng)求(其中?emailAddress?代表的是正則表達(dá)式?.+@.+\\.[a-z]+)都將由getByEmailAddress?處理。

getByLastName?方法上的?@Path?注釋指定了發(fā)送到?/contacts/{lastName}?路徑的所有請(qǐng)求(其中?lastName?代表的是一個(gè)與getByEmailAddress?內(nèi)的正則表達(dá)式不匹配的有效的 URL 部分)都將由?getByLastName?方法處理。

@GET、@POST、@PUT、@DELETE、@HEAD

@GET、@POST、@PUT、@DELETE 以及 @HEAD 均是 HTTP 請(qǐng)求方法指示符注釋。您可以使用它們來綁定根資源或子資源內(nèi)的 Java 方法與 HTTP 請(qǐng)求方法。HTTP GET 請(qǐng)求被映射到由 @GET 注釋的方法;HTTP POST 請(qǐng)求被映射到由 @POST 注釋的方法,以此類推。用戶可能還需要通過使用?@HttpMethod?注釋定義其自己的定制 HTTP 請(qǐng)求方法指示符。

清單 7. 定制的 HTTP 請(qǐng)求方法指示符注釋
package com.ibm.jaxrs.sample.organization;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;import javax.ws.rs.HttpMethod;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @HttpMethod("GET") public @interface CustomGET {}

上述的聲明定義了?@CustomGET?注釋。此注釋將具有與 @GET 注釋相同的語義值并可用在其位置上。

@Conumes 和 @Produces

@Consumes?注釋代表的是一個(gè)資源可以接受的 MIME 類型。@Produces?注釋代表的是一個(gè)資源可以返回的 MIME 類型。這些注釋均可在資源、資源方法、子資源方法、子資源定位器或子資源內(nèi)找到。

清單 8. @Consumes/@Produces
package com.ibm.jaxrs.sample.organization;import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces;@Path(value="/contacts") public class ContactsResource {@GET@Path(value="/{emailAddress:.+@.+\\.[a-z]+}")@Produces(value={"text/xml", "application/json"})public ContactInfo getByEmailAddress(@PathParam(value="emailAddress") String emailAddress) {...}@GET@Path(value="/{lastName}")@Produces(value="text/xml")public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) {...}@POST@Consumes(value={"text/xml", "application/json"})public void addContactInfo(ContactInfo contactInfo) {...} }

對(duì)于上述的?getByEmailAddress?和?addContactInfo?方法,它們均能處理?text/xml?和?application/json。被接受或返回的資源表示將依賴于客戶機(jī)設(shè)置的 HTTP 請(qǐng)求頭。@Consumes?注釋針對(duì)?Content-Type?請(qǐng)求頭進(jìn)行匹配,以決定方法是否能接受給定請(qǐng)求的內(nèi)容。

在清單 9 中,application/json?的?Content-Type?頭再加上對(duì)路徑?/contacts?的 POST,表明我們的?ContactsResource?類內(nèi)的addContactInfo?方法將會(huì)被調(diào)用以處理請(qǐng)求。

清單 9. Content-Type 頭部的使用
POST /contacts HTTP/1.1 Content-Type: application/json Content-Length: 32

相反地,@Produces?注釋被針對(duì)?Accept?請(qǐng)求頭進(jìn)行匹配以決定客戶機(jī)是否能夠處理由給定方法返回的表示。

清單 10. Accept 頭部的使用
GET /contacts/johndoe@us.ibm.com HTTP/1.1 Accept: application/json

在清單 10 中,對(duì) /contacts/johndoe@us.ibm.com 的?GET?請(qǐng)求表明了?getByEmailAddress?方法將會(huì)被調(diào)用并且返回的格式將會(huì)是application/json,而非 text/xml。

Providers

JAX-RS 提供程序是一些應(yīng)用程序組件,允許在三個(gè)關(guān)鍵領(lǐng)域進(jìn)行運(yùn)行時(shí)行為的定制:數(shù)據(jù)綁定、異常映射以及上下文解析(比如,向運(yùn)行時(shí)提供 JAXBContext 實(shí)例)。每個(gè) JAX-RS 提供程序類必須由?@Provider?注釋。如下的例子討論了兩個(gè)數(shù)據(jù)綁定提供程序?MessageBodyWriter?和MessageBodyReader。

MessageBodyWriter

MessageBodyWriters 被 JAX-RS 運(yùn)行時(shí)用來序列化所返回資源的表示。遵從 JSR-311 的運(yùn)行時(shí)提供了對(duì)常見類型(java.lang.String、java.io.InputStream、 JAXB 對(duì)象等)的本機(jī)支持,但用戶也可以向 JAX-RS 運(yùn)行時(shí)提供他或她自己的 MessageBodyWriter。比如,您可以提供一個(gè)定制?MessageBodyWriter?來處理定制?ContactInfo?Java 類型,如下所示。

清單 11. 定制 MessageBodyWriter
package com.ibm.jaxrs.sample.organization;import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider;@Provider @Produces("text/xml") public class ContactInfoWriter implements MessageBodyWriter<ContactInfo> {public long getSize(T t, java.lang.Class<ContactInfo> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType) {...}public boolean isWriteable(java.lang.Class<ContactInfo> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType) {return true;}public void writeTo(ContactInfo contactInfo, java.lang.Class<ContactInfo> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType, MultivaluedMap<java.lang.String, java.lang.Object> httpHeaders, java.io.OutputStream entityStream) {contactInfo.serialize(entityStream);} }

ContactInfoWriter?則在所返回的資源表示被序列化之前由 JAX-RS 運(yùn)行時(shí)調(diào)用。如果?isWriteable?返回 true 且?@Produces?是此資源方法的@Produces?值最為接近的匹配,就會(huì)調(diào)用?writeTo?方法。在這里,ContactInfoWriter?負(fù)責(zé)向底層的?OutputStream?序列化?ContactInfo?實(shí)例的內(nèi)容。

MessageBodyReader

MessageBodyReaders 則與 MessageBodyWriters 相反。對(duì)于反序列化,JAX-RS 運(yùn)行時(shí)支持與序列化相同的類型。用戶也可以提供他或她自己的 MessageBodyReader 實(shí)現(xiàn)。MessageBodyReader 的最主要的功能是讀取請(qǐng)求?InputStream?并將傳入的字節(jié)反序列化到一個(gè)此資源方法期望的 Java 對(duì)象。ContactInfo?類型的?MessageBodyReader?可以類似于清單 12。

清單 12. 定制 MessageBodyReader
package com.ibm.jaxrs.sample.organization;import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.Provider;@Provider @Consumes("text/xml") public class ContactInfoReader implements MessageBodyReader<ContactInfo> {public boolean isReadable(java.lang.Class<ContactInfo> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType) {return true;}public ContactInfo readFrom(java.lang.Class<ContactInfo> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType, MultivaluedMap<java.lang.String,java.lang.String> httpHeaders, java.io.InputStream entityStream) {return ContactInfo.parse(entityStream);}}

與 MessageBodyWriter?isWriteable?類似,ContactInfoReader?的?isReadable?方法將被調(diào)用以便決定 MessageBodyReader 能否處理此輸入。如果?isReadable?返回 true 且?@Consumes?值與此資源方法的?@Consumes?值最為匹配,就會(huì)選擇?ContactInfoReader。當(dāng)?readFrom?方法被調(diào)用時(shí),結(jié)果會(huì)是基于請(qǐng)求?InputStream?的內(nèi)容創(chuàng)建?ContactInfo?實(shí)例。

配置

至此,我們探討了 JAX-RS 資源類和一些提供程序類(MessageBodyReaders 和 MessageBodyWriters)。那么,該如何在 JAX-RS 運(yùn)行時(shí)內(nèi)配置這些類呢?這可以通過擴(kuò)展 javax.ws.rs.core.Application 類實(shí)現(xiàn)。此類提供了一組類或一組單例(singleton)對(duì)象實(shí)例,在一個(gè) JAX-RS 應(yīng)用程序內(nèi)包括所有的 根級(jí)別的資源和提供程序(由?@Provider?注釋的類)。若為這個(gè)示例聯(lián)系信息應(yīng)用程序擴(kuò)展這個(gè) Application 類,它應(yīng)該類似于清單 13。

清單 13. ContactInfoApplication
package com.ibm.jaxrs.sample.organization;import java.util.HashSet; import java.util.Set; import javax.ws.rs.core.Application;public class ContactInfoApplicaiton extends Application {public Set<Class<?>> getClasses() {Set<Class<?>> classes = new HashSetSet<Class<?>>();classes.add(ContactsResource.class);classes.add(ContactInfoWriter.class);classes.add(ContactInfoReader.class);}public SetSet<Object<?>> getSingletons() {// nothing to do, no singletons}}

getClasses?方法為 JAX-RS 運(yùn)行時(shí)提供了一組可用于元數(shù)據(jù)的類。請(qǐng)注意,getSingletons?方法什么都不返回。通常而言,將 JAX-RS 提供程序視為單例是沒有問題的,但將一個(gè) JAX-RS 資源視為單例則要格外謹(jǐn)慎。常被 JAX-RS 資源類使用的基于注釋的注入可能在一個(gè)單例實(shí)例的情況內(nèi)并不受支持。因此,除非仔細(xì)計(jì)劃,否則應(yīng)該避免使用 JAX-RS 資源的單例實(shí)例。

假設(shè),您正在一個(gè) servlet 容器內(nèi)部署一個(gè) JAX-RS 應(yīng)用程序,有兩種方法可以向 JAX-RS 運(yùn)行時(shí)注冊(cè)您的 javax.ws.rs.core.Application 子類。這是由 WAR 文件的 web.xml 處理的,如下所示。

清單 14. 不能感知 JAX-RS 的 servlet 容器
<web-app id="WebApp_ID" version="2.5"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><servlet><servlet-name>ContactInfoServlet</servlet-name><servlet-class>com.sample.RESTSystemServlet</servlet-class><init-param><param-name>javax.ws.rs.Application</param-name><param-value>com.ibm.jaxrs.sample.organization.ContactInfoApplication</param-value></init-param></servlet><servlet-mapping><servlet-name>ContactInfoServlet</servlet-name><url-pattern>/*</url-pattern></servlet-mapping> </web-app>

在一個(gè)被認(rèn)為是不能感知 JAX-RS 的 servlet 容器內(nèi),應(yīng)該作為 servlet 定義內(nèi)的 init-param 提供 Application 子類名。init-param 的名字必須是 javax.ws.rs.Application。servlet 類則很可能是 JAX-RS 運(yùn)行時(shí)系統(tǒng) servlet。您可以列出每個(gè)可能的 URL 模式,或者使用?/*?通配符注冊(cè),如下所示。

清單 15. 能感知 JAX-RS 的 servlet 容器
<web-app id="WebApp_ID" version="2.5"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><servlet><servlet-name>ContactInfoServlet</servlet-name><servlet-class>com.ibm.jaxrs.sample.organization.ContactInfoApplication</servlet-class></servlet><servlet-mapping><servlet-name>ContactInfoServlet</servlet-name><url-pattern>/*</url-pattern></servlet-mapping> </web-app>

在一個(gè)被認(rèn)為是能感知 JAX-RS 的 servlet 容器內(nèi),必須作為 servlet 定義內(nèi)的 servlet 類元素的值提供 Application 子類名。您仍然可以選擇是列出每個(gè)可能的 URL 模式還是使用?/*?通配符注冊(cè)。

以 Apache Wink 作為運(yùn)行時(shí)的 JAX-RS

下一步是找到一個(gè)能夠支持 JAX-RS 內(nèi)的可用功能的運(yùn)行時(shí)。Apache Wink 項(xiàng)目就提供了一個(gè)能滿足這種要求的運(yùn)行時(shí),具有上面所述的所有特性(參見?參考資料)。起初,Wink 是由開源社區(qū)的多個(gè)廠商和成員發(fā)起的一個(gè)協(xié)作項(xiàng)目。該項(xiàng)目的目的是提供最為靈活和輕量級(jí)的運(yùn)行時(shí)。

除了標(biāo)準(zhǔn) JAX-RS 特性之外,Wink 還提供了對(duì) JSON、Atom 和 RSS 序列化格式的增強(qiáng)支持。JAX-RS 本身并不提供客戶機(jī) API,但 Wink 包括了其對(duì)客戶機(jī) API 的自身模型,并且是完全以資源為中心的。

為了簡化基于 Wink 的服務(wù)的開發(fā),可以下載 Wink 1.0 庫并將它們作為默認(rèn) JAX-RS 庫包括到 Rational Application Developer (RAD) 7.5.5 開發(fā)環(huán)境(參見?參考資料)中。在這個(gè)更新版本中,RAD 添加了一個(gè) JAX-RS facet,可供您進(jìn)行配置以支持驗(yàn)證器和注釋幫助。這個(gè)新的 facet 還能通過自動(dòng)生成所需的 servlet 項(xiàng)和映射來簡化 servlet 的配置。

結(jié)束語

與傳統(tǒng)的 servlet 模型相比,JAX-RS 提供了一種可行的、更為簡便、移植性更好的方式來在 Java 內(nèi)實(shí)現(xiàn) RESTful 服務(wù)。使用注釋讓您能夠輕松提供 Java 資源的路徑位置并將 Java 方法綁定到 HTTP 請(qǐng)求方法。一種可移植的數(shù)據(jù)綁定架構(gòu)提供了一些本機(jī)的 Java 類型支持并允許進(jìn)行序列化/反序列化處理的完全定制。javax.ws.rs.core. Application 子類的擴(kuò)展以及 web.xml 內(nèi)的相應(yīng)清單表明了用最少的部署描述符配置就能進(jìn)行輕松部署。

本文只涉及了 JAX-RS 所能提供功能的一部分。就提供應(yīng)用程序上下文(比如 JAXBContext 實(shí)例)并將運(yùn)行時(shí)異常映射給 HTTP 請(qǐng)求而言,其他兩個(gè) JAX-RS 提供程序類型 ContextResolvers?和?ExceptionMappingProviders?還能提供對(duì)應(yīng)用程序組件的進(jìn)一步控制。注釋的定義是為了控制方法參數(shù)和類成員的注入,它們?cè)谶\(yùn)行時(shí)的整個(gè)過程向應(yīng)用程序提供了有價(jià)值的上下文信息。總的來說,JAX-RS 必將是一種面向基于 Java 的 RESTful 服務(wù)開發(fā)的簡便、可移植的、全面的 API。

原文地址:http://www.ibm.com/developerworks/cn/web/wa-jaxrs/index.html

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/4101767.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的用 Java 技术创建 RESTful Web 服务--转载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。