View Full Version : این فایل JSON که با اسپرینگ و کتابخونه های مربوط به REST میشه تولیدش کرد، کجا میره؟
La Volpe
سه شنبه 08 اردیبهشت 1394, 19:47 عصر
سلام
من دارم کار با اسپرینگ رو یاد میگیرم، و واسه شروع، این راهنما (http://spring.io/guides/gs/rest-service/) رو انجام دادم و کاملا اون چیزی که تو راهنما گفته شده رو فهمیدم و مشکلی ندارم. اما یه سوال واسم پیش اومد! تو این راهنما ما یه متد داریم به صورت زیر:
@RequestMapping("/greeting")
public Greeting greeting(
@RequestParam(value="name", defaultValue="World") String name)
{
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
این هر بار یه فایل جیسون تولید میکنه مثلا به صورت زیر:
{"id":2,"content":"Hello, Javad!"}
من سوالی که دارم، اینه که اون برچسب id که هر بار یه واحد اضافه میشه، JSON های با آیدی های قبلی کجا رفتن؟ اصلا جایی میمونن یا نه اون مقدار id هر بار یه جا میمونه تو رم و هر بار که رفرش میشه از بین میره؟ آیا این JSON ها به صورت on request تولید میشن و بعد از بین میرن؟
ahmad.mo74
سه شنبه 08 اردیبهشت 1394, 20:52 عصر
سلام، کد کاملش به اینصورته :
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMap ping;
import org.springframework.web.bind.annotation.RequestPar am;
import org.springframework.web.bind.annotation.RestContro ller;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
من یبار کامل توضیح میدم.
انوتیشن RestController@ معادل اینه :
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMap ping;
import org.springframework.web.bind.annotation.RequestPar am;
import org.springframework.web.bind.annotation.ResponseBo dy;
import java.util.concurrent.atomic.AtomicLong;
@Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
@ResponseBody
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
که برای موقعی که توی یه کنترلر میخواید برای همه متدهاش از ResponseBody@ استفاده کنید، برای راحتی فقط روی نام کلاس RestController@ رو مینویسید.
ResponseBody@ یعنی اینکه هر چیزی که این متد برگردوند رو به عنوان response بفرسته.
از اون جایی که spring باهوشه (از طریق Reflection) خودش متوجه میشه که کی خروجی رو به json تبدیل کنه (با استفاده از jackson این کارو میکنه)
اینجا هم متد greeting یک آبجکت از کلاس Greeting رو برمیگردونه که دارای فیلدهای id و content هست. در واقع با این هیچ فرقی نداره :
import com.fasterxml.jackson.core.JsonProcessingException ;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMap ping;
import org.springframework.web.bind.annotation.RequestPar am;
import org.springframework.web.bind.annotation.ResponseBo dy;
import java.util.concurrent.atomic.AtomicLong;
@Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
@ResponseBody
public String greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
try {
return new ObjectMapper().writeValueAsString(new Greeting(counter.incrementAndGet(), String.format(template, name)));
} catch (JsonProcessingException e) {
return e.toString();
}
}
}
اما اینکه چرا هربار به id اضافه میشه به scope کنترلر برمیگرده.
اسپرینگ بای دیفالت به صورت singleton با component ها رفتار میکنه و به همین خاطر اینجا هم کلاس GreetingController فقط یبار new میشه.
پس با اولین درخواستی که میاد یک بار GreetingController رو new میکنه و مقدار counter هم برابر صفر میشه. هربار که درخواست میاد مقدار counter یه واحد اضافه میشه و به عنوان id به Greeting داده میشه و همین طور الی آخر...
اگر بخوای scope رو تغییر بدی مثلا برای هر درخواست new بشه :
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMap ping;
import org.springframework.web.bind.annotation.RequestPar am;
import org.springframework.web.bind.annotation.RestContro ller;
import java.util.concurrent.atomic.AtomicLong;
@RestController
@Scope("request")
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
در کل scope های مهم اش ایناس : singleton, session, request, prototype
La Volpe
سه شنبه 08 اردیبهشت 1394, 21:30 عصر
خیلی ممنون بابت پاسخ!
ولی فک کنم متوجه منظورم نشدی. من اون جیسون ها رو لازم دارم. همونطوری که گفتم با مفهوم مشکلی ندارم، بحث اینجاست که میخوام اون جیسون ها رو بعدا استفاده کنم.
مثلا بگم:
http://localhost:8080/greeting?id=3
و فرض میکنیم که مقدار فعلی idمون ۵ باشه! من میخوام کانتنت متناظر با ۳ نمایش داده بشه! یعنی خروجی درخواست بالا این باشه:
{"id":3,"content":"Hello, Javad!"}
ahmad.mo74
سه شنبه 08 اردیبهشت 1394, 21:39 عصر
ممنون.
اگر بخوای مستقیما خود json رو ذخیره کنی و از طریق id به json برسی، باید اول خودت Greeting رو به json تبدیلش کنی، بعد بریزی توی map و یک متد هم بزاری که id بگیره و از توی map بهت json رو برگردونه، یعنی :
import com.fasterxml.jackson.core.JsonProcessingException ;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.RequestMap ping;
import org.springframework.web.bind.annotation.RequestPar am;
import org.springframework.web.bind.annotation.RestContro ller;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
private final Map<Long, String> greetings = new HashMap<>();
@RequestMapping("/greeting")
public String greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
long id = counter.incrementAndGet();
Greeting greeting = new Greeting(id, String.format(template, name));
try {
String json = new ObjectMapper().writeValueAsString(greeting);
greetings.put(id, json);
return json;
} catch (JsonProcessingException e) {
return e.toString();
}
}
@RequestMapping("/getJson")
public String find(@RequestParam(value = "id") long id) {
String json = greetings.get(id);
return json == null ? "Json Not Found!" : json;
}
}
اما اگر آبجکت Greeting رو ذخیره کنی کار راحتتره :
import org.springframework.web.bind.annotation.RequestMap ping;
import org.springframework.web.bind.annotation.RequestPar am;
import org.springframework.web.bind.annotation.RestContro ller;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
private final Map<Long, Greeting> greetings = new HashMap<>();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
long id = counter.incrementAndGet();
Greeting greeting = new Greeting(id, String.format(template, name));
greetings.put(id, greeting);
return greeting;
}
@RequestMapping("/getContent")
public String find1(@RequestParam(value = "id") long id) {
Greeting greeting = greetings.get(id);
return greeting == null ? "Content Not Found!" : greeting.getContent();
}
@RequestMapping("/getJson")
public Greeting find2(@RequestParam(value = "id") long id) {
return greetings.get(id);
}
}
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.