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

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

一、全局异常处理

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

导入maven

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<!-- 阿里巴巴json转换 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>

<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.6</version>
    <scope>provided</scope>
</dependency>

<!-- 校验包 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

自定义处理器代码

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();
    }
}

测试结果

在这里插入图片描述

二、全局参数处理

实现全局参数处理需要配合@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<String, String> presetParam(){
//        Map<String, String> map = new HashMap<String, String>();
//        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);
}

测试结果

在这里插入图片描述

三、请求参数预处理

实现请求参数预处理需要配合@InitBinder注解进行处理
这部分参考了博客:https://blog.youkuaiyun.com/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该注解的作用原理跟aop相似,都是进行拦截,而需要拦截处理的具体功能是由其他注解来协助(类似于aop的Advice)。
以上我学习整理的ControllerAdvice注解的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谦风(Java)

一起学习,一起进步(✪ω✪)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值