Spring MVC RequestMapping | آموزش ریکوئست مپینگ در اسپرینگ
توضیحات جلسه
جزوه و مستندات
مفاهیم کلیدی
- Domain Model
مجموعهای از کلاسهای نشاندهنده موجودیتها و قواعد تجاری نرمافزار (مانند Taco، Ingredient و TacoOrder) که ساختار دادهها و هسته اصلی سیستم را تشکیل میدهند.
- Project Lombok
کتابخانهای کمکی در جاوا که با استفاده از انوتیشنها در زمان کامپایل، متدهای تکراری مانند getter، setter، سازندهها و toString را تولید کرده و حجم کدهای پروژه را کاهش میدهد.
@Data
انوتیشن پرکاربرد Lombok در سطح کلاس که بهطور همزمان انوتیشنهای @ToString، @EqualsAndHashCode، @Getter، @Setter و همچنین @RequiredArgsConstructor (سازنده فیلدهای final) را تولید میکند.
@Slf4j
انوتیشنی از Lombok که در زمان کامپایل، یک نمونه فیلد استاتیک از لاگر SLF4J به نام log در کلاس میسازد و نیاز به تعریف دستی متد لاگگیری را حذف میکند.
@RequestMapping
انوتیشن پایهای مدیریت مسیرها که وقتی در سطح کلاس استفاده شود، مسیر پایه (Base Path) تمام متدهای درون کلاس را مشخص میکند.
@ModelAttribute
انوتیشنی دوکاره که هم در سطح متد برای قرار دادن دادهها داخل Model قبل از اجرای متدهای هندلر به کار میرود و هم در سطح پارامتر برای دریافت و اتصال دادههای ارسالی یا موجود در Model.
@SessionAttributes
انوتیشن در سطح کلاس Controller که مشخص میکند کدام یک از فیلدهای اضافه شده به Model باید در طول چندین درخواست کاربر داخل حافظه نشست (Session) نگهداری شوند.
- Spring Converter
اینترفیسی در Spring Framework به نام Converter<S, T> که وظیفه تبدیل نوع ورودی S (مانند String) به نوع مقصد T (مانند آبجکت Ingredient) را برای اتصال خودکار فیلدهای فرم بر عهده دارد.
- Post/Redirect/Get Pattern
یک الگوی طراحی وب که پس از پردازش درخواست POST، کاربر را با پیشوند :redirect به مسیر جدیدی هدایت میکند تا از ارسال مجدد فرم با ریفرش مرورگر جلوگیری شود.
- SessionStatus
آبجکتی که به متد کنترلر پاس داده میشود تا چرخه حیات Session را مدیریت کند؛ متد setComplete در این آبجکت دادههای مرتبط با @SessionAttributes را پس از پایان فرآیند پاکسازی میکند.
موارد مصاحبه ای
- تفاوت استفاده از
@RequestMappingدر سطح کلاس با سطح متد چیست؟
در سطح کلاس، پیشوند آدرس کلیه روتهای کنترلر را مشخص میکند و نوع درخواست را تعیین نمیکند؛ اما در سطح متد، مسیرهای جزیی و نوع افعال HTTP مانند GET یا POST را تفکیک و نگاشت میکند.
- انوتیشن
@ModelAttributeوقتی روی متد قرار میگیرد چه رفتاری دارد؟
متدهایی با انوتیشن @ModelAttribute پیش از اجرای هر کدام از متدهای اصلی دارای @GetMapping یا @PostMapping در آن کلاس فراخوانی میشوند و خروجی آنها به Model اضافه میشود تا همواره در نماها در دسترس باشد.
- چرا پیشوند
redirect:در مقدار بازگشتی کنترلر استفاده میشود؟
این پیشوند نشاندهنده هدایت مجدد کاربر از طریق پاسخ HTTP 302 به یک مسیر دیگر است و مانع از ثبت دوباره اطلاعات در اثر ریفرش صفحه یا ارسال ناخواسته فرم در الگوی PRG میشود.
سناریو کاربردی
- مدیریت ثبت سفارش چندمرحلهای با نگهداری نشست و تبدیل خودکار دادهها
در سناریوی ثبت سفارش، کاربر ابتدا در صفحه طراحی با ارسال شناسه رشتهای مواد اولیه، یک تاکو میسازد و سپس به صفحه ثبت نهایی منتقل میشود:
۱. کلاس مبدل برای تبدیل شناسه متنی به شیء:
@Component
public class IngredientByIdConverter implements Converter<String, Ingredient> {
private Map<String, Ingredient> ingredientMap = new HashMap<>();
public IngredientByIdConverter() {
// نمونهسازی موقت مواد اولیه تا پیش از اتصال پایگاهداده
ingredientMap.put("FLTO", new Ingredient("FLTO", "Flour Tortilla", Type.WRAP));
ingredientMap.put("GRBF", new Ingredient("GRBF", "Ground Beef", Type.PROTEIN));
}
@Override
public Ingredient convert(String id) {
return ingredientMap.get(id);
}
}
۲. کنترلر ساخت تاکو و نگهداری سبد خرید در نشست:
@Slf4j
@Controller
@RequestMapping("/design")
@SessionAttributes("tacoOrder")
public class DesignTacoController {
@ModelAttribute(name = "tacoOrder")
public TacoOrder order() {
return new TacoOrder();
}
@GetMapping
public String showDesignForm(Model model) {
model.addAttribute("taco", new Taco());
return "design";
}
@PostMapping
public String processTaco(Taco taco, @ModelAttribute TacoOrder tacoOrder) {
tacoOrder.addTaco(taco);
log.info("Processing taco: {}", taco);
return "redirect:/orders/current";
}
}
۳. کنترلر تکمیل سفارش و پاکسازی نشست:
@Slf4j
@Controller
@RequestMapping("/orders")
@SessionAttributes("tacoOrder")
public class OrderController {
@GetMapping("/current")
public String orderForm() {
return "orderForm";
}
@PostMapping
public String processOrder(TacoOrder order, SessionStatus sessionStatus) {
log.info("Order submitted: {}", order);
// پاکسازی نشست جهت آمادهسازی برای سفارشهای بعدی
sessionStatus.setComplete();
return "redirect:/";
}
}
در این سناریو، شناسه متنی مواد تیکخورده در فرم توسط IngredientByIdConverter به شیء تبدیل شده و آبجکت tacoOrder در نشست کاربری حفظ میشود تا در مرحله بعدی تکمیل و پاکسازی گردد.
بیشتر بدانید
- تنظیم Maven Plugin برای خروج Lombok از فایل نهایی
از آنجا که تغییرات Lombok در زمان کامپایل صورت میگیرد، بهتر است این کتابخانه از خروجی نهایی پکیج استثنا شود:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
- نصب افزونه Lombok در محیط توسعه
برای جلوگیری از خطاهای کاذب کامپایلر محیط برنامهنویسی نظیر عدم شناسایی متدهای سازنده، getter و setter، نصب Plugin لومبوک و فعالسازی گزینه Annotation Processing در تنظیمات IDE ضروری است.
