URI havolalar

All lectures for UZ purposes
Daraja, Dars
Mavjud

UriComponents

Spring MVC va Spring WebFlux

UriComponentsBuilder URI-shablonlardan o'zgaruvchilar yordamida URI identifikatorlarini yaratishga yordam beradi, bu quyidagi misolda ko'rsatilgan:

Java
UriComponents uriComponents = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}")  
        .queryParam("q", "{q}")  
        .encode() 
        .build(); 
URI uri = uriComponents.expand("Westin", "123").toUri();  
  1. URI-shablon bilan statik fabrika usuli.
  2. URI-komponentlarini qo'shish yoki o'zgartirish.
  3. URI-shablon va URI-o'zgaruvchilarning kodlanishi uchun so'rov.
  4. UriComponents yig'ilishi.
  5. O'zgaruvchilarni kengaytirib URI olish.
Kotlin
val uriComponents = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}")  
        .queryParam("q", "{q}")  
        .encode() 
        .build() 
val uri = uriComponents.expand("Westin", "123").toUri()  
  1. URI-shablon bilan statik fabrika usuli.
  2. URI-komponentlarini qo'shish yoki o'zgartirish.
  3. URI-shablon va URI-o'zgaruvchilarning kodlanishi uchun so'rov.
  4. UriComponents yig'ilishi.
  5. O'zgaruvchilarni kengaytirib URI olish.

Oldingi misoldagi kodni bitta zanjirga yig'ib, buildAndExpand yordamida qisqartirish mumkin, bu quyidagi misolda ko'rsatilgan:

Java
URI uri = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}")
        .queryParam("q", "{q}")
        .encode()
        .buildAndExpand("Westin", "123")
        .toUri();
Kotlin
val uri = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}")
        .queryParam("q", "{q}")
        .encode()
        .buildAndExpand("Westin", "123")
        .toUri()

Bu yerda yana qisqartirish mumkin, ya'ni to'g'ridan-to'g'ri URI identifikatoriga o'tish orqali (bu kodlashni nazarda tutadi), quyidagi misolda ko'rsatilgan:

Java
URI uri = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}")
        .queryParam("q", "{q}")
        .build("Westin", "123");
Kotlin
val uri = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}")
        .queryParam("q", "{q}")
        .build("Westin", "123")

Bu yerda yanada ko'proq qisqartirish mumkin, bu to'liq URI-shablon bilan, quyidagi misolda ko'rsatilgan:

Java
URI uri = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}?q={q}")
        .build("Westin", "123");
Kotlin
val uri = UriComponentsBuilder
        .fromUriString("https://example.com/hotels/{hotel}?q={q}")
        .build("Westin", "123")

UriBuilder

Spring MVC va Spring WebFlux

UriComponentsBuilder UriBuilder ni amalga oshiradi. Bu holda UriBuilderFactory yordamida UriBuilder yaratishingiz mumkin. Birgalikda UriBuilderFactory va UriBuilder umumiy konfiguratsiya, masalan asosiy URL-manzil, kodlash parametrlari va boshqa tafsilotlar asosida URI identifikatorlarini yaratish uchun ulanish mexanizmini taqdim etadi.

RestTemplate va WebClient ni UriBuilderFactory bilan sozlash orqali URI identifikatorlarini tayyorlashni sozlashingiz mumkin. DefaultUriBuilderFactory – bu UriBuilderFactory ning asosiy darajadagi amalga oshirilishi bo'lib, u ichki darajada UriComponentsBuilder dan foydalanadi va umumiy konfiguratsiya parametrlari ochib beradi.

Quyidagi misolda bunday bean'ni qanday sozlash ko'rsatilgan:

Java
// org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode ni import qilamiz;
String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
Kotlin
// org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode ni import qilamiz
val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES
val restTemplate = RestTemplate()
restTemplate.uriTemplateHandler = factory

Quyidagi misolda WebClient konfiguratsiyasi ko'rsatilgan:

Java
// org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode ni import qilamiz;
String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
Kotlin
// org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode ni import qilamiz
val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES
val client = WebClient.builder().uriBuilderFactory(factory).build()

Bundan tashqari, DefaultUriBuilderFactory ni to'g'ridan-to'g'ri ham ishlatishingiz mumkin. Bu UriComponentsBuilder dan foydalanishga o'xshaydi, lekin statik fabrika usullari o'rniga, bu haqiqiy nusxa bo'lib, konfiguratsiya va parametrlarni saqlaydi, quyidagi misolda ko'rsatilgan:

Java
String baseUrl = "https://example.com";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
        .queryParam("q", "{q}")
        .build("Westin", "123");
Kotlin
val baseUrl = "https://example.com"
val uriBuilderFactory = DefaultUriBuilderFactory(baseUrl)
val uri = uriBuilderFactory.uriString("/hotels/{hotel}")
        .queryParam("q", "{q}")
        .build("Westin", "123")

URI identifikatorlarini kodlash

Spring MVC va Spring WebFlux

UriComponentsBuilder kodlash uchun ikki darajadagi opsiyalarni ochadi:

  • UriComponentsBuilder#encode(): Avval URI-shablonni oldindan kodlaydi, so'ngra kengaytirishda URI identifikatorlarining o'zgaruvchilarini qat'iy kodlaydi.

  • UriComponents#encode(): URI komponentlarini kodlaydi keyin URI identifikatorining o'zgaruvchilarini kengaytirishdan keyin.

Har ikki opsiya ASCII standarti bo'lmagan belgilar va ruxsat etilmagan belgilarni ekranlash turida o'zgartiradi. Biroq, birinchi variant URI identifikatorlarining o'zgaruvchilarida ko'rinadigan belgilarni ham o'zgartiradi.

";", masalan, yo'lda ruxsat etilgan, lekin rezervasi bor. Birinchi variant URI identifikatorlarining o'zgaruvchilarida ";" ni "%3B" ga o'zgartiradi, lekin URI shablonda emas. Bunga qarshi, ikkinchi variant hech qachon ";" ni o'zgartirmaydi, chunki u yo'lda ruxsat etilgan belgi.

Odatda, birinchi variant kutilgan natijani beradi, chunki u URI identifikatorlarining o'zgaruvchilarini to'liq kodlanadigan ma'lumotlar sifatida hisoblaydi, shu bilan birga ikkinchi variant foydali bo'lishi mumkin, agar URI identifikatorlarining o'zgaruvchilari ataylab rezervasiyalarni o'z ichiga olgan bo'lsa. Ikkinchi variant, shuningdek, agar siz umumiy kodlar o'zgaruvchilarni kengaytirishni istamasangiz, foydali ekanligini ko'rsatadi.

Quyidagi misolda birinchi variant ishlatilgan:

Java
URI uri = UriComponentsBuilder.fromPath("/hotellar ro'yhati/{shahar}")
        .queryParam("q", "{q}")
        .encode()
        .buildAndExpand("Nyu York", "foo+bar")
        .toUri();
// Natija "/hotel%20list/New%20York?q=foo%2Bbar"
Kotlin
val uri = UriComponentsBuilder.fromPath("/hotellar ro'yhati/{shahar}")
        .queryParam("q", "{q}")
        .encode()
        .buildAndExpand("Nyu York", "foo+bar")
        .toUri()
// Natija "/hotel%20list/New%20York?q=foo%2Bbar"

Oldingi misoldagi kodni qisqartirish uchun to'g'ridan-to'g'ri URI identifikatoriga o'tish orqali (bu kodlashni nazarda tutadi), quyidagi misolda ko'rsatilgan:

Java
URI uri = UriComponentsBuilder.fromPath("/hotellar ro'yhati/{shahar}")
        .queryParam("q", "{q}")
        .build("Nyu York", "foo+bar");
Kotlin
val uri = UriComponentsBuilder.fromPath("/hotellar ro'yhati/{shahar}")
        .queryParam("q", "{q}")
        .build("Nyu York", "foo+bar")

Bu yerda yanada ko'proq qisqartirish mumkin, bu to'liq URI-shablon bilan, quyidagi misolda ko'rsatilgan:

Java
URI uri = UriComponentsBuilder.fromUriString("/hotellar ro'yhati/{shahar}?q={q}")
        .build("Nyu York", "foo+bar");
Kotlin
val uri = UriComponentsBuilder.fromUriString("/hotellar ro'yhati/{shahar}?q={q}")
        .build("Nyu York", "foo+bar")

WebClient va RestTemplate URI-shablonlarni kengaytirib, ichki darajada UriBuilderFactory yordamida kodlashadi. Har ikki variant maxsus strategiyani ishlatish orqali konfiguratsiya qilinishi mumkin, quyidagi misolda ko'rsatilgan:

Java
String baseUrl = "https://example.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
// RestTemplate sozlaymiz...
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
// WebClient sozlaymiz...
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
Kotlin
val baseUrl = "https://example.com"
val factory = DefaultUriBuilderFactory(baseUrl).apply {
    encodingMode = EncodingMode.TEMPLATE_AND_VALUES
}
// RestTemplate sozlaymiz...
val restTemplate = RestTemplate().apply {
    uriTemplateHandler = factory
}
// WebClient sozlaymiz...
val client = WebClient.builder().uriBuilderFactory(factory).build()

DefaultUriBuilderFactory ning amalga oshirilishi ichki darajada URI-shablonlarni kengaytirish va kodlash uchun UriComponentsBuilder dan foydalanadi. Fabrika sifatida u kodlashga yondashuvni konfiguratsiya qilish uchun yagona joyni taqdim etadi, bu quyidagi kodlash rejimlaridan biri asosida:

  • TEMPLATE_AND_VALUES: Birinchi variantning yuqorida keltirilgan opsiyasiga muvofiq UriComponentsBuilder#encode() dan foydalanadi, bu URI-shablonni oldindan kodlaydi va kengaytirishda URI identifikatorlarining o'zgaruvchilarini qat'iy kodlaydi.

  • VALUES_ONLY: URI-shablonni kodlamaydi va o'z o'rniga URI identifikatorlarining o'zgaruvchilarini UriUtils#encodeUriVariables orqali qat'iy kodlashni amalga oshiradi, ularni shablonga kengaytirishdan avval.

  • URI_COMPONENT: Ikkinchi variantning yuqoridagi opsiyasiga muvofiq UriComponents#encode() dan foydalanadi, URI o'zgaruvchilarning kengaytirishidan keyin URI identifikator komponentining qiymatini kodlaydi.

  • NONE: Kodlash qo'llanilmaydi.

RestTemplate tarixiy sabablar va orqaga moslik uchun EncodingMode.URI_COMPONENT ga o'rnatilgan. WebClient DefaultUriBuilderFactory ning asosiy qiymati bo'yicha ishga tushadi, u 5.0.x da EncodingMode.URI_COMPONENT dan 5.1 da EncodingMode.TEMPLATE_AND_VALUES ga o'zgartirilgan.

Nisbiy so'rov servleti

Hozirgi so'rovga nisbatan URI identifikatorlarini yaratish uchun ServletUriComponentsBuilder dan foydalanishingiz mumkin, quyidagi misolda ko'rsatilgan:

Java
HttpServletRequest request = ...
// Oyina, xost, port, yo'l va so'rov satridan qayta foydalanishni amalga oshiradi...
URI uri = ServletUriComponentsBuilder.fromRequest(request)
        .replaceQueryParam("accountId", "{id}")
        .build("123");
Kotlin
val request: HttpServletRequest = ...
// Oyina, xost, port, yo'l va so'rov satridan qayta foydalanishni amalga oshiradi...
val uri = ServletUriComponentsBuilder.fromRequest(request)
        .replaceQueryParam("accountId", "{id}")
        .build("123")

Kontekstli yo'lga nisbatan URI identifikatorlarini yaratishingiz mumkin, quyidagi misolda ko'rsatilgan:

Java
HttpServletRequest request = ...
// Oyina, xost, port va kontekstli yo'ldan qayta foydalanishni amalga oshiradi...
URI uri = ServletUriComponentsBuilder.fromContextPath(request)
        .path("/accounts")
        .build()
        .toUri();
Kotlin
val request: HttpServletRequest = ...
// Oyina, xost, port va kontekstli yo'ldan qayta foydalanishni amalga oshiradi...
val uri = ServletUriComponentsBuilder.fromContextPath(request)
        .path("/accounts")
        .build()
        .toUri()

Servisga (masalan, /main/*) nisbatan URI identifikatorlarini yaratishingiz mumkin, quyidagi misolda ko'rsatilgan:

Java
HttpServletRequest request = ...
// Oyina, xost, port, kontekstli yo'l va servis xaritasi prefiksidan qayta foydalanish amalga oshiriladi...
URI uri = ServletUriComponentsBuilder.fromServletMapping(request)
        .path("/accounts")
        .build()
        .toUri();
Kotlin
val request: HttpServletRequest = ...
// Oyina, xost, port, kontekstli yo'l va servis xaritasi prefiksidan qayta foydalanish amalga oshiriladi...
val uri = ServletUriComponentsBuilder.fromServletMapping(request)
        .path("/accounts")
        .build()
        .toUri()
5.1 versiyasidan boshlab, ServletUriComponentsBuilder mijoz tomoni manzilini ko'rsatuvchi Forwarded va X-Forwarded-* sarlavhalaridan kelgan ma'lumotlarni e'tiborsiz qoldiradi. Bunday sarlavhalarni qaytarib olish va ishlatish yoki chiqarib tashlash uchun ForwardedHeaderFilter ni ishlatib ko'ring.

Kontroller havolalari

Spring MVC kontroller metodlariga havolalarni tayyorlash mexanizmiga ega. Masalan, quyidagi MVC kontrolleri havolalar yaratishga imkon beradi:

Java
@Controller
@RequestMapping("/hotels/{hotel}")
public class BookingController {
    @GetMapping("/bookings/{booking}")
    public ModelAndView getBooking(@PathVariable Long booking) {
        // ...
    }
}
Kotlin
@Controller
@RequestMapping("/hotels/{hotel}")
class BookingController {
    @GetMapping("/bookings/{booking}")
    fun getBooking(@PathVariable booking: Long): ModelAndView {
        // ...
    }
}

Quyidagi misolda ko'rsatilganidek, metod nomini ko'rsatgan holda havolani tayyorlashingiz mumkin:

Java
UriComponents uriComponents = MvcUriComponentsBuilder
    .fromMethodName(BookingController.class, "getBooking", 21).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
Kotlin
val uriComponents = MvcUriComponentsBuilder
    .fromMethodName(BookingController::class.java, "getBooking", 21).buildAndExpand(42)
val uri = uriComponents.encode().toUri()

Oldingi misolda, biz metodning haqiqiy parametr qiymatlarini (bu yerda uzun qiymat: 21) yo'l o'zgaruvchisi sifatida foydalanish uchun URL-manzilga qo'shamiz. Bundan tashqari, biz har qanday qolgan URI identifikatorlar o'zgaruvchilarini to'ldirish uchun 42 qiymatini ko'rsatamiz, masalan, tur tipidagi darajadagi so'rovni xaritalashdan meros qilingan hotel o'zgaruvchisi. Agar metodda ko'proq argumentlar mavjud bo'lsa, biz URL-manzil uchun foydalanilmasligini istamasak, nol qiymatini o'rnatib qo'yishimiz mumkin. Umuman olganda, faqat @PathVariable va @RequestParam bilan annotatsiyalangan argumentlar URL-manzilni qurish uchun ahamiyatga ega.

MvcUriComponentsBuilder ni ishlatishning qo'shimcha usullari mavjud. Masalan, Metod nomiga muvofiq kontroller metodiga murojaat qilishdan qochish uchun, quyidagi misolda ko'rsatilganidek (misol MvcUriComponentsBuilder.on uchun statik importni nazarda tutadi), sinov uchun o'xshash usulni ishlatgan holda foydalanishingiz mumkin:

Java
UriComponents uriComponents = MvcUriComponentsBuilder
    .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
Kotlin
val uriComponents = MvcUriComponentsBuilder
    .fromMethodCall(on(BookingController::class.java).getBooking(21)).buildAndExpand(42)
val uri = uriComponents.encode().toUri()
Kontroller metodlarining imzolari fromMethodCall yordamida havolalar yaratish uchun ishlatilishi mumkinligi nazarda tutilgan, chunki ularning konstruktsiyasi cheklangan. Parametrlar imzolari to'g'ri bo'lishi kerakligi bilan bir qatorda, texnik cheklovlar mavjud (ya'ni, havolalar ishlab chiqaruvchi chaqirilganda, ularning natijalarini tezda olish va dinamik proksi yaratish). Ayniqsa, String ni qaytarish turidagi oddiy foydalanish (masalan, ko'rinish nomlari uchun) burada ish bermaydi. Buning o'rniga ModelAndView yoki hatto oddiy Object dan foydalaning (bunda qaytarish qiymati String bo'lishi mumkin).

Oldingi misollarda MvcUriComponentsBuilder ning statik metodlari ishlatilgan. Ichki darajada, ular hozirgi so'rovning oyina, xost, port, kontekst yo'li va servlet yo'li asosida bazaviy URL tayyorlash uchun ServletUriComponentsBuilder ga murojaat qiladi. Bu ko'p holatlar uchun yaxshi ishlaydi. Biroq, ba'zida bu etarli bo'lmasligi mumkin. Misol uchun, so'rov kontekstidan tashqarida bo'lishingiz mumkin (masalan, havolalarni tayyorlaydigan paket jarayonida) yoki, ehtimol, yo'l prefiksini qo'shishingiz kerak (masalan, so'rov yo'lidan o'chirilgan va havolalarda yana qo'shilmeli bo'lgan region qiymatlari prefiksi).

Bunday holatlar uchun, fromXxx statik metodlarining orttirilgan versiyalaridan foydalanishingiz mumkin, ular UriComponentsBuilder ni bazaviy URL uchun ishlatadilar. Shuningdek, bazaviy URL bilan MvcUriComponentsBuilder nusxasini yaratib, keyin withXxx nomli, nusxaga asoslangan metodlardan foydalanishingiz mumkin. Masalan, quyidagi listingda withMethodCall dan foydalanadi:

Java
UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath().path("/en");
MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);
builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
Kotlin
val base = ServletUriComponentsBuilder.fromCurrentContextPath().path("/en")
val builder = MvcUriComponentsBuilder.relativeTo(base)
builder.withMethodCall(on(BookingController::class.java).getBooking(21)).buildAndExpand(42)
val uri = uriComponents.encode().toUri()
5.1 versiyasidan boshlab, MvcUriComponentsBuilder mijoz tomoni manzilini ko'rsatuvchi Forwarded va X-Forwarded-* sarlavhalaridan kelgan ma'lumotlarni e'tiborsiz qoldiradi. Bunday sarlavhalarni qaytarib olish va ishlatish yoki chiqarib tashlash uchun ForwardedHeaderFilter ni ishlatib ko'ring.

Ko'rinishdagi havolalar

Thymeleaf, FreeMarker yoki JSP kabi ko'rinishlarda, har bir so'rovni xaritalash uchun noaniq yoki aniq tayinlangan nomga tayanish orqali, annostatsiyalangan kontrollerlarga havolalar yaratish mumkin.

Quyidagi misolni ko'rib chiqing:

Java
@RequestMapping("/people/{id}/addresses")
public class PersonAddressController {
    @RequestMapping("/{country}")
    public HttpEntity<PersonAddress> getAddress(@PathVariable String country) { ... }
}
Kotlin
@RequestMapping("/people/{id}/addresses")
class PersonAddressController {
    @RequestMapping("/{country}")
    fun getAddress(@PathVariable country: String): HttpEntity<PersonAddress> { ... }
}

Yuqoridagi kontrollerni hisobga olgan holda, quyidagi tarzda JSP dan havolani tayyorlashingiz mumkin:

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
...
<a href="${s:mvcUrl('PAC#getAddress').arg(0,'US').buildAndExpand('123')}">Manzili olish</a>

Yuqoridagi misolda biz Spring'ning tag library'dagi mvcUrl funktsiyasiga tayanmoqdamiz (ya'ni META-INF/spring.tld), lekin o'z funktsiyangizni aniqlash yoki boshqa shablon texnologiyalari uchun o'xshashini tayyorlash ham juda oson.

Bunda har bir @RequestMapping annotatsiyasi ishga tushganda, agar nomlar mos kelmasa, maxsus nomlash strategiyasini amalga oshirishingiz mumkin.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION