2013-04-14 18 views
9

Để xử lý các phiên bản nội dung khác nhau, tôi đang cố sử dụng các tham số chấp nhận của tiêu đề "Chấp nhận *" (RFC 2616).Cách xử lý thông số chấp nhận khi phát triển ứng dụng jax-rs

Accept: application/vnd.mycompany.mytype;version=2 , application/vnd.mycompany.mytype;version=1;q=0.1 

Vấn đề là Jax-RS chú thích không hỗ trợ Accept-thông số ...

@GET 
@Produces("application/vnd.test;version=1") 
public Response test1() { 
    return Response.ok("Version 1", "application/vnd.test").build(); 
} 

@GET 
@Produces("application/vnd.test;version=2") 
public Response test2() { 
    return Response.ok("Version 2", "application/vnd.test").build(); 
} 

Kết quả trong một ngoại lệ phương tiện truyền thông loại mâu thuẫn:

Producing media type conflict. The resource methods public javax.ws.rs.core.Response test.resources.TestResource.test2() and public javax.ws.rs.core.Response test.resources.TestResource.test1() can produce the same media type 

Có lẽ, ngoại lệ này chỉ liên quan đến khung JAX-RS của tôi (Jersey), nhưng tôi sợ điều này là do JSR311 không rõ ràng về các tham số chấp nhận.

Hiện tại, tôi đang sử dụng các loại nội dung chứa phiên bản bên trong tên của chúng, nhưng tôi thấy giải pháp này khá uggly.

@GET 
@Produces("application/vnd.test-v1") 
public Response test() { 
    return Response.ok("Version 1", "application/vnd.test-v1").build(); 
} 

Bạn có ý tưởng nào về cách xử lý thông số chấp nhận không?

EDIT

Tôi nghĩ rằng tôi đã không đủ rõ ràng. Tôi muốn tự động định tuyến yêu cầu đến các phương pháp cụ thể. Các phương thức này được phiên bản và tương ứng với phiên bản cụ thể của kiểu nội dung trả về. Thực thi hiện tại JAX-RS ngăn tôi sử dụng các tham số chấp nhận để định tuyến yêu cầu (đến phương thức tương ứng).

greenkode đề xuất rằng tôi quản lý thông số chấp nhận version trong phương thức gửi đi (sử dụng @HeaderParam("Accept")). Giải pháp này sẽ kết thúc bằng cách viết lại logic phân ly nội dung được nhúng trong khung công tác (và được mô tả trong JSR 311).

Tôi có thể làm gì để sử dụng cả logic chấp nhận tham số và nội dung-phân ly từ JAX-RS?

Có thể giải pháp là sử dụng một khung công tác khác (Tôi chỉ làm việc với Jersey theo Hiện hành). Nhưng tôi không biết cái nào.

+1

Bây giờ điều đó thật thú vị. Đọc nhận xét, tôi thấy rằng JAX-RS không có vấn đề gì khi diễn tả điều này. Thay vào đó, nó là một vấn đề với việc thực hiện * Jersey *, và rằng ít nhất một triển khai khác có thể thực hiện nó. (Tôi muốn tôi biết liệu CXF, khung tôi sử dụng, có vấn đề ở đây, nhưng tôi đang trên đường ngay bây giờ và không thể kiểm tra ...) –

+0

Bất kỳ cập nhật nào về cách bạn chọn triển khai. Tôi cần phải làm như vậy và tò mò muốn biết nếu hte chọn câu trả lời đã làm việc cho bạn. –

Trả lời

15

các JAX-RS đặc điểm kỹ thuật không rõ ràng bất cứ điều gì nhà nước về phớt lờ Chấp nhận các thông số tiêu đề. Nhưng thông số duy nhất cho w xử lý hich là chắc chắn được xác định là chất lượng (q). Đây là một lĩnh vực có thể cải thiện vì nó dường như đã dẫn đến sự mơ hồ (hoặc buông xả hoàn toàn) trong việc thực hiện Jersey. Phiên bản hiện tại của Jersey (1,17) không mất Chấp nhận các thông số đầu vào xem xét khi kết hợp yêu cầu đến nguồn lực phương pháp, đó là lý do tại sao bạn đang nhận được lỗi:

SEVERE: Producing media type conflict. The resource methods ...

Đối với tài nguyên:

@GET 
@Produces("application/vnd.test;version=1") 
public Response test1() { 
    return Response.ok("Version 1", "application/vnd.test").build(); 
} 

@GET 
@Produces("application/vnd.test;version=2") 
public Response test2() { 
    return Response.ok("Version 2", "application/vnd.test").build(); 
} 

Có vẻ như Jersey thực hiện kiểm tra 'duy nhất' dựa trên tiêu đề Chấp nhận 'loại/loại phụ', hoàn toàn bỏ qua bất kỳ thông số nào. Điều này có thể được xác nhận bằng cách thử nghiệm với các cặp tiêu đề khác nhau trên phương thức tài nguyên 'phù hợp':

 
Resource 1    Resource 2 
---------------------------------------- 
text/html;q=0.4  text/html;q=0.8 
text/html    text/html;q=0.2 
text/html    text/html;qs=1.4 
text/html;qs=1.4  text/html;qs=1.8 
text/html;level=1  text/html;level=2 
text/html;foo=bleh text/html;bar=23 

Tất cả đều không có lỗi tương tự. Nếu giả định đã được thực hiện mà chỉ có các tham số chất lượng được từng gửi, sau đó nó sẽ làm cho tinh thần để chỉ trận đấu trên 'loại/kiểu phụ', bởi vì loại này yêu cầu là vô nghĩa:

Accept: text/html;q=0.8, text/html;q=0.4, text/html

Aka, chất lượng thông số chỉ có ý nghĩa khi bạn đang xử lý một kết hợp của các loại nội dung có thể.Tuy nhiên, loại kết hợp hạn chế này không thành công khi các tham số không phải chất lượng hoặc thông số bổ sung đang được gửi:

Vì vậy, các giải pháp có thể là gì?

  • Intercept yêu cầu trình độ cao dựa trên 'loại/kiểu phụ', sau đó đường đến phương pháp thích hợp hơn (bạn đã chỉ ra bạn không muốn làm điều này)
  • Sửa đổi tiêu đề dự kiến ​​của bạn. Ví dụ: 'application/vnd.mycompany.mytype + v2' và 'application/vnd.mycompany.mytype + v1'. Không cần thay đổi nào khác và bạn có thể tiếp tục sử dụng Jersey
  • Khuôn khổ chuyển đổi. RESTEasy xảy ra để xử lý kịch bản của bạn một cách dễ dàng.

Với RESTEasy, và tài nguyên:

@Path("/content/version") 
public class ContentVersionResource { 

    @GET 
    @Produces("application/vnd.test;version=1") 
    public Response test1() { 
     return Response.ok("Version 1", "application/vnd.test").build(); 
    } 

    @GET 
    @Produces("application/vnd.test;version=2") 
    public Response test2() { 
     return Response.ok("Version 2", "application/vnd.test").build(); 
    } 
} 

Một trận đấu thành công được thực hiện với những điều sau Chấp nhận tiêu đề:

Accept: application/vnd.test;version=1;q=0.3, application/vnd.test;version=2;q=0.5
Response: Version 2

Và đây:

Accept: application/vnd.test;version=1;q=0.5, application/vnd.test;version=2;q=0.3
Response: Version 1

Bạn có thể tải xuống và kiểm tra với điều này sample project. Git, Maven và JBoss 7.x yêu cầu

+0

Tôi đã học được điều gì đó mới mẻ hôm nay :) – greenkode

+0

Tôi đã thử RESTEasy một thời gian ngắn trước đây ... Nhưng rõ ràng, tôi đã bỏ lỡ một số điểm. Cảm ơn bạn đã phản hồi. – Arno

+0

@Amo - np và chúc bạn may mắn với phần còn lại của dự án. – Perception

2

Trừ khi tôi thiếu thứ gì đó. JAX-RS hỗ trợ chấp nhận tham số. xem chú thích @Consumes("*/*"). Ngoài ra, Ngoại lệ bạn nhận được với xung đột loại phương tiện xảy ra do bạn có hai phương thức GET tại cùng một url. chú thích phương thức test2() với @Path("test2"), sau đó gửi yêu cầu GET tới url/test2 thay thế. nên loại bỏ lỗi đó.

EDIT

Bạn có thể tiêm các giá trị gia tăng của Accept tiêu đề sử dụng @HeaderParams. Đây là một ví dụ về những gì tôi đã làm.

@Path("/conneg") 
public class ConnNeg { 

    @GET 
    @Produces("application/vnd.test;version=1") 
    public Response test1(@HeaderParam("Accept") String header) { 
     System.out.println(header); 
     return Response.ok("Version 1", "application/vnd.test").build(); 
    } 
} 

đi qua các yêu cầu

Accept: application/vnd.test;version=2 , application/vnd.test;version=1;q=0.1

này sẽ in

application/vnd.test;version=2 , application/vnd.test;version=1;q=0.1

Sau đó bạn có thể xử lý nó bằng tay. Đây có phải là những gì bạn đang tìm kiếm không?

+0

Tôi đã biết rằng JAX-RS không hỗ trợ chấp nhận tham số. Những gì tôi muốn là các đề xuất về cách xử lý chúng đúng cách. – Arno

+0

oh, tôi hiểu rồi. tôi đã nhầm lẫn 'phạm vi đa phương tiện' với' accept-params'. – greenkode

+0

Tôi đã chỉnh sửa câu trả lời của mình. là những gì bạn đang tìm kiếm? – greenkode

1

Với khung công tác Jersey, tiêu đề Chấp nhận của yêu cầu HTTP đã khai báo những gì được chấp nhận nhất. Nếu một lớp tài nguyên có khả năng tạo ra nhiều hơn một kiểu phương tiện MIME thì phương thức tài nguyên được chọn sẽ tương ứng với kiểu phương tiện được chấp nhận nhất như được khai báo bởi máy khách. Trong trường hợp của bạn, nếu tiêu đề chấp nhận là

Accept: application/vnd.mycompany.mytype;version=2 

thì phương thức test1() sẽ được gọi.

Nếu đó là

Accept: application/vnd.mycompany.mytype;q=0.9 version=2, application/vnd.mycompany.mytype;version=1 

một trong những thứ hai sẽ được gọi.

Hơn một loại phương tiện truyền thông có thể được khai báo trong tờ khai @Produces cùng, ví dụ:

@GET 
@Produces({"application/vnd.mycompany.mytype; version=2", "application/vnd.mycompany.mytype; version=1"}) 
public Response test() { 
    return Response.ok("").build(); 
} 

kiểm tra (9 phương pháp sẽ được gọi nếu một trong 2 mediatypes là chấp nhận được nếu cả hai đều chấp nhận được. , người đầu tiên sẽ được gọi.

Hy vọng nó sẽ giúp!

Các vấn đề liên quan