در ابتدا لازم است دو کتابخانه برای JSON و XML به پروژه اضافه کنیم
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.7.2</version> </dependency>
کتابخانه معروف jackson در Spring قابلیت استفاده و شناسایی دارد
در Spring MVC سه روش برای تعیین media type وجود دارد :
- پسوند URL درخواستی مثل css. یا jpg.
- صراحتا اعلام کردن آن در پارامتر های درخواست مثل format=json?
- فیلد Accept در header درخواست
اگر هیچکدام از این سه استراتژی فعال نبود میتوانیم یک content type پیش فرض را تعریف کنیم
استراتژی پسوند URL درخواستی :
بصورت پیش فرض این استراتژی غیر فعال است
@RequestMapping( value = "/employee/{id}", produces = { "application/json", "application/xml" }, method = RequestMethod.GET) public @ResponseBody Employee getEmployeeById(@PathVariable long id) { return employeeMap.get(id); }
ارسال درخواست :
curl http://localhost:8080/spring-mvc-basics/employee/10.json
اگر به url درخواستی نگاه کنید پسوند درخواستی json. است و موقع ساخت Response دیتای کلاس بصورت json سریالایز خواهد شد و باید چیزی مثل زیر دریافت کنیم :
{ "id": 10, "name": "Test Employee", "contactNumber": "999-999-9999" }
حالا بیایم آنرا به xml تغییر دهیم :
curl http://localhost:8080/spring-mvc-basics/employee/10.xml
چیزی که دریافت میکنیم بصورت xml خواهد بود :
<employee> <contactNumber>999-999-9999</contactNumber> <id>10</id> <name>Test Employee</name> </employee>
حال اگر پسوندی تعیین نکنیم چطور عمل میکند ؟
مثال :
curl http://localhost:8080/spring-mvc-basics/employee/10
در این صورت چیزی که به عنوان default content type تعیین کردیم برگشت داده میشود
حالا ببینیم چطور باید آنرا تعیین کنیم :
- روش اول ست کردن تنظیمات با استفاده از کد Java
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(true). favorParameter(false). ignoreAcceptHeader(true). useJaf(false). defaultContentType(MediaType.APPLICATION_JSON); }
در ابتدا استراتژی path extension را فعال کرده ایم تا از روی پسوند درخواست ها متوجه شود محتوا را باید به چه شکل سرو کند
در خط بعدی استراتژی URL parameter و در خط بعدش استراتژی خواندن فیلد Accept در Header را غیر فعال کرده ایم چون میخواهیم تنها استراتژی path extension فعال باشد
در خط بعدی میتوان عبارت Jaf را مشاهده کرد که غیر فعال شده Jaf مخفف Java Activation Framework است، Jaf یک مکانیزمی است برای تعیین خودکار media type اگر بخواهیم مقدار پیش فرضی را تعیین کنیم باید این مکانیزم نیز غیر فعال باشد
و در انتها Content Type پیش فرض را از نوع JSON تعیین کردیم
- روش دوم با استفاده از تنظیمات XML :
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="true" /> <property name="favorParameter" value="false"/> <property name="ignoreAcceptHeader" value="true" /> <property name="defaultContentType" value="application/json" /> <property name="useJaf" value="false" /> </bean>
از نام property ها میتوان فهمید که مشابه روش Java است و نیازی به تکرار توضیحات ندارد
استراتژی URL Parameter :
اگر در تنظیمات بالا مقدار favorParameter را true کنیم میتوانیم با این شکل از URL درخواستی Content Type مربوطه را دریافت کنیم
curl http://localhost:8080/spring-mvc-basics/employee/10?mediaType=json
حالا بیاییم قدری تنظیمات پیشرفته تری را انجام دهیم :
روش Java Configuration :
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false). favorParameter(true). parameterName("mediaType"). ignoreAcceptHeader(true). useJaf(false). defaultContentType(MediaType.APPLICATION_JSON). mediaType("xml", MediaType.APPLICATION_XML). mediaType("json", MediaType.APPLICATION_JSON); }
روش XML configuration :
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="false" /> <property name="favorParameter" value="true"/> <property name="parameterName" value="mediaType"/> <property name="ignoreAcceptHeader" value="true" /> <property name="defaultContentType" value="application/json" /> <property name="useJaf" value="false" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> </bean>
در این تنظیمات میتوان به عبارت ست کردن mediaType اشاره کرد این خط ما صراحتا اعلام میکنیم که درخواست اگر شامل عبارت خاصی بود کدامیک از media type ها را باید برایش در نظر بگیرید این برای حالتی که میخواهیم پسوند دلخواه خودمان را ست کنیم هم کاربرد دارد
استراتژی Accept در هدر :
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(true). favorParameter(false). parameterName("mediaType"). ignoreAcceptHeader(false). useJaf(false). defaultContentType(MediaType.APPLICATION_JSON). mediaType("xml", MediaType.APPLICATION_XML). mediaType("json", MediaType.APPLICATION_JSON); }
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="true" /> <property name="favorParameter" value="false"/> <property name="parameterName" value="mediaType"/> <property name="ignoreAcceptHeader" value="false" /> <property name="defaultContentType" value="application/json" /> <property name="useJaf" value="false" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> </bean>
چنانچه بخواهیم مدیریت تعیین Media Type را تغییر دهیم میتوان این خط را با plugin های مختلف تغییر دهیم :
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />