欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入了解SpringBoot中@ControllerAdvice的介紹及三種用法

 更新時間:2023年02月06日 09:25:06   作者:Ethan.Han  
這篇文章主要為大家詳細介紹了SpringBoot中@ControllerAdvice的介紹及三種用法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

淺析@ControllerAdvice

首先,ControllerAdvice本質(zhì)上是一個Component,因此也會被當成組建掃描,一視同仁,掃掃掃。

然后,我們來看一下此類的注釋:

這個類是為那些聲明了(@ExceptionHandler、@InitBinder@ModelAttribute注解修飾的)方法的類而提供的專業(yè)化的@Component , 以供多個 Controller類所共享。

說白了,就是aop思想的一種實現(xiàn),你告訴我需要攔截規(guī)則,我?guī)湍惆阉麄償r下來,具體你想做更細致的攔截篩選和攔截之后的處理,你自己通過@ExceptionHandler、@InitBinder@ModelAttribute這三個注解以及被其注解的方法來自定義。

初定義攔截規(guī)則:

ControllerAdvice 提供了多種指定Advice規(guī)則的定義方式,默認什么都不寫,則是Advice所有Controller,當然你也可以通過下列的方式指定規(guī)則

比如對于 String[] value() default {} , 寫成@ControllerAdvice("org.my.pkg") 或者 @ControllerAdvice(basePackages="org.my.pkg"), 則匹配org.my.pkg包及其子包下的所有Controller,當然也可以用數(shù)組的形式指定,如:@ControllerAdvice(basePackages={"org.my.pkg", "org.my.other.pkg"}), 也可以通過指定注解來匹配,比如我自定了一個 @CustomAnnotation 注解,我想匹配所有被這個注解修飾的 Controller, 可以這么寫:@ControllerAdvice(annotations={CustomAnnotation.class})

還有很多用法,這里就不全部羅列了。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {

	@AliasFor("basePackages")
	String[] value() default {};

	@AliasFor("value")
	String[] basePackages() default {};

	Class<?>[] basePackageClasses() default {};

	Class<?>[] assignableTypes() default {};

	Class<? extends Annotation>[] annotations() default {};

}

1.處理全局異常

@ControllerAdvice 配合 @ExceptionHandler 實現(xiàn)全局異常處理

用于在特定的處理器類、方法中處理異常的注解

接收Throwable類作為參數(shù),我們知道Throwable是所有異常的父類,所以說,可以自行指定所有異常

比如在方法上加:@ExceptionHandler(IllegalArgumentException.class),則表明此方法處理

IllegalArgumentException 類型的異常,如果參數(shù)為空,將默認為方法參數(shù)列表中列出的任何異常(方法拋出什么異常都接得住)。

下面的例子:處理所有IllegalArgumentException異常,域中加入錯誤信息errorMessage 并返回錯誤頁面error

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    public ModelAndView handleException(IllegalArgumentException e){
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("errorMessage", "參數(shù)不符合規(guī)范!");
        return modelAndView;
    }
}

2.預設全局數(shù)據(jù)

@ControllerAdvice 配合 @ModelAttribute 預設全局數(shù)據(jù)

我們先來看看 ModelAttribute注解類的源碼

/**
 * Annotation that binds a method parameter or method return value
 * to a named model attribute, exposed to a web view. Supported
 * for controller classes with {@link RequestMapping @RequestMapping}
 * methods.
 * 此注解用于綁定一個方法參數(shù)或者返回值到一個被命名的model屬性中,暴露給web視圖。支持在
 * 在Controller類中注有@RequestMapping的方法使用(這里有點拗口,不過結(jié)合下面的使用介紹
 * 你就會明白的)
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {

	@AliasFor("name")
	String value() default "";

	@AliasFor("value")
	String name() default "";

	boolean binding() default true;

}

實際上這個注解的作用就是,允許你往 Model 中注入全局屬性(可以供所有Controller中注有@Request Mapping的方法使用),value 和 name 用于指定 屬性的 key ,binding 表示是否綁定,默認為 true。

具體使用方法如下:

全局參數(shù)綁定

方式一:

@ControllerAdvice
public class MyGlobalHandler {
    @ModelAttribute
    public void presetParam(Model model){
        model.addAttribute("globalAttr","this is a global attribute");
    }
}

這種方式比較靈活,需要什么自己加就行了,加多少屬性自己控制

方式二:

@ControllerAdvice
public class MyGlobalHandler {

    @ModelAttribute()
    public Map<String, String> presetParam(){
        Map<String, String> map = new HashMap<String, String>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        return map;
    }

}

這種方式對于加單個屬性比較方便。默認會把返回值(如上面的map)作為屬性的value,而對于key有兩種指定方式:

當 @ModelAttribute() 不傳任何參數(shù)的時候,默認會把返回值的字符串值作為key,如上例的 key 則是 ”map"(值得注意的是,不支持字符串的返回值作為key)。

當 @ModelAttribute("myMap") 傳參數(shù)的時候,則以參數(shù)值作為key,這里 key 則是 ”myMap“。

全局參數(shù)使用

@RestController
public class AdviceController {

    @GetMapping("methodOne")
    public String methodOne(Model model){ 
        Map<String, Object> modelMap = model.asMap();
        return (String)modelMap.get("globalAttr");
    }

  
    @GetMapping("methodTwo")
    public String methodTwo(@ModelAttribute("globalAttr") String globalAttr){
        return globalAttr;
    }


    @GetMapping("methodThree")
    public String methodThree(ModelMap modelMap) {
        return (String) modelMap.get("globalAttr");
    }
    
}

這三種方式大同小異,其實都是都是從Model 中存儲屬性的 Map里取數(shù)據(jù)。

3.請求參數(shù)預處理

@ControllerAdvice 配合 @InitBinder 實現(xiàn)對請求參數(shù)的預處理

再次之前我們先來了解一下 @IniiBinder,先看一下源碼,我會提取一些重要的注釋進行淺析

/**
 * Annotation that identifies methods which initialize the
 * {@link org.springframework.web.bind.WebDataBinder} which
 * will be used for populating command and form object arguments
 * of annotated handler methods.
 * 粗略翻譯:此注解用于標記那些 (初始化[用于組裝命令和表單對象參數(shù)的]WebDataBinder)的方法。
 * 原諒我的英語水平,翻譯起來太拗口了,從句太多就用‘()、[]'分割一下便于閱讀
 *
 * Init-binder methods must not have a return value; they are usually
 * declared as {@code void}.
 * 粗略翻譯:初始化綁定的方法禁止有返回值,他們通常聲明為 'void'
 *
 * <p>Typical arguments are {@link org.springframework.web.bind.WebDataBinder}
 * in combination with {@link org.springframework.web.context.request.WebRequest}
 * or {@link java.util.Locale}, allowing to register context-specific editors.
 * 粗略翻譯:典型的參數(shù)是`WebDataBinder`,結(jié)合`WebRequest`或`Locale`使用,允許注冊特定于上下文的編輯 
 * 器。
 * 
 * 總結(jié)如下:
 *  1. @InitBinder 標識的方法的參數(shù)通常是 WebDataBinder。
 *  2. @InitBinder 標識的方法,可以對 WebDataBinder 進行初始化。WebDataBinder 是 DataBinder 的一
 * 		           個子類,用于完成由表單字段到 JavaBean 屬性的綁定。
 *  3. @InitBinder 標識的方法不能有返回值,必須聲明為void。
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InitBinder {
	/**
	 * The names of command/form attributes and/or request parameters
	 * that this init-binder method is supposed to apply to.
	 * <p>Default is to apply to all command/form attributes and all request parameters
	 * processed by the annotated handler class. Specifying model attribute names or
	 * request parameter names here restricts the init-binder method to those specific
	 * attributes/parameters, with different init-binder methods typically applying to
	 * different groups of attributes or parameters.
	 * 粗略翻譯:此init-binder方法應該應用于的命令/表單屬性和/或請求參數(shù)的名稱。默認是應用于所有命	   		* 令/表單屬性和所有由帶注釋的處理類處理的請求參數(shù)。這里指定模型屬性名或請求參數(shù)名將init-binder		 * 方法限制為那些特定的屬性/參數(shù),不同的init-binder方法通常應用于不同的屬性或參數(shù)組。
	 * 我至己都理解不太理解這說的是啥呀,我們還是看例子吧
	 */
	String[] value() default {};
}

參數(shù)處理

@ControllerAdvice
public class MyGlobalHandler {

    @InitBinder
    public void processParam(WebDataBinder dataBinder){

        /*
         * 創(chuàng)建一個字符串微調(diào)編輯器
         * 參數(shù){boolean emptyAsNull}: 是否把空字符串("")視為 null
         */
        StringTrimmerEditor trimmerEditor = new StringTrimmerEditor(true);

        /*
         * 注冊自定義編輯器
         * 接受兩個參數(shù){Class<?> requiredType, PropertyEditor propertyEditor}
         * requiredType:所需處理的類型
         * propertyEditor:屬性編輯器,StringTrimmerEditor就是 propertyEditor的一個子類
         */
        dataBinder.registerCustomEditor(String.class, trimmerEditor);
        
        //同上,這里就不再一步一步講解了
        binder.registerCustomEditor(Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
    }
}

這樣之后呢,就可以實現(xiàn)全局的實現(xiàn)對 Controller 中RequestMapping標識的方法中的所有 String 和Date類型的參數(shù)都會被作相應的處理。

Controller:

@RestController
public class BinderTestController {

    @GetMapping("processParam")
    public Map<String, Object> test(String str, Date date) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("str", str);
        map.put("data", date);
        return  map;
    }
}

測試結(jié)果:

我們可以看出,str 和 date 這兩個參數(shù)在進入 Controller 的test的方法之前已經(jīng)被處理了,str 被去掉了兩邊的空格(%20 在Http url 中是空格的意思),String類型的 1997-1-10被轉(zhuǎn)換成了Date類型。

參數(shù)綁定

參數(shù)綁定可以解決特定問題,那么我們先來看看我們面臨的問題

class Person {

    private String name;
    private Integer age;
    // omitted getters and setters.
}

class Book {

    private String name;
    private Double price;
    // omitted getters and setters.
}

@RestController
public class BinderTestController {

    @PostMapping("bindParam")
    public void test(Person person, Book book) throws Exception {
        System.out.println(person);
        System.out.println(book);
    }
}

我們會發(fā)現(xiàn) Person類和 Book 類都有 name屬性,那么這個時候就會出先問題,它可沒有那么只能區(qū)分哪個name是哪個類的。因此 @InitBinder就派上用場了:

@ControllerAdvice
public class MyGlobalHandler {

	/*
     * @InitBinder("person") 對應找到@RequstMapping標識的方法參數(shù)中
     * 找參數(shù)名為person的參數(shù)。
     * 在進行參數(shù)綁定的時候,以‘p.'開頭的都綁定到名為person的參數(shù)中。
     */
    @InitBinder("person")
    public void BindPerson(WebDataBinder dataBinder){
        dataBinder.setFieldDefaultPrefix("p.");
    }

    @InitBinder("book")
    public void BindBook(WebDataBinder dataBinder){
        dataBinder.setFieldDefaultPrefix("b.");
    }
}

因此,傳入的同名信息就能對應綁定到相應的實體類中:

p.name -> Person.name b.name -> Book.name

還有一點注意的是如果 @InitBinder("value") 中的 value 值和 Controller 中 @RequestMapping() 標識的方法的參數(shù)名不匹配,則就會產(chǎn)生綁定失敗的后果,如:

@InitBinder(“p”)、@InitBinder(“b”)

public void test(Person person, Book book)

上述情況就會出現(xiàn)綁定失敗,有兩種解決辦法

第一中:統(tǒng)一名稱,要么全叫p,要么全叫person,只要相同就行。

第二種:方法參數(shù)加 @ModelAttribute,有點類似@RequestParam

@InitBinder(“p”)、@InitBinder(“b”)

public void test(@ModelAttribute(“p”) Person person, @ModelAttribute(“b”) Book book)

以上就是深入了解SpringBoot中@ControllerAdvice的介紹及三種用法的詳細內(nèi)容,更多關于SpringBoot @ControllerAdvice用法的資料請關注腳本之家其它相關文章!

相關文章

  • Java 處理超大數(shù)類型之BigInteger案例詳解

    Java 處理超大數(shù)類型之BigInteger案例詳解

    這篇文章主要介紹了Java 處理超大數(shù)類型之BigInteger案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解

    JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解

    這篇文章主要介紹了JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • SpringCloud中Zuul網(wǎng)關原理及其配置

    SpringCloud中Zuul網(wǎng)關原理及其配置

    Spring?Cloud是一個基于Spring?Boot實現(xiàn)的微服務應用開發(fā)工具,其中的Zuul網(wǎng)關可以實現(xiàn)負載均衡、路由轉(zhuǎn)發(fā)、鑒權(quán)、限流等功能,本文將從Spring?Cloud中Zuul網(wǎng)關的原理、使用場景和配置過程詳細介紹,幫助大家更好地了解和應用Zuul網(wǎng)關,需要的朋友可以參考下
    2023-06-06
  • java中進制的轉(zhuǎn)換,Byte與16進制的轉(zhuǎn)換方法

    java中進制的轉(zhuǎn)換,Byte與16進制的轉(zhuǎn)換方法

    下面小編就為大家?guī)硪黄猨ava中進制的轉(zhuǎn)換,Byte與16進制的轉(zhuǎn)換方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • java高并發(fā)ScheduledThreadPoolExecutor與Timer區(qū)別

    java高并發(fā)ScheduledThreadPoolExecutor與Timer區(qū)別

    這篇文章主要為大家介紹了java高并發(fā)ScheduledThreadPoolExecutor與Timer區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Java中的Semaphore如何使用

    Java中的Semaphore如何使用

    Semaphore實際上是一種共享鎖,因為它允許多個線程并發(fā)獲取共享的資源,在Semaphore對象創(chuàng)建時必須設置可用令牌的初始數(shù)量permits,用于控制并發(fā)時同時獲取資源權(quán)限的線程數(shù)量,這篇文章主要介紹了Java中的Semaphore如何使用,需要的朋友可以參考下
    2022-06-06
  • SpringBoot與Angular2的集成示例

    SpringBoot與Angular2的集成示例

    本篇文章主要介紹了SpringBoot與Angular2的集成示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • SpringBoot如何防止XSS注入攻擊詳解

    SpringBoot如何防止XSS注入攻擊詳解

    這篇文章主要給大家介紹了關于SpringBoot如何防止XSS注入攻擊的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • Java中HashMap與String字符串互轉(zhuǎn)的問題解決

    Java中HashMap與String字符串互轉(zhuǎn)的問題解決

    本文介紹了Java中HashMap與String字符串互轉(zhuǎn)的問題解決,當我們有需求將HashMap轉(zhuǎn)為Json格式的String時,需要使用FastJson/Gson將HashMap轉(zhuǎn)為String,感興趣的可以了解一下
    2022-03-03
  • Java 如何解析key為動態(tài)的json操作

    Java 如何解析key為動態(tài)的json操作

    這篇文章主要介紹了Java 如何解析key為動態(tài)的json操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02

最新評論