@ControllerAdvice(实现全局异常、全局参数、请求参数预处理)

近期看到了ControllerAdvice这个注解,本身只是为了看下全局异常处理的,简单了解后发现可以分别与@ExceptionHandler、@ModelAttribute、@InitBinder实现 全局异常、全局参数、请求参数预处理 的功能。

目录

  • 一、全局异常处理
  • 二、全局参数处理
  • 三、请求参数预处理

一、全局异常处理

实现全局异常处理需要配合@ExceptionHandler注解进行处理

导入maven




    com.alibaba
    fastjson
    1.2.75




    org.projectlombok
    lombok
    1.18.6
    provided




    org.springframework.boot
    spring-boot-starter-validation

自定义处理器代码

import com.zhangximing.springboot_annotate.pojo.ErrorResponse;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;

//全局处理器
@ControllerAdvice
public class GlobalHandler {

    // 异常处理器
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ErrorResponse handleException(Exception e) {
        // 这里可以根据需要记录异常信息,发送通知等
        System.err.println("发生异常: " + e.getMessage());

        // 返回错误信息
        ErrorResponse response = new ErrorResponse(500,"服务器发生异常("+e.getMessage()+"),请稍后重试");

        return response;
    }
}

实体代码

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 异常处理实体
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {
    private int code;
    private String message;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;

/**
 *  统一API响应结果封装实体
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private int code;
    private String message;
    private Object data;

    public static Result success() {
        return new Result(HttpStatus.OK.value(), "操作成功", null);
    }

    public static Result success(Object data) {
        return new Result(HttpStatus.OK.value(), "操作成功", data);
    }

    public static Result error(String message) {
        return new Result(HttpStatus.BAD_REQUEST.value(), message, null);
    }
}

测试方法

import com.alibaba.fastjson.JSONObject;
import com.zhangximing.springboot_annotate.pojo.Result;
import lombok.SneakyThrows;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/test")
public class TestController {

    // 测试全局异常
    @SneakyThrows
    @RequestMapping("/globalException")
    public Result globalException(@Validated @RequestBody JSONObject param) {

        // 设置验证门槛
        String authCode = param.getString("authCode");
        // 验证不通过抛异常
        if (null == authCode || !"XM_PASS".equals(authCode.trim())){
            throw new Exception("authCode error");
        }

        return Result.success();
    }
}

测试结果

@ControllerAdvice(实现全局异常、全局参数、请求参数预处理)_第1张图片

二、全局参数处理

实现全局参数处理需要配合@ModelAttribute注解进行处理
引入的pom以及实体代码与上同

import com.zhangximing.springboot_annotate.pojo.ErrorResponse;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//全局处理器
@ControllerAdvice
public class GlobalHandler {
    // 设置全局参数
    @ModelAttribute
    public void presetParam(Model model){
        model.addAttribute("globalAttr","globalAttr_Number1");
    }

//    //注意@ModelAttribute若加括号不传任何参数的时候默认key为map,这种写法与上述写法不一致之处在于会包裹一层map
//    @ModelAttribute()
//    public Map presetParam(){
//        Map map = new HashMap();
//        map.put("globalAttr", "globalAttr_Number2");
//        return map;
//    }
}

测试方法

// 测试全局预设参数
// 预设情况一 (直接model转换map)
@GetMapping("presetOne")
public String presetOne(Model model){
    Map<String, Object> modelMap = model.asMap();
    return JSONObject.toJSONString(modelMap);
}

// 预设情况二(指定全局异常变量)
@GetMapping("presetTwo")
public String presetTwo(@ModelAttribute("globalAttr") String globalAttr){
    return globalAttr;
}

// 预设情况三(指定modelMap对象)
@GetMapping("presetThree")
public String presetThree(ModelMap modelMap) {
    return JSONObject.toJSONString(modelMap);
}

测试结果

@ControllerAdvice(实现全局异常、全局参数、请求参数预处理)_第2张图片

三、请求参数预处理

实现请求参数预处理需要配合@InitBinder注解进行处理
这部分参考了博客:https://blog.csdn.net/qq_36829919/article/details/101210250

import com.zhangximing.springboot_annotate.pojo.ErrorResponse;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//全局处理器
@ControllerAdvice
public class GlobalHandler {
    // 请求参数预处理
    @InitBinder
    public void processParam(WebDataBinder dataBinder){

        /*
         * 创建一个字符串微调编辑器
         * 参数{boolean emptyAsNull}: 是否把空字符串("")视为 null
         */
        StringTrimmerEditor trimmerEditor = new StringTrimmerEditor(true);

        /*
         * 注册自定义编辑器
         * 接受两个参数{Class requiredType, PropertyEditor propertyEditor}
         * requiredType:所需处理的类型
         * propertyEditor:属性编辑器,StringTrimmerEditor就是 propertyEditor的一个子类
         */
        dataBinder.registerCustomEditor(String.class, trimmerEditor);

        //同上,当日期类型时
        dataBinder.registerCustomEditor(Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
    }
}

测试方法

// 测试全局预处理
@RequestMapping("initDeal")
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;
}

测试结果

@ControllerAdvice(实现全局异常、全局参数、请求参数预处理)_第3张图片

个人理解:ControllerAdvice该注解的作用原理跟aop相似,都是进行拦截,而需要拦截处理的具体功能是由其他注解来协助(类似于aop的Advice)。
以上我学习整理的ControllerAdvice注解的使用。

你可能感兴趣的:(#,SpringBoot,java,spring,boot,注解)