JavaRush /Курсы /All lectures for AM purposes /Բացառություններ

Բացառություններ

All lectures for AM purposes
1 уровень , 595 лекция
Открыта

Անոտացված @Controller և @ControllerAdvice ունեցող կլասերը կարող են ունենալ մեթոդներ, որոնք նշված են @ExceptionHandler-ով՝ բացառությունները կարգավորելու համար, ինչպես ցույց է տրված հետևյալ օրինակով:

Java
@Controller
public class SimpleController {
    // ...
    @ExceptionHandler
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}
Kotlin
@Controller
class SimpleController {
    // ...
    @ExceptionHandler
    fun handle(ex: IOException): ResponseEntity<String> {
        // ...
    }
}

Բացառությունը կարող է համընկնել բարձր մակարդակի տարածված բացառության հետ (օրինակ, ուղղակիորեն գեներացված IOException) կամ կարող է լինել ներսում որպես պատճառ բացառության-փաթեթի մեջ (օրինակ, IOException, որը փաթեթված է IllegalStateException ներսում): Սկսած 5.3-ից, դա կարող է համընկնել ցանկացած մակարդակի պատճառների վրա, մինչդեռ նախկինում միայն անմիջական պատճառը էր հաշվի առնվում:

Համընկնող բացառությունների տեսակների համար ցանկալի է հայտարարել նպատակային բացառությունը որպես մեթոդի արգումենտ, ինչպես ցույց է տրված նախորդ օրինակում: Մի քանի բացառությունների համընկնելու դեպքում, սովորաբար գերադասելի է է արմատային բացառության համընկնումը, քան պատճառի բացառության համընկնումը: Հատկապես, ExceptionDepthComparator-ը օգտագործվում է բացառությունները տեսակավորելու նրանց խորությամբ գեներացված բացառության տիպից:

Բացի այդ, անոտացիայի հայտարարումը կարող է սահմանափակել բացառությունների տեսակներ, որոնք պետք է համընկնեն, ինչպես ցույց է տրված հետևյալ օրինակում:

Java
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(IOException ex) {
    // ...
}
Kotlin
@ExceptionHandler(FileSystemException::class, RemoteException::class)
fun handle(ex: IOException): ResponseEntity<String> {
    // ...
}

Կարող եք նույնիսկ օգտագործել հատուկ բացառությունների տեսակների ցանկ շատ ընդհանուր արգումենտային ստորագրությամբ, ինչպես ցույց է տրված հետևյալ օրինակում:

Java
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(Exception ex) {
    // ...
}
Kotlin
@ExceptionHandler(FileSystemException::class, RemoteException::class)
fun handle(ex: Exception): ResponseEntity<String> {
    // ...
}

Արմատային և պատճառի բացառությունների համընկնումների միջև տարբերությունը կարող է զարմացնել:

IOException-ի օրինակում, որը ցույց է տրված վերևում, մեթոդը ընդհանուր առմամբ կանչվում է FileSystemException կամ RemoteException փաստացի օրինակի օգտագործմամբ որպես արգումենտ, քանի որ երկուսն էլ ընդլայնվում են IOException-ից: Սակայն, եթե ցանկացած նման համընկնող բացառություն տարածվում է փաթեթող բացառության ներսում, որը ինքն իրեն պահում է որպես IOException, ապա փոխանցվող բացառության օրինակը հենց այդ փաթեթող բացառությունն է:

handle(Exception) տարբերակում աշխատանքի տրամաբանությունը նույնիսկ ավելի պարզ է: Կանչվում է փաթեթող բացառությամբ փաթեթավորման սցենարում, իսկ փաստացի համընկնող բացառությունը կարող է գտնվել ex.getCause()-ի օգնությամբ այս դեպքում: Փոխանցված բացառությունը հանդիսանում է FileSystemException կամ RemoteException փաստացի օրինակը միայն այն դեպքում, եթե դրանք գեներացվում են որպես բարձր մակարդակի բացառություններ:

Հաճախ առաջարկվում է որքան հնարավոր է կոնկրետ լինել արգումենտների ստորագրությունում՝ նվազեցնելու համար արմատային և պատճառի բացառությունների տեսակների միջև անհամապատասխանության հավանականությունը: Հաշվի առեք մի քանի համընկնումներով մեթոդը բաժանելու առանձին մեթոդներին, որոնք անոտացված են @ExceptionHandler և որոնցից յուրաքանչյուրն ունի մեկ բացառության հատուկ տեսակ՝ իր ստորագրությամբ:

Մի քանի @ControllerAdvice անոտացիաների կոնֆիգուրացիայում մենք խորհուրդ ենք տալիս հայտարարել հիմնական արմատային բացառությունների քարտեզները @ControllerAdvice անոտացիայով համապատասխան առաջնահերթության կարգով: Թեպետ արմատային բացառությունների համընկնումը գերադասելի է, քան պատճառի բացառության համընկնումը, որոշումը տեղի է ունենում տվյալ կոնտրոլերի կամ @ControllerAdvice-ով անոտացված դասի մեթոդների շրջանում: Սա նշանակում է, որ պատճառի համընկնումը @ControllerAdvice-ով բարձր առաջնահերթությամբ նախընտրելի է ցանկացած համընկնումից (օրինակ, արմատային) @ControllerAdvice-ով ավելի ցածր առաջնահերթությամբ:

Վերջապես, @ExceptionHandler անոտացված մեթոդի իրականացումը կարող է հրաժարվել զբաղվել տվյալ բացառության օրինակով՝ կրկին գեներացնելով այն սկզբնական ձևով: Սա օգտակար է այն դեպքերում, երբ ձեզ հետաքրքրում են բացառապես արմատային մակարդակի կամ որոշակի կոնտեքստում համընկնումների, որոնք չեն կարող որոշվել ստատիկորեն, համընկնումները: Կրկնակի գեներացված բացառությունը տարածվում է մնացած լուծման շղթայի ընթացքում, կարծես թե առաջինը չէր համընկնում @ExceptionHandler-ով նշված մեթոդի հետ:

Spring MVC-ում @ExceptionHandler անոտացիայով մեթոդների աջակցությունը կառուցված է DispatcherServlet մակարդակում, HandlerExceptionResolver մեխանիզմի վրա:

Մեթոդի արգումենտներ

@ExceptionHandler անոտացված մեթոդները աջակցում են հետևյալ արգումենտներին:

Մեթոդի արգումենտներ Նկարագրություն

Բացառության տեսակ

Վերահասցադրում է գեներացված բացառությանը:

HandlerMethod

Տրամադրում է մուտք դեպի այն կոնտրոլերի մեթոդը, որը գեներացրել է բացառությունը:

WebRequest, NativeWebRequest

Տիպիզացված մուտք դեպի հարցման պարամետրերը և հարցման և սեսիայի ատրիբուտները՝ առանց օգտվելու անմիջականորեն Servlet API-ից:

javax.servlet.ServletRequest, javax.servlet.ServletResponse

Ընտրեք հարցման կամ պատասխանի որևէ կոնկրետ տեսակ (օրինակ, ServletRequest կամ HttpServletRequest, կամ MultipartRequest կամ MultipartHttpServletRequest Spring-ից):

javax.servlet.http.HttpSession

Ապահովում է սեսիայի առկայությունը: Հետևաբար, այդպիսի արգումենտը երբեք չի կարող լինել null:
Խնդրում ենք նկատի ունենալ, որ սեսիայի մուտքը թելահոսանային չէ: Հաշվի առեք RequestMappingHandlerAdapter օրինակի synchronizeOnSession դրոշի նշանակումը true արժեքին, եթե թույլատրված է սեսիայի միաժամանակյա մի քանի հարցումներին մուտք գործել:

java.security.Principal

Ընթացիկ վավերացված օգտատերը՝ հնարավոր է, Principal-ի կոնկրետ իրականացման դասը, եթե նա հայտնի է:

HttpMethod

Հարցման HTTP մեթոդը:

java.util.Locale

Հարցման ընթացիկ տեղայնությունները՝ որոշված ամենա կոնկրետ մատչելի LocaleResolver-ից՝ ըստ էության կոնֆիգուրացված LocaleResolver կամ LocaleContextResolver:

java.util.TimeZone, java.time.ZoneId

Ժամային գոտին, կապված ընթացիկ հարցման հետ, որոշված LocaleContextResolver-ով:

java.io.OutputStream, java.io.Writer

Ապահովում է մուտք դեպի բուն պատասխանի մարմինը, ինչպես նախատեսված է Servlet API-ի միջոցով:

java.util.Map, org.springframework.ui.Model, org.springframework.ui.ModelMap

Ապահովում է մուտք դեպի մոդելի՝ սխալի պատասխանը մատչելի դարձնելու համար: Միշտ դատարկ է:

RedirectAttributes

Նշեք այն ատրիբbutները, որոնք օգտագործվում են վերահղման դեպքում՝ (որոնք ավելացվում են հարցման տողում) և flash ատրիբուտները ժամանակավոր պահպանման համար մինչև վերահղման հարցման ստացավը:

@SessionAttribute

Նպատակ ունի ապահովել մուտք դեպի սեսիայի ցանկացած ատրիբուտ, ի տարբերություն մոդելի ատրիբուտների, որոնք պահվում են սեսիայով ՝ հասկանալի դարձնելու համար @SessionAttributes անոտացիա հայտարարման արդյունքում դասի մակարդակում:

@RequestAttribute

Նպատակ ունի ապահովել մուտք դեպի հարցման ատրիբուտները:

Վերադարձվող արժեքներ

@ExceptionHandler անոտացիայով մեթոդները աջակցում են հետևյալ վերադարձվող արժեքներին:

Return value Նկարագրություն

@ResponseBody

Վերադարձվող արժեվորումը փոխակերպվում է HttpMessageConverter օրինակներով և գրվում է պատասխանում:

HttpEntity<B>, ResponseEntity<B>

Վերադարձվող արժեվորմա նշում է, որ ամբողջ պատասխանը (ներառյալ HTTP վերնագրերը և մարմինը) փոխակերպվում է HttpMessageConverter օրինակներով և գրվում է պատասխան:

String

Դիտման անունը, որը պետք է ճանաչվի ViewResolver իրականացման միջոցով և օգտագործվի մեկտեղով անուղղակի մոդելի հետ՝ որոշված հրամանային օբյեկտներով և @ModelAttribute անոտացիայով մեթոդններով: Մեթոդը, ինչպես նաև, կարող է ծրագրավորել մոդել, հայտարելով Model արգումենտը (նկարագրած վերևում):

View

View առարկան, որը նախատեսված է վիզուալիզացիայի համար, մեկտեղով անուղղակի մոդելի հետ՝ որոշված հրամանային օբյեկտներով և @ModelAttribute անոտացիայով մեթոդններով: Մեթոդը կարող է, ինչպես նաև, ծրագրավորել մոդել, հայտարելով Model արգումենտը (նկարագրած վերևում):

java.util.Map, org.springframework.ui.Model

Ատրիբուտներ, որը պետք է ավելացնենք անուղղակի մոդելին՝ դիտման անունով, անուղղակի որոշված RequestToViewNameTranslator-ով:

@ModelAttribute

Ատրիբուտը, որը ավելացված է մոդելում՝ դիտման անունով, անուղղակի սահմանված RequestToViewNameTranslator-ով:

Խնդրում ենք նկատի ունենալ, որ @ModelAttribute անոտացիան կամընտիր է: Տես "Ցանկացած այլ վերադարձվող արժեք" բաժինը այս աղյուսակի վերջում:

ModelAndView object

Օգտագործված է տեսքի և մոդելի ատրիբուտներին և, անհրաժեշտության դեպքում, պատասխանի կարգավիճակին:

void

Համարվում է, որ void վերադարձով (կամ վերադարձվող արժեվորմա null) մեթոդը ամբողջովին իրականացրել է պատասխանը, եթե նա նույնպես ունի ServletResponse կամ OutputStream արգումենտ, կամ @ResponseStatus անոտացիա: Նույնը ճիշտ է, եթե կոնտրոլերը կատարել է ETag կամ ժամանակային կնիքի lastModified հաջողված ստուգումը:

Եթե վերը նշվածներից մեկը ճիշտ չէ, ապա void վերադարձավի տիպը կարող է նաև նշանակել «առանց պատասխանի բալադի»՝ REST կոնտրոլերի համար կամ ըստ նախընտրելի դիտման անունը՝ HTML կոնտրոլերի համար:

Ցանկացած այլ վերադարձվող արժեք

Եթե վերադարձվող արժեքը չի համապատասխանեցվում վերոնշյալներից ոչ մեկին և պարզ տիպ չէ (ինչպես ցույց է տրված BeanUtils#isSimpleProperty), ապա դա կանխադրված է որպես մոդելի ատրիբուտ, որը պետք է ավելացնենք մոդելին: Եթե դա պարզ տիպ է, ապա այն մնում է չվճռված:

Բացառությունների կառավարումն REST API-ի ներսում

REST ծառայությունների ընդհանուր պահանջն է սխալի տեղեկատվությունը ներառել պատասխանի մարմնում: Spring Framework-ը ինքնաբերաբար դա չի կատարում, քանի որ սխալի տեղեկատվութան ներկայացումը պատասխանի մարմնում կախված է կոնկրետ հավելվածից: Սակայն, @RestController անոտացիայով մեթոդները կարող են օգտվել @ExceptionHandler-ով նշված մեթոդների՝ վերադարձվող արժեքով ResponseEntity կարգավիճակի և պատասխանի մարմնի կարգավորման համար: Այդպիսի մեթոդները նաև կարող են հայտարարել @ControllerAdvice-ով անոտացված դասերում, որպեսզի դրանք կիրառվեն գլոբալ:

Հավելվածներ, որոնք իրականացնում են գլոբալ բացառությունների կառավարում՝ սխալի մանրամասն նկարագրությամբ պատասխանի մարմնում, պետք է հաշվի առնել ResponseEntityExceptionHandler ընդլայնման հնարավորությունը, որը ապահովում է բացառությունների կարգավորում Spring MVC-ում և տրամադրում է միջակներ՝ պատասխանի մարմինը կարգավորելու համար: Այս նպատակի համար ստեղծեք ResponseEntityExceptionHandler իջած դաս, այն.annotate @ControllerAdvice ընտանիքին, վերախմբագրեք անհրաժեշտ մեթոդները և հայտարարեք այն որպես Spring bean:

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ