วิธีเข้าถึงพารามิเตอร์ในเมธอด RESTful POST


123

วิธีการโพสต์ของฉันมีลักษณะดังนี้:

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

เมื่อฉันสร้าง Jersey Client ใน Netbeans วิธีที่เรียกวิธีการโพสต์จะมีลักษณะดังนี้:

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

เมื่อทำการทดสอบนี้:

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

ให้ผลลัพธ์ต่อไปนี้ในเซิร์ฟเวอร์:

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

ฉันต้องเปลี่ยนอะไรเพื่อให้พารามิเตอร์ให้ค่าที่ถูกต้อง


คุณใช้สิ่งนี้กับแอปพลิเคชัน Android หรือไม่?
Android-Droid

ในที่สุดฉันก็ต้องการเรียกวิธีการโพสต์นี้ในแอพ Android อย่างไรก็ตามบริการเว็บเซอร์ไม่ทราบวิธีการลงนามค่าในพารามิเตอร์ ฉันต้องการทราบวิธีการทำเช่นนี้
Klaasvaak

คำตอบ:


356

@POSTวิธีการของคุณควรยอมรับออบเจ็กต์ JSON แทนที่จะเป็นสตริง Jersey ใช้ JAXB เพื่อสนับสนุนอ็อบเจ็กต์ JSON แบบ marshaling และ unmarshaling (ดูรายละเอียดในเอกสารเจอร์ซีย์ ) สร้างชั้นเรียนเช่น:

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

@POSTวิธีการของคุณจะมีลักษณะดังนี้:

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

วิธีนี้คาดว่าจะได้รับออบเจ็กต์ JSON เป็นเนื้อความของ HTTP POST JAX-RS ส่งผ่านเนื้อหาเนื้อหาของข้อความ HTTP เป็นพารามิเตอร์ที่ไม่มีคำอธิบาย - inputในกรณีนี้ ข้อความจริงจะมีลักษณะดังนี้:

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

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

การใช้ JSON ในลักษณะนี้เป็นเรื่องปกติสำหรับเหตุผลที่ชัดเจน อย่างไรก็ตามหากคุณสร้างหรือใช้งานในสิ่งอื่นที่ไม่ใช่ JavaScript คุณจะต้องระมัดระวังในการหลีกเลี่ยงข้อมูลอย่างเหมาะสม ใน JAX-RS คุณจะต้องใช้MessageBodyReaderและMessageBodyWriterเพื่อใช้สิ่งนี้ ฉันเชื่อว่า Jersey มีการใช้งานสำหรับประเภทที่ต้องการอยู่แล้ว (เช่น Java primitives และ JAXB wrap class) รวมถึง JSON JAX-RS รองรับวิธีการอื่น ๆ ในการส่งผ่านข้อมูล สิ่งเหล่านี้ไม่ต้องการการสร้างคลาสใหม่เนื่องจากข้อมูลถูกส่งโดยใช้การส่งผ่านอาร์กิวเมนต์ธรรมดา


HTML <FORM>

พารามิเตอร์จะถูกใส่คำอธิบายประกอบโดยใช้@FormParam :

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

เบราว์เซอร์จะเข้ารหัสรูปแบบโดยใช้"application / x-www ฟอร์ม urlencoded" รันไทม์ JAX-RS จะดูแลการถอดรหัสเนื้อความและส่งต่อไปยังเมธอด นี่คือสิ่งที่คุณควรเห็นบนสายไฟ:

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

เนื้อหาถูกเข้ารหัส URLในกรณีนี้

หากคุณไม่ทราบชื่อของ FormParam คุณสามารถดำเนินการดังต่อไปนี้:

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

ส่วนหัว HTTP

คุณสามารถใช้คำอธิบายประกอบ@HeaderParamหากคุณต้องการส่งผ่านพารามิเตอร์ผ่านส่วนหัว HTTP:

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

นี่คือลักษณะของข้อความ HTTP โปรดทราบว่า POST นี้ไม่มีเนื้อความ

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

ฉันจะไม่ใช้วิธีนี้สำหรับการส่งผ่านพารามิเตอร์ทั่วไป จะมีประโยชน์มากหากคุณต้องการเข้าถึงค่าของส่วนหัว HTTP เฉพาะ


พารามิเตอร์การสืบค้น HTTP

วิธีนี้ใช้กับ HTTP GET เป็นหลัก แต่สามารถใช้ได้กับ POSTs ใช้คำอธิบายประกอบ@QueryParam

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

เช่นเดียวกับเทคนิคก่อนหน้านี้การส่งผ่านพารามิเตอร์ผ่านสตริงการสืบค้นไม่จำเป็นต้องมีเนื้อหาของข้อความ นี่คือข้อความ HTTP:

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

คุณจะต้องระมัดระวังเป็นพิเศษในการเข้ารหัสพารามิเตอร์การสืบค้นในฝั่งไคลเอ็นต์ การใช้พารามิเตอร์การค้นหาอาจเป็นปัญหาได้เนื่องจากข้อจำกัดความยาวของ URL ที่บังคับใช้โดยพร็อกซีบางรายรวมถึงปัญหาที่เกี่ยวข้องกับการเข้ารหัส


พารามิเตอร์เส้นทาง HTTP

พารามิเตอร์พา ธ คล้ายกับพารามิเตอร์คิวรียกเว้นว่าถูกฝังอยู่ในเส้นทางทรัพยากร HTTP วิธีนี้ดูเหมือนจะเป็นที่นิยมในปัจจุบัน มีผลกระทบเกี่ยวกับการแคช HTTP เนื่องจากเส้นทางเป็นสิ่งที่กำหนดทรัพยากร HTTP อย่างแท้จริง รหัสมีลักษณะแตกต่างจากที่อื่นเล็กน้อยเนื่องจากมีการแก้ไขคำอธิบายประกอบ@Pathและใช้@PathParam :

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

ข้อความจะคล้ายกับเวอร์ชันพารามิเตอร์เคียวรียกเว้นว่าชื่อของพารามิเตอร์จะไม่รวมอยู่ที่ใดในข้อความ

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

วิธีนี้ใช้การเข้ารหัสร่วมกันกับเวอร์ชันของพารามิเตอร์เคียวรี ส่วนเส้นทางถูกเข้ารหัสแตกต่างกันดังนั้นคุณต้องระมัดระวังเช่นกัน


อย่างที่คุณเห็นมีข้อดีข้อเสียของแต่ละวิธี ทางเลือกมักจะตัดสินใจโดยลูกค้าของคุณ ถ้าคุณจะให้บริการFORMหน้าเว็บ HTML @FormParamชั่นการใช้งานแล้ว หากไคลเอ็นต์ของคุณใช้ JavaScript + HTML5 คุณอาจต้องการใช้การทำให้เป็นอนุกรมตาม JAXB และออบเจ็กต์ JSON การMessageBodyReader/Writerใช้งานควรดูแลการหลบหนีที่จำเป็นสำหรับคุณเพื่อให้มีสิ่งที่ผิดพลาดน้อยลง หากไคลเอนต์ของคุณใช้ Java แต่ไม่มีตัวประมวลผล XML ที่ดี (เช่น Android) ฉันอาจจะใช้การFORMเข้ารหัสเนื่องจากเนื้อหาเนื้อหาสร้างและเข้ารหัสได้ง่ายกว่า URL หวังว่ารายการ mini-wiki นี้จะช่วยให้กระจ่างเกี่ยวกับวิธีการต่างๆที่ JAX-RS รองรับ

หมายเหตุ:เพื่อประโยชน์ของการเปิดเผยข้อมูลทั้งหมดฉันยังไม่ได้ใช้คุณลักษณะนี้ของ Jersey เรากำลังแก้ไขปัญหานี้เนื่องจากเรามีแอปพลิเคชัน JAXB + JAX-RS จำนวนมากที่ใช้งานได้และกำลังย้ายเข้าสู่พื้นที่ไคลเอนต์มือถือ JSON เหมาะกับ XML บนโซลูชันที่ใช้ HTML5 หรือ jQuery มากขึ้น


4
ฉันได้ทดสอบคุณสมบัตินี้เมื่อวานนี้ไม่จำเป็นต้องมีคำอธิบายประกอบ
@XmlElement

ขอบคุณสำหรับสิ่งนี้. ถ้าฉันยังต้องการส่ง 2 Strings แล้ว restfull ต้องใช้อะไรถึงจะกินได้? หรือใช้พารามิเตอร์หลายตัวกับ @PathParm เท่านั้น?
Klaasvaak

1
@Klaasvaak - คุณต้องระบุตำแหน่งที่คาดว่าจะแยกพารามิเตอร์แต่ละตัวออกมา อย่างที่คุณมีตอนนี้ Jersey / NetBeans สมมติว่ามีการโพสต์แบบฟอร์มและแยกข้อมูลที่ส่งเป็น FormParm ใส่คำอธิบายประกอบแต่ละวิธีของคุณเพิ่มขึ้นด้วยตำแหน่งที่คุณต้องการข้อมูลจาก (PathParam, FormParam, CookieParam และอื่น ๆ )
Perception

1
@Klaasvaak - ฉันเพิ่มตัวอย่างมากมายโดยใช้คำอธิบายประกอบต่างๆ
D.Shawley

2
ขอบคุณมากสำหรับเรื่องนี้! นี่คือสิ่งที่ฉันกำลังมองหาจริงๆ คุณทำให้วันของฉัน;) ตอนนี้ฉันใช้ FormParams และได้ผล!
Klaasvaak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.