Spring boot--控制器增強


在Spring3.2中,新增了@ControllerAdvice注解。關於這個注解的官方說明https://docs.spring.io/spring-framework/docs/5.0.0.M1/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

我們可以根據字面意思將這個注解理解為Controller的Advice(在spring aop中,Advice被翻譯為“增強”)。

在這個控制器的增強處理中,spring提供了三個注解,來幫助我們對Controller進行增強的操作:

@ExceptionHandler:異常處理器、@InitBinder:初始參數綁定器、@ModelAttribute(模型參數)。

 

@ControllerAdvice

先來看下@ControllerAdvice的內容,這個注解是使用在Class上,里面有幾個參數可以指定basePackages,但由於這個注解只是對Controller的增強,因此只對指定包下的Controller生效(如果在dao或service包中對異常上拋,也是可以拋出到Controller層,並通過搭配該注解進行捕獲異常)。

@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 {};
}

 

@ExceptionHandler

@ExceptionHandler:這個注解是使用在方法上,可以處理指定的異常。假如異常不在這個范圍內,則不會被捕獲,可以定義多個不同的異常處理器用來分別處理不同的異常。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
    Class<? extends Throwable>[] value() default {};
}

 

我們來測試一下@ExceptionHandler

定義一個全局異常處理器,里面指定了兩個異常的捕獲和處理,一個是IAE,一個是NPE。

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = IllegalArgumentException.class) //指定異常只處理IAE,也可以指定為Throwable類,可以處理所有的異常。
    @ResponseBody //這里添加ResponseBody是為了直接返回字符串到前端,否則會如同Controller一樣,將返回的字符串作為視圖名處理,向視圖發起請求。 public String handler(Exception exception) {
        System.out.println("抓住異常,異常原因:");
        System.out.println(exception.getMessage());
        return "IllegalArgumentException";
    }

    @ExceptionHandler(value = NullPointerException.class)
    @ResponseBody
    public String handler2(Exception exception) {
        System.out.println("抓住異常,異常原因:");
        System.out.println(exception.getMessage());
        return "NullPointerException";
    }

}

然后我們定義一個Controller,里面會拋出上面的兩種異常

    @GetMapping("users/{id}")
    public String getUser(@PathVariable("id") String id) throws Exception {
        System.out.println("接收到請求[/users/" + id + "]");
        if (id.equals("error")) {
            throw new IllegalArgumentException("參數錯誤!");
        } else if (id.equals("null")) {
            throw new NullPointerException("id不能為null!");
        }
        return "testUser";
    }

啟動項目,分別輸入參數為error和null的請求,查看控制台打印數據:

接收到請求[/users/error]
抓住異常,異常原因:
參數錯誤!

接收到請求[/users/error]
抓住異常,異常原因:
id不能為null!

如果我們在controller里面再拋出一個其他類型的異常,則會直接返回到前端,而不是被交給異常處理器處理。

 

@InitBinder

這個注解用來對從前端傳入的參數進行功能輔助。

具體的輔助功能有很多種。比如我們傳了一個String類型的"2019-05-05",但是我們在controller要用Date來獲取,默認情況下是會拋出非法參數異常,如下:

因此這個時候需要我們在@InitBinder中配置一個自定義日期格式,如下:

    @InitBinder
    public void globalInitBinder(WebDataBinder binder) {
        binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
    }

 

這個注解關鍵的重點在於它的參數WebDataBinder中配置的信息,除了上面的添加自定義格式外,還可以注冊其他的類型,如將參數自動存儲在Map中。

    @InitBinder
    public void globalInitBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Integer.class, new CustomMapEditor(HashMap.class));
    }

 

@ModelAttribute

該注解用來在Controller接收參數之前對數據模型進行處理,可以添加或刪除相關的數據,比如我們在@ModelAttrbute中配置兩個數據name和age

    @ModelAttribute
    public void model(Model model) {
        model.addAttribute("name", "yxf");
        model.addAttribute("age", 12);
    }

然后在Controller的方法中進行配置

    @GetMapping("users/login")
    public String test(@ModelAttribute("name")String name, @ModelAttribute("age") int age) {
        System.out.println("Name="+name + ";Age="+age);
        return "index";
    }

配置完成后運行啟動類,輸入路徑"/users/login"不帶任何參數。

控制台照樣會打印結果:Name=yxf;Age=12

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM