zoukankan      html  css  js  c++  java
  • 如何抓住该死的异常

    全局异常处理

      全局异常的作用:可以捕捉系统内部产生的错误,不管是参数错误,还是程序错误,还是突然代码发神经导致的错误。但是这些错误我们都可以拿到,并且输出对应我们想要前台看到的信息。让前台更优雅的看到这些错误,不至于看到都是系统提示的英文鸟语。

    全局异常扫描注解

      在application启动类中,需要配置全局异常扫描:@EnableAutoConfiguration

    //启动类09
    @SpringBootApplication  //扫描所有包
    @MapperScan(basePackages = "com.wt.mapper")
    @ComponentScan(basePackages = {"com.wt"})
    @EnableAutoConfiguration
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }
    }

    包的结构

    处理代码

    1、返回的处理结果类型JsonData,Commonreturntype类

    package com.wt.response;
    
    //通用返回格式
    public class CommonReturnType {
                //摆明对应的请求的返回处理结果  success或fail
        private String status;
        //status= success 则data返回json数据
        //status= fail   返回的错误码格式
    
        private Object data;
    
        public static CommonReturnType create(Object result, String status) {
            CommonReturnType type = new CommonReturnType();
            type.setStatus(status);
            type.setData(result);
            return type;
        }
    
        //定义一个通用的创建方法
        public static CommonReturnType create(Object result) {
            return CommonReturnType.create(result, "success");
        }
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    
        public Object getData() {
            return data;
        }
    
        public void setData(Object data) {
            this.data = data;
        }
    }

    2、错误接口类的定义:CommonError

    package com.wt.error;
    
    public interface CommonError {
        //获取错误信息码
        public int getErrCode();
        //获取错误信息
        public String getErrMsg();
        //获取共同的错误
        public CommonError setErrMsg(String errMsg);
    
    }

    3、EmBusinessError定义枚举错误信息,这里存储了我们自己觉得需要抛出的异常文字定义,总之我们想要抛出啥错误信息,就需要在这里定义更多的枚举变量

    package com.wt.error;
    
    import javax.xml.stream.events.Comment;
    
    public enum EmBusinessError implements CommonError {
    
    //枚举变量要放在最开始
        //通用错误类型  10001
        PARAMETER_VALIDATION_ERROR(10001, "参数不合法"),
            UNKNOWN_ERROR(10002, "未知错误");
        EmBusinessError(int errCode, String errMsg) {
            this.errCode = errCode;
            this.errMsg = errMsg;
    
        }
        //成员变量可以靠后放置
        private int errCode;
        private String errMsg;
    
        @Override
        public int getErrCode() {
            return this.errCode;
        }
    
        @Override
        public String getErrMsg() {
            return this.errMsg;
        }
    
        @Override
        public CommonError setErrMsg(String errMsg) {
            this.errMsg = errMsg;
            return this;
        }
        public void setErrCode(int errCode) {
            this.errCode = errCode;
        }
    }

    4、BusinessException包装类业务异常类实现,这个又是另一种错误抛出的信息提示

    package com.wt.error;
    //业务错误处理
    public class BusinessException extends RuntimeException implements CommonError{
        private CommonError commonError;
        //直接接收EmbusinessError 的传参用于构造业务异常
        public BusinessException(CommonError commonError){
            super();
            this.commonError = commonError;
        }
    
        //接收自定义的errMsg的方式构造业务异常
        public BusinessException(CommonError commonError, String errMsg) {
            super();
            this.commonError= commonError;
            this.commonError.setErrMsg(errMsg);
        }
    
        @Override
        public int getErrCode() {
            return this.commonError.getErrCode();
        }
    
        @Override
        public String getErrMsg() {
            return this.commonError.getErrMsg();
        }
    
        @Override
        public CommonError setErrMsg(String errMsg) {
            this.commonError.setErrMsg(errMsg);
            return this;
        }
        public CommonError getCommonError() {
            return commonError;
        }
    }

    5、GlobalExceptionHandler最后定义全局异常捕获类,这就相当于一个接口,一个监视器一样,我们程序出现错误就会有这样一个监管的人来逮住你

    package com.wt.errorhandler;
    
    import com.wt.error.BusinessException;
    import com.wt.error.EmBusinessError;
    import com.wt.response.CommonReturnType;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.ServletRequestBindingException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.NoHandlerFoundException;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashMap;
    import java.util.Map;
    
    //全局异常处理
    @ControllerAdvice
    public class GlobalExceptionHandler {
        //日志监测
        public static final  org.slf4j.Logger logger=LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
        //错误处理
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public CommonReturnType doError(HttpServletRequest httpServletReques, HttpServletResponse
                                        httpServletResponse, Exception ex) {
            ex.printStackTrace();
            //map存储异常响应的数据
            Map<String, Object> responseData = new HashMap<>();
            //如果是业务异常类型
            if (ex instanceof BusinessException) {
                System.out.println("===这里错误了进来了么哟===");
                BusinessException businessException = (BusinessException) ex;
                //map中就放置  错误码和信息
                responseData.put("errCode", businessException.getErrCode());
                responseData.put("errMsg", businessException.getErrMsg());
                //
            } else if (ex instanceof ServletRequestBindingException) {
                responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode());
                //拦截到对应错误信息 输出对应的异常信息
                responseData.put("errMsg", "url绑定路由问题");
            } else if (ex instanceof NoHandlerFoundException) {
                responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg", "没有找到对应的访问路径");
            } else {
                /*这里错误了没*/
                responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg", EmBusinessError.UNKNOWN_ERROR.getErrMsg());
            }
            //错误日志输出
            logger.error(responseData.toString());
            System.out.println("================这个是错误集合"+responseData.toString());
            //回写错误集合
            return CommonReturnType.create(responseData,"fail");
        }
    }

    测试

      测试还是老规矩:在controller中进行测试,controller在api模块中,别搞忘了

        //异常错误
        @GetMapping("/exceptiontest")
        public CommonReturnType exceptionTest() {
            //这里传递一个参数  有个为空 代表参数错误
            int i=1/0;
           return CommonReturnType.create(null, "fail");
        }

      访问路径:http://localhost:8088/exceptiontest

    全局异常检测下的验证器

    项目结构图

    引入依赖

            <!--校验相关 -->
            <!--apache工具包,方便常规操作 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.4</version>
            </dependency>
            <!--hibernate校验工具 -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>6.1.4.Final</version>
            </dependency>
            <!-- lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.4</version>
            </dependency>
            <!--hutool工具 -->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.3.7</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-parent</artifactId>
                <version>5.3.7</version>
                <type>pom</type>
            </dependency>

    校验器

    1、校验结果的判断ValidationResult

    package com.wt.validator;
    
    
    import org.apache.commons.lang3.StringUtils;
    
    import java.util.HashMap;
    import java.util.Map;
    
    //校验结果
    //检验结果的正确与否
    public class ValidationResult {
        //检验结果是否有错
        private boolean hasErrors = false ;
        //存放错误信息 的map
        private Map<String, String> errorMsgMap = new HashMap<>();
    
        public boolean isHasErrors() {
            return hasErrors;
        }
    
        public void setHasErrors(boolean hasErrors) {
            this.hasErrors = hasErrors;
        }
    
        public Map<String, String> getErrorMsgMap() {
            return errorMsgMap;
        }
    
        public void setErrorMsgMap(Map<String, String> errorMsgMap) {
            this.errorMsgMap = errorMsgMap;
        }
    
        //实现通用的通过格式化字符串信息获取错误结果的msg方法
        public String getErrMsg() {
            return StringUtils.join(errorMsgMap.values().toArray(), ",");
        }
    }

    2、校验器的实现类ValidatorImpl,这里会和全局异常配合使用,当校验的结果和规定的不符合,就会捕捉到错误的信息进行处理,并且返回规定的错误提示信息。vo类是页面向后台传递数据的对象,将页面数据封装与后台进行查询交互,这样一个对象可以很好的规范用户在页面的操作。免得搞一些小动作。

    package com.wt.validator;
    
    import cn.hutool.core.map.MapUtil;
    import com.wt.error.BusinessException;
    import com.wt.error.EmBusinessError;
    import org.apache.ibatis.io.ResolverUtil;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.stereotype.Component;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.Validation;
    import javax.validation.Validator;
    import java.util.Set;
    
    
    @Component
    public class ValidatorImpl implements InitializingBean {
        private Validator validator;
    
        public void check(Object bean) throws BusinessException{
            ValidationResult result = validate(bean);
            if(MapUtil.isNotEmpty(result.getErrorMsgMap())) {
                if(result.isHasErrors()) {
                    throw new BusinessException(EmBusinessError.UNKNOWN_ERROR, result.getErrorMsgMap().toString());
                }
            }
        }
    
        //实现校验方法并返回校验结果
        private ValidationResult validate(Object bean) {
            //验证器结果
            final ValidationResult result = new ValidationResult();
            //将验证器的结果放入集合
            Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(bean);
            //如果有错误
            if(constraintViolationSet.size()>0){
                //有错误
                result.setHasErrors(true);
                //打印错误集合 ,同时得到错误信息,和每个错误的属性名字 也就是错误code
                constraintViolationSet.forEach(ConstraintViolation->{
                    String errMsg = ConstraintViolation.getMessage();
                    String propertyName = ConstraintViolation.getPropertyPath().toString();
                    result.getErrorMsgMap().put(propertyName, errMsg);
                });
            }
            return result;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            //将hibernate validator 通过工厂的初始化方式使其实例化
            this.validator = Validation.buildDefaultValidatorFactory().getValidator();
        }
    }

    3、创建Vo对象

    package com.wt.controller.viewobject;
    
    import lombok.*;
    import org.hibernate.validator.constraints.Length;
    
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    
    
    //这个对象的用处还是蛮大的 一般用于界面封装界面提交的信息
    //你想想 每次页面提交 信息的个数和格式 估摸着都和数据库的不一样
    //那么我们在输入信息的时候就将信息封装成一个对象  那这个对象到后台去校验 操作
    
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    @Setter
    @Getter
    public class TestVo {
        @NotNull
        private Integer id;
    
        //这里给他规定字符的格式
        @NotBlank
        @Length(min=1, max=3, message = "名称长度1-3")
        private String name;
        private Integer age;
    }

    测试

      老规矩还是在controller中进行添加测试模块,如果有不懂的需要看我前面的搭建。我是不会告诉你直接答案的。

        @Resource
        private ValidatorImpl validator;
        
    
        @GetMapping("/validatorTest")
        public CommonReturnType testException(TestVo testVo) {
            validator.check(testVo);
            return CommonReturnType.create("success");
        }

      这里由于是封装了一个对象,参数是一个参数,所以用那个swagger2并不是很友好,不知道怎么去封装一个对象那就别玩了,还是老老实实去用一下postman,提交id,name。

      输入和他规定不符合的,那么就会出现他提示我的错出来

  • 相关阅读:
    全文检索(SOLR)前端应用浅析续 Rails前端分析
    全文搜索应用 企业搜索SearchBlox
    持续集成(CI) 几种测试的区别(摘录)
    图解全文检索SOLR的酷应用[Ajax Solr]
    Php如何实现下载功能超详细流程分析
    在MySQL字段中使用逗号分隔符
    session的垃圾回收机制
    【转】apache常用配置
    深入理解PHP之数组(遍历顺序)
    正则表达式的子模式详解
  • 原文地址:https://www.cnblogs.com/HelloM/p/14250102.html
Copyright © 2011-2022 走看看