Cara mengakses parameter dalam metode POST RESTful

123

Metode POST saya terlihat seperti ini:

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String param1, String param2){
    System.out.println("param1 = " + param1);
    System.out.println("param2 = " + param2);
}

Ketika saya membuat Klien Jersey di Netbeans, metode yang memanggil metode posting terlihat seperti ini:

public void create(Object requestEntity){
    webResource.path("create").type(MediaType.APPLICATION_JSON).post(requestEntity);
}

Saat menjalankan tes ini:

@Test
public void hello(){
    String json = "{param1=\"hello\",param2=\"hello2\"}";
    this.client.create(json);
}

Ini memberikan output berikut di server:

INFO: param1 = {param1="hello",param2="hello2"}
INFO: param2 = 

Apa yang harus saya ubah agar parameter memberikan nilai yang benar?

Klaasvaak
sumber
apakah Anda menggunakan ini di aplikasi android atau tidak?
Android-Droid
Saya akhirnya ingin memanggil metode posting ini di aplikasi android. Entah bagaimana layanan web tidak tahu cara menandatangani nilai ke parameter. Saya ingin tahu bagaimana melakukan ini.
Klaasvaak

Jawaban:

356

@POSTMetode Anda harus menerima objek JSON, bukan string. Jersey menggunakan JAXB untuk mendukung marshaling dan unmarshaling objek JSON (lihat dokumentasi jersey untuk detailnya ). Buat kelas seperti:

@XmlRootElement
public class MyJaxBean {
    @XmlElement public String param1;
    @XmlElement public String param2;
}

Kemudian Anda @POST metode akan terlihat seperti berikut:

@POST @Consumes("application/json")
@Path("/create")
public void create(final MyJaxBean input) {
    System.out.println("param1 = " + input.param1);
    System.out.println("param2 = " + input.param2);
}

Metode ini mengharapkan untuk menerima objek JSON sebagai badan HTTP POST. JAX-RS meneruskan isi pesan HTTP sebagai parameter tanpa pemberitahuan - inputdalam hal ini. Pesan sebenarnya akan terlihat seperti ini:

POST /create HTTP/1.1
Content-Type: application/json
Content-Length: 35
Host: www.example.com

{"param1":"hello","param2":"world"}

Menggunakan JSON dengan cara ini cukup umum karena alasan yang jelas. Namun, jika Anda membuat atau mengkonsumsinya dalam sesuatu selain JavaScript, maka Anda harus berhati-hati untuk keluar dari data dengan benar. Di JAX-RS, Anda akan menggunakan MessageBodyReader dan MessageBodyWriter untuk mengimplementasikan ini. Saya percaya bahwa Jersey sudah memiliki implementasi untuk tipe yang dibutuhkan (misalnya, Java primitif dan kelas yang dibungkus JAXB) serta untuk JSON. JAX-RS mendukung sejumlah metode lain untuk meneruskan data. Ini tidak memerlukan pembuatan kelas baru karena data diteruskan menggunakan penerusan argumen sederhana.


HTML <FORM>

Parameter akan dianotasi menggunakan @FormParam :

@POST
@Path("/create")
public void create(@FormParam("param1") String param1,
                   @FormParam("param2") String param2) {
    ...
}

Browser akan menyandikan formulir menggunakan "application / x-www-form-urlencoded" . Runtime JAX-RS akan menangani decoding tubuh dan meneruskannya ke metode. Inilah yang harus Anda lihat di kawat:

POST /create HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 25

param1=hello&param2=world

Konten tersebut dikodekan URL kasus ini, .

Jika Anda tidak mengetahui nama FormParam, Anda dapat melakukan hal berikut:

@POST @Consumes("application/x-www-form-urlencoded")
@Path("/create")
public void create(final MultivaluedMap<String, String> formParams) {
    ...
}

Header HTTP

Anda dapat menggunakan anotasi @HeaderParam jika Anda ingin meneruskan parameter melalui header HTTP:

@POST
@Path("/create")
public void create(@HeaderParam("param1") String param1,
                   @HeaderParam("param2") String param2) {
    ...
}

Seperti inilah tampilan pesan HTTPnya. Perhatikan bahwa POST ini tidak memiliki badan.

POST /create HTTP/1.1
Content-Length: 0
Host: www.example.com
param1: hello
param2: world

Saya tidak akan menggunakan metode ini untuk melewatkan parameter umum. Ini sangat berguna jika Anda perlu mengakses nilai dari header HTTP tertentu.


Parameter Kueri HTTP

Metode ini terutama digunakan dengan HTTP GET tetapi juga berlaku untuk POST. Ini menggunakan anotasi @QueryParam .

@POST
@Path("/create")
public void create(@QueryParam("param1") String param1,
                   @QueryParam("param2") String param2) {
    ...
}

Seperti teknik sebelumnya, meneruskan parameter melalui string kueri tidak memerlukan badan pesan. Inilah pesan HTTPnya:

POST /create?param1=hello&param2=world HTTP/1.1
Content-Length: 0
Host: www.example.com

Anda harus sangat berhati-hati untuk mengenkode parameter kueri dengan benar di sisi klien. Penggunaan parameter kueri dapat menimbulkan masalah karena batasan panjang URL yang diberlakukan oleh beberapa proxy serta masalah yang terkait dengan pengkodeannya.


Parameter Jalur HTTP

Parameter jalur mirip dengan parameter kueri kecuali bahwa parameter tersebut disematkan di jalur sumber daya HTTP. Metode ini tampaknya disukai hari ini. Ada dampak sehubungan dengan cache HTTP karena jalur itulah yang sebenarnya mendefinisikan sumber daya HTTP. Kode terlihat sedikit berbeda dari yang lain karena anotasi @Path diubah dan menggunakan @PathParam :

@POST
@Path("/create/{param1}/{param2}")
public void create(@PathParam("param1") String param1,
                   @PathParam("param2") String param2) {
    ...
}

Pesan ini mirip dengan versi parameter kueri kecuali bahwa nama parameter tidak disertakan di mana pun dalam pesan.

POST /create/hello/world HTTP/1.1
Content-Length: 0
Host: www.example.com

Metode ini berbagi kesengsaraan encoding yang sama dengan versi parameter kueri. Segmen jalur dikodekan secara berbeda sehingga Anda juga harus berhati-hati di sana.


Seperti yang Anda lihat, ada pro dan kontra untuk setiap metode. Pilihan biasanya ditentukan oleh klien Anda. Jika Anda melayani FORMhalaman HTML berbasis, maka gunakan @FormParam. Jika klien Anda berbasis JavaScript + HTML5, Anda mungkin ingin menggunakan serialisasi berbasis JAXB dan objek JSON. The MessageBodyReader/Writerimplementasi harus mengurus yang diperlukan melarikan diri untuk Anda sehingga adalah satu hal sedikit yang bisa salah. Jika klien Anda berbasis Java tetapi tidak memiliki prosesor XML yang baik (misalnya, Android), saya mungkin akan menggunakanFORM pengkodean karena badan konten lebih mudah untuk dibuat dan dikodekan dengan benar daripada URL. Semoga entri wiki-mini ini menjelaskan beberapa metode yang didukung JAX-RS.

Catatan: untuk kepentingan pengungkapan penuh, saya belum benar-benar menggunakan fitur Jersey ini. Kami mengotak-atiknya karena kami memiliki sejumlah aplikasi JAXB + JAX-RS yang diterapkan dan pindah ke ruang klien seluler. JSON jauh lebih cocok daripada XML pada solusi berbasis HTML5 atau jQuery.

D. Shawley
sumber
4
Saya telah menguji fitur ini kemarin, penjelasan @XmlElement tidak diperlukan
mmatloka
Terima kasih untuk ini. Jika saya masih ingin mengirim 2 String lalu apa yang dibutuhkan restfull untuk dapat menggunakan? Atau apakah beberapa parameter hanya berfungsi dengan @PathParm?
Klaasvaak
1
@Klaasvaak - Anda perlu menentukan dari mana setiap param diharapkan akan diekstraksi. Seperti yang Anda miliki sekarang, Jersey / NetBeans mengasumsikan posting formulir dan mengekstrak data yang dikirim sebagai FormParm. Anotasi setiap penambahan metode Anda dengan tempat asal datanya (PathParam, FormParam, CookieParam, dll.)
Persepsi
1
@Klaasvaak - saya menambahkan sekelompok contoh menggunakan berbagai penjelasan
D.Shawley
2
Terima kasih banyak untuk ini! Ini benar-benar yang saya cari. Anda membuat hari saya;) Saya menggunakan FormParams sekarang dan berhasil!
Klaasvaak