البرمجة

حلاً لمشكلة تحويل الـ URI في Spring Data Rest مع وحدات التحكم المخصصة

في مشروعي الحالي القائم على Spring Data Rest، والذي يحتوي أيضًا على بعض النقاط النهائية المخصصة، يُستخدم تنسيق JSON لإرسال بيانات POST. وفي الواقع، يعمل ذلك بشكل جيد مع Spring Data Rest، ولكنه لا يعمل بشكل صحيح مع وحدة التحكم المخصصة.

على سبيل المثال، يتم استخدام التنسيق التالي:

json
{ "action": "REMOVE", "customer": "http://localhost:8080/api/rest/customers/7" }

هذا يعمل بشكل جيد مع Spring Data Rest، ولكن يواجه مشكلة عند استخدامه مع وحدة التحكم المخصصة، كما هو موضح في الكود التالي:

java
@RestController public class ActionController { @Autowired private ActionService actionService; @RequestMapping(value = "/customer/action", method = RequestMethod.POST) public ResponseEntity doAction(@RequestBody Action action){ ActionType actionType = action.action; Customer customer = action.customer; // <-- هناك مشكلة ActionResult result = actionService.doCustomerAction(actionType, customer); return ResponseEntity.ok(result); } }

عند استدعاء الأمر:

bash
curl -v -X POST -H "Content-Type: application/json" -d '{"action": "REMOVE","customer": "http://localhost:8080/api/rest/customers/7"}' http://localhost:8080/customer/action

يتم الحصول على رد الخطأ التالي:

json
{ "timestamp": "2016-05-12T11:55:41.237+0000", "status": 400, "error": "Bad Request", "exception": "org.springframework.http.converter.HttpMessageNotReadableException", "message": "Could not read document: Can not instantiate value of type [simple type, class model.user.Customer] from String value ('http://localhost:8080/api/rest/customers/7'); no single-String constructor/factory method\n at [Source: java.io.PushbackInputStream@73af10c6; line: 1, column: 33] (through reference chain: api.controller.Action[\"customer\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class logic.model.user.Customer] from String value ('http://localhost:8080/api/rest/customers/7'); no single-String constructor/factory method\n at [Source: java.io.PushbackInputStream@73af10c6; line: 1, column: 33] (through reference chain: api.controller.Action[\"customer\"])", "path": "/customer/action" }

يحدث هذا لأن Spring لا يستطيع تحويل URI إلى كائن كوستمر (Customer entity). هل هناك طريقة لاستخدام آلية Spring Data Rest لحل الكيانات بواسطة معرفها URI؟

في الواقع، لدي فكرة واحدة فقط حاليًا – استخدام محلل Json مخصص مع تحليل URI لاستخراج هوية الكائن وإجراء طلب إلى المستودع. ومع ذلك، هذا الاستراتيجية لا تساعد إذا كانت لدي URI مثل “http://localhost:8080/api/rest/customers/8/product”، حيث لا يتوفر لي قيمة لـ product.Id.

لم يتم التعامل مع حالة مثل هذه من قبل، وأعتقد أن هناك حاجة إلى معالجة خاصة لهذا النوع من الحالات. سأكمل البحث والتجارب للعثور على حلاً ملائمًا لمشكلتك. سأواصل التحقق من الوثائق والمصادر ذات الصلة للعثور على حلاً متقدمًا يتيح لك حل هذه المشكلة بشكل أكثر فعالية.

المزيد من المعلومات

في سياق هذه المشكلة، يظهر أن المشكلة الرئيسية تكمن في عدم قدرة Spring على تحويل القيمة النصية للـ URI إلى كائن Customer بطريقة تلقائية، وهذا يعود إلى عدم وجود منهج سهل لتحويل السلسلة إلى كائن معين في هذه الحالة.

لحل هذه المشكلة، يمكن اتباع بعض الخطوات التي تعتمد على تخصيص معالجة تحويل الـ JSON في Spring. يمكن استخدام محلل JSON مخصص (Custom JSON Deserializer) لتحليل القيمة المستلمة وتحويلها بطريقة مخصصة.

في هذا السياق، يمكنك إنشاء محلل JSON خاص لـ Customer يتعامل بشكل خاص مع القيمة النصية للـ URI. في هذا المحلل، يمكنك استخدام Spring Data Rest لحل الكائن باستخدام الـ URI.

قد يكون لديك شيء مشابه للكود التالي:

java
public class CustomerDeserializer extends JsonDeserializer { @Autowired private CustomerRepository customerRepository; @Override public Customer deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); String customerUri = node.asText(); // استخدم Spring Data Rest لحل الكائن باستخدام الـ URI ResponseEntity responseEntity = restTemplate.getForEntity(customerUri, Customer.class); return responseEntity.getBody(); } }

ومن ثم، يمكنك استخدام هذا المحلل المخصص في كلاس العملية (Action) كما يلي:

java
public class Action { public ActionType action; @JsonDeserialize(using = CustomerDeserializer.class) public Customer customer; }

باستخدام هذا النهج، يمكنك تجاوز مشكلة تحويل القيمة النصية للـ URI إلى كائن Customer بشكل فعّال. يجب عليك ضبط الكود بما يتناسب مع بنية مشروعك واحتياجاتك الخاصة.

زر الذهاب إلى الأعلى