Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 348|回复: 0

springboot-web进阶(三)——统一异常处理

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-8 22:56:26 | 显示全部楼层 |阅读模式

    补充

      springboot中也是一样的可以对结果进行统一格式的包装,这样也就方便了前台的统一接收处理了;

      1.结果集包装类 

    package com.example.demo.bean;
    
    /**
     * 结果包装
     *
     * @author zcc ON 2018/2/9
     **/
    public class Result<T> {
        /**
         * 错误代码(可以设定例如500表示错误)
         */
        private Integer code;
        /**
         * 提示信息
         */
        private String msg;
        /**
         * 数据内容
         */
        private T data;
    
        public Result() {
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    Resultde

     

        可以参考之前SSM中的包装类http://www.cnblogs.com/jiangbei/p/7080955.html

      2.使用包装结果集

    @PostMapping(value = "/girls") public Result<Girl> addGirl(@Valid Girl girl, BindingResult bindingResult) { Result<Girl> result = new Result<>(); // 表单验证逻辑
            if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); StringBuffer sb = new StringBuffer(); for (FieldError fieldError : fieldErrors) { sb.append(fieldError.getDefaultMessage()); } result.setCode(500); result.setMsg(sb.toString()); return result; } result.setCode(200); result.setMsg("success"); result.setData(girlRepository.save(girl)); return result; }

        3。改进结果集

          通过代码观察或者对比SSM中的示例,都发现这样写在代码中是挺傻的,这样,我们提供一个工具类(或者在结果集中直接封装)

    /** * 结果集的工具类 * * @author zcc ON 2018/2/9 **/
    public class ResultUtils { public static Result<Object> success(Object data) { Result<Object> result = new Result<>(); result.setCode(200); result.setMsg("success"); result.setData(data); return result; } public static Result<Object> error(String msg) { Result<Object> result = new Result<>(); result.setCode(500); result.setMsg(msg); return result; } }

        使用:

     @PostMapping(value = "/girls") public Result<Object> addGirl(@Valid Girl girl, BindingResult bindingResult) { // 表单验证逻辑
            if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); StringBuffer sb = new StringBuffer(); for (FieldError fieldError : fieldErrors) { sb.append(fieldError.getDefaultMessage()); } return ResultUtils.error(sb.toString()); } return ResultUtils.success(girlRepository.save(girl)); }

     

    一、概述

      springboot提供了默认的统一异常处理,basicErrorController,这个controller提供了默认了错误处理方法,包括错误跳转的路径和渲染方法。

      因为默认的错误处理方法可能会不适合项目的需要,所以当需要自定义统一错误处理的时候,可以继承basicErrorController。或重新实现basicErrorController.

    统一异常处理可配置400,404,500等状态异常错误处理。basicErrorController内部提供了针对accept=**的不同处理方法,可区别是普通调用还是ajax等其他调用。

      缺点:需要重写basicErrorController。并配置覆盖原来springboot的默认配置。当使用EmbeddedServletContainerCustomizer类配置400,404。500的时候,暂时不清楚调用springboot的处理方法。

    二、问题提出

      假设需要根据girl的不同age作出不同的动作,controller如下:

     @GetMapping(value = "/girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) { // 判断应该交给service
            

      service:

    public void getAge(Integer id) { Integer age = girlRepository.findOne(id).getAge(); if (age < 12) { // 小学生
            } else { // 上初中了
     } }

      如果只是简单的判断,不同年龄返回不同信息给前台,那确实可以通过返回一个String来进行

      但是,如果业务比较复杂,需要的不仅仅是返回一个字符串,而是需要其他动作,这个时候就显得有点力不从心了!

    三、统一异常处理

       1.基本用法

       controller调用service,抛出异常即可:

     @GetMapping(value = "/girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) throws Exception{ // 判断应该交给service
     girlService.getAge(id); }

      service也是,该抛异常就抛出异常:

    public void getAge(Integer id) throws Exception{ Integer age = girlRepository.findOne(id).getAge(); if (age < 12) { // 小学生
                throw new Exception("小学生!"); } else { // 上初中了
                throw new Exception("初中生!"); } }

      统一异常处理类:

    package com.example.demo.handle; import com.example.demo.bean.Result; import com.example.demo.utils.ResultUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * 异常处理类 * 添加@ControllerAdvice标记为异常处理类 * @author zcc ON 2018/2/9 **/ @ControllerAdvice public class MyExceptionHandler { /** * 如果不在这里加@ResponseBody,则需要在类上加 * @param e 异常 * @return
         */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e) { return ResultUtils.error(e.getMessage()); } }

      2.自定义异常

        写自定义异常还是之前的基础篇的老套路,基本就是几个构造方法的编写,再根据需要加上自己的变量!

     

    package com.example.demo.exception; /** * 自定义异常 * 继承RuntimeException才能使得spring进行异常时的回滚 * @author zcc ON 2018/2/9 **/
    public class MyException extends RuntimeException{ private Integer code; public MyException(Integer code, String msg) { super(msg); this.code = code; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }

     

        异常处理类:

    package com.example.demo.handle; import com.example.demo.bean.Result; import com.example.demo.exception.MyException; import com.example.demo.utils.ResultUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * 异常处理类 * 添加@ControllerAdvice标记为异常处理类 * @author zcc ON 2018/2/9 **/ @ControllerAdvice public class MyExceptionHandler { /** * 如果不在这里加@ResponseBody,则需要在类上加 * @param e 异常 * @return
         */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e) { // 先判断捕获的是不是我们定义的异常
            if (e instanceof MyException) { MyException me = (MyException) e; return ResultUtils.exp(me.getCode(), me.getMessage()); } else { return ResultUtils.error("未知错误!"); } } }

      其他地方需要注意:

        既然MyException继承RuntimeException了,那controller和service就不用抛出异常了

        ResultUtils根据需要微调一些

      统一404、500异常处理

     

      @ExceptionHandler(value = Exception.class) @ResponseBody public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { logger.error("", e); ResponseData r = new ResponseData(); r.setMessage(e.getMessage()); if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) { r.setCode(404); } else { r.setCode(500); }

     

     

     

    三、使用枚举优化管理

      1.枚举

    package com.example.demo.enums; /** * 结果集的枚举管理类 * 不用给出setter了,因为枚举不会再去set了 * @author zcc **/
    public enum ResultEnum { UNKNOWN(-1, "未知错误"), SUCCESS(200, "success"), PRIMARY(100, "小学生"), MIDDLE(101, "中学生"); private Integer code; private String msg; ResultEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public String getMsg() { return msg; } }

      更多枚举基础知识,参考:http://www.cnblogs.com/jiangbei/p/7580482.html

     

      2.调整自定义异常的构造方法

    /** * 自定义异常 * 继承RuntimeException才能使得spring进行异常时的回滚 * @author zcc ON 2018/2/9 **/
    public class MyException extends RuntimeException{ private Integer code; public MyException(ResultEnum resultEnum) { super(resultEnum.getMsg()); this.code = resultEnum.getCode(); } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }

      3.使用自定义枚举统一管理错误代码和错误信息之间的关系

     public void getAge(Integer id) { Integer age = girlRepository.findOne(id).getAge(); if (age < 12) { // 小学生
                throw new MyException(ResultEnum.PRIMARY); } else { // 上初中了
                throw new MyException(ResultEnum.MIDDLE); } }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-2 09:56 , Processed in 0.061319 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表