JavaRush /Kurslar /All lectures for UZ purposes /Spring Boot va Web MVC, qism 3

Spring Boot va Web MVC, qism 3

All lectures for UZ purposes
Daraja , Dars
Mavjud

Shablonizatorlar

REST veb-xizmatlari bilan bir qatorda, Spring MVC-dan dinamik HTML-tarkibni boshqarish uchun ham foydalanishingiz mumkin. Spring MVC turli shablon texnologiyalarini qo'llab-quvvatlaydi, jumladan Thymeleaf, FreeMarker va JSP. Bundan tashqari, boshqa ko'plab shablonizatorlar Spring MVC bilan o'zlarining integratsiya vositalariga ega.

Spring Boot quyidagi shablonizatorlar uchun avtoko'ngiroqni qo'llab-quvvatlaydi:

Agar ushbu shablonizatorlardan biri default konfiguratsiya bilan ishlatilsa, unda shablonlar avtomatik ravishda src/main/resources/templates dan tanlanadi.

Dastur qanday amalga oshirilishiga qarab, IDE classpath-ni turli tartibda joylashtirishi mumkin. Dasturning asosiy metodidan IDEda ishga tushirish Maven yoki Gradle bilan, yoki uning arxivlangan jar-faylidan ishga tushirilganda boshqacha tartiblashtirishga olib keladi. Bu Spring Boot tomonidan kutilayotgan shablon topilmasligiga olib kelishi mumkin. Agar shunday muammo yuzaga kelsa, classpath tartibini o'zgartirib, modul klasslari va resurslarini birinchi o'ringa qo'shishingiz mumkin.

Xatolarni qayta ishlash

Odatiy holatda Spring Boot barcha xatolarni mos ravishda boshqaradigan /error ko'rsatadi va bu servlet konteynerida "global" xato sahifasi sifatida ro'yxatdan o'tkaziladi. Mashina mijozlari uchun bu xatolarning tafsilotlarini, HTTP status kodini va istisno xabarnomasini o'z ichiga olgan JSON shaklida javob hosil qiladi. Brauzer mijozlari uchun HTML formatida o'sha ma'lumotlarni vizualizatsiya qiluvchi "whitelabel" xato tasviri mavjud (uni sozlash uchun errorni yechadigan View qo'shing).

Agar xatolarni boshqarishning default logikasini maxsuslashtirish kerak bo'lsa, server.error xususiyatlarini o'rnatishingiz mumkin.

Odatdagi logikani to'liq almashtirish uchun ErrorController ni amalga oshirishingiz va bu turdagi bean aniqlanishini ro'yxatdan o'tkazishingiz yoki mavjud mexanizmni foydalanish uchun ErrorAttributes turidagi bean qo'shishingiz va lekin uning mazmunini o'zgartirishingiz mumkin.

BasicErrorController maxsus ErrorController uchun asosiy klass sifatida foydalanish mumkin. Bu, ayniqsa, yangi tarkib turini boshqarish kerak bo'lganda qulay bo'ladi (odatiy boshqaruvchi faqat text/html ni boshqaradi va qolgan barcha narsalar uchun zaxira imkoniyatini beradi). Buning uchun BasicErrorController ni kengaytiring, produces atributi ega @RequestMapping anotatsiyasiga ega ochiq metod qo'shing va yangi turdagi bean yarating.

Bundan tashqari, aniqlangan boshqaruvchi uchun qaytariladigan JSON-hujjatni yoki/yoki istisno turini tuzish uchun @ControllerAdvice bilan anotatsiyalangan klassni ham aniqlashingiz mumkin, quyidagi misolda ko'rsatib o'tilganidek:

Java
import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @ControllerAdvice(basePackageClasses = SomeController.class) public class MyControllerAdvice extends ResponseEntityExceptionHandler { @ResponseBody @ExceptionHandler(MyException.class) public ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) { HttpStatus status = getStatus(request); return new ResponseEntity<>(new MyErrorBody(status.value(), ex.getMessage()), status); } private HttpStatus getStatus(HttpServletRequest request) { Integer code = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); HttpStatus status = HttpStatus.resolve(code); return (status != null) ? status : HttpStatus.INTERNAL_SERVER_ERROR; } } 
Kotlin
import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.ControllerAdvice import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.ResponseBody import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler import javax.servlet.RequestDispatcher import javax.servlet.http.HttpServletRequest @ControllerAdvice(basePackageClasses = [SomeController::class]) class MyControllerAdvice : ResponseEntityExceptionHandler() { @ResponseBody @ExceptionHandler(MyException::class) fun handleControllerException(request: HttpServletRequest, ex: Throwable): ResponseEntity<*> { val status = getStatus(request) return ResponseEntity(MyErrorBody(status.value(), ex.message), status) } private fun getStatus(request: HttpServletRequest): HttpStatus { val code = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE) as Int val status = HttpStatus.resolve(code) return status ?: HttpStatus.INTERNAL_SERVER_ERROR } } 

Yuqoridagi misolda, agar MyException xatosi SomeController bilan bir xil paketda aniqlangan boshqaruvchi tomonidan yaratilsa, ErrorAttributes tasviri o'rniga MyErrorBody POJO ob'ektining JSON tasviri ishlatiladi.

Ba'zi hollarda boshqaruvchi darajasida qayta ishlangan xatolar metrik infratuzilmasida ro'yxatga olinmaydi. Iloji bo'lsa, bunday istisnolarni metrik so'rovlarida qayd etish uchun, qayta ishlangan istisnoni so'rov atributi sifatida sozlash mumkin:

Java
import javax.servlet.http.HttpServletRequest; import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; @Controller public class MyController { @ExceptionHandler(CustomException.class) String handleCustomException(HttpServletRequest request, CustomException ex) { request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex); return "errorView"; } } 
Kotlin
import org.springframework.boot.web.servlet.error.ErrorAttributes import org.springframework.stereotype.Controller import org.springframework.web.bind.annotation.ExceptionHandler import javax.servlet.http.HttpServletRequest @Controller class MyController { @ExceptionHandler(CustomException::class) fun handleCustomException(request: HttpServletRequest, ex: CustomException?): String { request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex) return "errorView" } } 

Maxsus xato sahifalari

Agar ma'lum bir holat kodining maxsus HTML xato sahifasini ekranga chiqarish kerak bo'lsa, faylni /error katalogiga qo'shishingiz mumkin. Xato sahifalari statik HTML (ya'ni har qanday statik resurs kataloglariga qo'shilgan) yoki shablonlardan foydalangan holda qurilgan bo'lishi mumkin. Fayl nomi to'liq holat kodi yoki seriya maskasini o'z ichiga olishi kerak.

Masalan, statik HTML fayli bilan 404ni ko'rsatish uchun katalog tuzilishi quyidagicha bo'lishi kerak:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

Barcha 5xx xatolarni FreeMarker shabloni yordamida ko'rsatish uchun katalog tuzilishi quyidagicha bo'lishi kerak:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftlh
             +- <other templates>

Murakkab tasvirlar uchun ErrorViewResolver interfeysini amalga oshiruvchi beanlar ham qo'shishingiz mumkin, quyidagi misolda ko'rsatib o'tilganidek:

Java
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.ModelAndView; public class MyErrorViewResolver implements ErrorViewResolver { @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { // Xohlagan modelni qaytarish uchun so'rov yoki statusdan foydalanamiz if (status == HttpStatus.INSUFFICIENT_STORAGE) { // Bu yerda biz maxsus model qiymatini qo'shishimiz mumkin new ModelAndView("myview"); } return null; } } 
Kotlin
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver import org.springframework.http.HttpStatus import org.springframework.web.servlet.ModelAndView import javax.servlet.http.HttpServletRequest class MyErrorViewResolver : ErrorViewResolver { override fun resolveErrorView(request: HttpServletRequest, status: HttpStatus, model: Map<String, Any>): ModelAndView? { // Xohlagan modelni qaytarish uchun so'rov yoki statusdan foydalanamiz if (status == HttpStatus.INSUFFICIENT_STORAGE) { // Bu yerda biz maxsus model qiymatini qo'shishimiz mumkin return ModelAndView("myview") } return null } } 

Bundan tashqari, odatiy ExceptionHandler anotatsiyasi bilan belgilangan metodlar va @ControllerAdvice anotatsiyasi kabi oddiy Spring MVC funksiyalaridan foydalanishingiz mumkin. ErrorController keyin barcha ishlov berilmagan istisnolarni ushlaydi.

Spring MVCdan tashqarida xato sahifalarini ko'rsatish

Spring MVCni ishlatmaydigan dasturlar uchun ErrorPagesni to'g'ridan-to'g'ri ro'yxatdan o'tkazish uchun ErrorPageRegistrar interfeysidan foydalanishingiz mumkin. Ushbu abstraktsiya bevosita pastki darajadagi o'rnatilgan servlet konteyneri bilan ishlaydi va sizda Spring MVC uchun DispatcherServlet mavjud bo'lmagan holatlarda ham yaxshi ishlaydi.

Java
import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.ErrorPageRegistrar; import org.springframework.boot.web.server.ErrorPageRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; @Configuration(proxyBeanMethods = false) public class MyErrorPagesConfiguration { @Bean public ErrorPageRegistrar errorPageRegistrar() { return this::registerErrorPages; } private void registerErrorPages(ErrorPageRegistry registry) { registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400")); } } 
Kotlin
import org.springframework.boot.web.server.ErrorPage import org.springframework.boot.web.server.ErrorPageRegistrar import org.springframework.boot.web.server.ErrorPageRegistry import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.HttpStatus @Configuration(proxyBeanMethods = false) class MyErrorPagesConfiguration { @Bean fun errorPageRegistrar(): ErrorPageRegistrar { return ErrorPageRegistrar { registry: ErrorPageRegistry -> registerErrorPages(registry) } } private fun registerErrorPages(registry: ErrorPageRegistry) { registry.addErrorPages(ErrorPage(HttpStatus.BAD_REQUEST, "/400")) } } 
Agar siz Filter bilan qayta ishlanadigan yo'lni ishlatib ErrorPageni ro'yxatdan o'tkazayotgan bo'lsangiz (Springga tegishli bo'lmagan ba'zi veb-freymvorklar uchun umumiy, masalan, Jersey va Wicket), unda Filter ERROR dispetcheri sifatida aniq ro'yxatga olinishi kerak, quyidagi misolda ko'rsatib o'tilgan:
Java
import java.util.EnumSet; import javax.servlet.DispatcherType; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyFilterConfiguration { @Bean public FilterRegistrationBean<MyFilter> myFilter() { FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(new MyFilter()); // ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); return registration; } } 
Kotlin
import org.springframework.boot.web.servlet.FilterRegistrationBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import java.util.EnumSet import javax.servlet.DispatcherType @Configuration(proxyBeanMethods = false) class MyFilterConfiguration { @Bean fun myFilter(): FilterRegistrationBean<MyFilter> { val registration = FilterRegistrationBean(MyFilter()) // ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType::class.java)) return registration } } 

Shuni yodda tutingki, FilterRegistrationBean odatda ERROR dispetcher turini o'z ichiga olmaydi.

WAR joylashtirishda xatolarni boshqarish

Servlet konteynerida joylashtirilganda Spring Boot xato kodiga mos keladigan xato sahifasiga so'rovni yo'naltirish uchun o'z xato sahifasi filtrini ishlatadi. Bu zarur, chunki servlet spetsifikatsiyasi xato sahifalarini ro'yxatdan o'tkazish uchun APIni ta'minlamaydi. Sizning war faylingizni joylashtirayotgan konteyner va dasturning foydalanayotgan texnologiyalariga qarab qo'shimcha konfiguratsiya talab qilinishi mumkin.

Xato sahifa filtri javob hali tasdiqlanmaganida to'g'ri xato sahifasiga so'rovni yo'naltirishi mumkin. Odatiy bo'lib, WebSphere Application Server 8.0 va undan keyingi versiyalar javobni servlet xizmat metodi muvaffaqiyatli yakunlangandan so'ng tasdiqlaydi. Bu xatti-harakatni com.ibm.ws.webcontainer.invokeFlushAfterService parametrini false ga o'rnatish orqali o'chirishingiz kerak.

Agar siz Spring Securitydan foydalanayotgan bo'lsangiz va xato sahifasida printsipga kirishni xohlasangiz, Spring Security filtrini xatolarni yuborishda chaqirilishi uchun sozlashingiz kerak. Buning uchun spring.security.filter.dispatcher-types xususiyatini async, error, forward, request ga o'rnating.

CORS qo'llab-quvvatlashi

Turli manbalar orasidagi resurslarni almashish (CORS) W3C spetsifikatsiyasi bo'lib, ko'pgina brauzerlar tomonidan amalga oshirilgan bo'lib, qanday turdagi domensiz so'rovlar ruxsat etilishini moslashuvchan tarzda aniqlash imkonini beradi, va u IFRAME yoki JSONP kabi kamroq xavfsiz va kamroq samarali yondashuvlarni almashtirish niyatida.

Versiya 4.2dan boshlab, Spring MVC CORSni qo'llab-quvvatlaydi. Spring Boot dasturida @CrossOrigin annotatsiyalari bilan CORS konfiguratsiyasi uchun boshqaruvchi metodini ishlatish maxsus konfiguratsiyani talab qilmaydi. Global CORS konfiguratsiyasini addCorsMappings(CorsRegistry) metodi sozlangan WebMvcConfigurer beani ro'yxatdan o'tkazish orqali aniqlash mumkin, quyidagi misolda ko'rsatilganidek:

Java
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration(proxyBeanMethods = false) public class MyCorsConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } } 
Kotlin
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.web.servlet.config.annotation.CorsRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurer @Configuration(proxyBeanMethods = false) class MyCorsConfiguration { @Bean fun corsConfigurer(): WebMvcConfigurer { return object : WebMvcConfigurer { override fun addCorsMappings(registry: CorsRegistry) { registry.addMapping("/api/**") } } } } 
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION