SpringBoot中@ControllerAdvice結合@InitBinder、@ModelAttribute、@ExceptionHandler的使用

簡介

@ControllerAdvice 就是 @Controller 的增強版。主要用來處理全局數據,一般搭配 @InitBinder@ModelAttribute@ExceptionHandler 使用。在@ControllerAdvice註解類的內部使用以上三個註解的方法會應用到所有的@RequestMapping註解的方法。

注:

  • 如果這三個註解直接在@Controller類中使用,則只對當前控制器生效
  • 如果@ControllerAdvice中不需要返回view,也可以使用@RestControllerAdvice,即@RestControllerAdvice = @ControllerAdvice + @ResponseBody

下面將分別介紹:

一、@InitBinder

作用:對HTTP請求參數進行預處理,再綁定到對應的接口。這裏我們就可以對參數做一些額外的處理,比如時間格式的轉換等。(注意:這裏對@RequestBody註解的參數無效,需要自行實現)

在Spring MVC的web項目中,相信小夥伴們經常會遇到一些前端給後端傳值比較棘手的問題:
比如後端Controller如何接收Date日期類型的參數,業界比較通用的做法是用時間戳或者用字符串或者使用@DateTimeFormat註解,但是這還需要我們自己做後續的處理轉換,或者每一個日期類型的參數都需要加註解處理,用起來麻煩而且不夠優雅,這裏看我們的@InitBinder是怎麼處理的:

import org.apache.commons.lang3.time.DateUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.util.Date;

@ControllerAdvice
public class GlobalHandler {

    private static String[] patterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"
    };

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                Date date = null;
                try {
                    if (text != null) {
                        date = DateUtils.parseDate(text, patterns);
                    }
                } catch (ParseException e) {
                }
                setValue(date);
            }
        });
    }
}

這樣當前後端再需要傳日期類型的參數時,後端可以直接使用Date進行接收了。

使用時:
在這裏插入圖片描述

二、@ModelAttribute

作用:綁定數據

這個註解大家應該很熟悉了,可以在進入接口前綁定一些數據

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

import java.util.HashMap;

@ControllerAdvice
public class GlobalHandler {

    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("msg", "Hello World");

        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "張三");
        map.put("age", 20);
        model.addAttribute("info", map);
    }
}

使用時:
在這裏插入圖片描述

三、@ExceptionHandler

作用:統一異常處理

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalHandler.class);

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Map<String, Object> handleException(Exception e) {
        LOGGER.error(e.getMessage(), e);

        HashMap<String, Object> map = new HashMap<>(3);
        map.put("code", 500);
        map.put("msg", "服務器內部錯誤");
        return map;
    }
}

使用時:
在這裏插入圖片描述
這樣,對於RequestMapping標記的方法,只要拋出了Exception異常,便會被此方法攔截,從而返回我們封裝標準的響應格式或者view,這裏我只處理了Exception異常,還可以指定其他自定義的業務異常等等。

當定義了多個異常處理器的時候,比如@ExceptionHandler(Exception.class)@ExceptionHandler(ParseException.class),如果程序中拋出了異常,那麼它將嘗試查找爲處理異常而註冊的最“特定”的異常處理程序。如果沒有這樣的處理程序,它將嘗試檢查異常的超類,如果它也沒有找到,它會更高級別等等等等,從最具體到一般。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章