自定义返回异常

要求:使用自定义异常 ,返回友好提示

结果如图,当价格未输入时,提示400,并且提示具体错误信息:

1,pojo 只有id name price

2, 控制层

@RestController
public class ItemController {
    @PostMapping("item")
    public ResponseEntity<Item> save(Item item){
        item.setId(1L);
        if (item.getPrice()==null){
            throw new LyException(ExceptionEnum.PRICE_CANNOT_BE_NULL);
        }
        return ResponseEntity.status(HttpStatus.CREATED).body(item);
    }
}

使用spring的ResponseEntity处理HTTP响应。

搜索资料:

1.ResponseEntity的优先级高于@ResponseBody。在不是ResponseEntity的情况下才去检查有没有@ResponseBody注解。如果响应类型是ResponseEntity可以不写@ResponseBody注解,写了也没有关系。

2.ResponseEntity 是在 org.springframework.http.HttpEntity 的基础上添加了http status code(http状态码),用于RestTemplate以及@Controller的HandlerMethod。它在Controoler中或者用于服务端响应时,作用是和@ResponseStatus与@ResponseBody结合起来的功能一样的。用于RestTemplate时,它是接收服务端返回的http status code 和 reason的。 总结: 简单粗暴的讲 @ResponseBody可以直接返回Json结果, @ResponseEntity不仅可以返回json结果,还可以定义返回的HttpHeaders和HttpStatus

3,自定义的异常 (继承了RuntimeException ,重写了2个构造,throwable是Exception 的父类)

@Getter
public class LyException extends RuntimeException{
    private int status;

    public LyException(ExceptionEnum em) {
        super(em.getMessage());
        this.status = em.getStatus();
    }

    public LyException(ExceptionEnum em, Throwable cause) {
        super(em.getMessage(),cause);
        this.status = em.getStatus();
    }
}

4,异常的参数 是一个enum (应该是上一步之前

用户抛出异常时,就必须传递两个内容:

  • 异常信息

  • 异常状态码

但是RuntimeException是无法接受状态码的,只能接受异常的消息,所以我们需要做两件事情:

  • 自定义异常,来接受状态码、异常消息

  • 状态码与异常消息可能会重复使用,我们通过枚举来把这些信息变为常量

枚举:把一件事情的所有可能性列举出来。在计算机中,枚举也可以叫多例,单例是多例的一种情况 。

@Getter
public enum  ExceptionEnum {
    PRICE_CANNOT_BE_NULL(400,"价格不能为空");


    private int status;
    private String message;
    ExceptionEnum(int status, String message) {
        this.status = status;
        this.message = message;
    }
}

 

5,异常的通知类(用来指定哪个异常)

@ControllerAdvice
@Slf4j
public class BasicExceptionAdvice {
    //捕获异常处理 自定义异常
    @ExceptionHandler(LyException.class)
    public ResponseEntity<ExceptionResult> LyException(LyException le){
        // 从异常中获取友好提示信息
        return ResponseEntity.status(le.getStatus()).body(new ExceptionResult(le));
    }
}

Spring 在3.2版本后面增加了一个ControllerAdvice注解。

ControllerAdvice拆分开来就是Controller Advice,关于Advice,在Spring Aop中,其是用于封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。

这里ContrllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行“切面”环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。

@ControllerAdvice是在类上声明的注解,其用法主要有三点:

  • 结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的;

  • 结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的;

  • 结合方法型注解@ModelAttribute,表示其标注的方法将会在目标Controller方法执行之前执行。

@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持。

解读:

@ControllerAdvice:默认情况下,会拦截所有加了@Controller的类

  • @ExceptionHandler(LyException.class):作用在方法上,声明要处理的异常类型,可以有多个,这里指定的是LyException。被声明的方法可以看做是一个SpringMVC的Handler

    • 参数是要处理的异常,类型必须要匹配

    • 返回结果可以是ModelAndViewResponseEntity等,基本与handler类似

  • 这里等于从新定义了返回结果,我们可以随意指定想要的返回类型。此处使用了String

一个被@ExceptionHandler注解修饰的方法,就能捕获controller层所有抛出的InsertMessageException类型异常,并对异常进行相应的处理

如果想一个方法处理多种类型异常,就需要在@ExceptionHandler的括号中用大括号添加所想要处理的异常类型,用”,”隔开 
例如:@ExceptionHandler({InsertException.class,DeleteException.class})

使用 @ControllerAdvice,不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调

6,异常返回结果的友好(应该是上一步之前

@Getter
public class ExceptionResult {
    private int status;
    private String message;
    private String timestamp;

    public ExceptionResult(LyException e) {
        this.status = e.getStatus();
        this.message = e.getMessage();
        this.timestamp = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
    }
}

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

慢慢CG

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值