乐趣区

关于vue.js:SpringCloud微服务实战搭建企业级开发框架七自定义通用响应消息及统一异常处理

  平时开发过程中,无可避免咱们须要解决各类异样,所以这里咱们在公共模块中自定义对立异样,Spring Boot 提供 @RestControllerAdvice 注解对立异样解决,咱们在 GitEgg_Platform 中新建 gitegg-platform-boot 子工程,此工程次要用于 Spring Boot 相干性能的自定义及扩大。
1、批改 gitegg-platform-boot 的 pom.xml,增加 spring-boot-starter-web 和 swagger 依赖,设置 optional 为 true,让这个包在我的项目之间依赖不传递。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-swagger</artifactId>
            <optional>true</optional>
        </dependency>

2、自定义通用响应音讯类,Result 和 PageResult,一个是一般响应音讯,一个是分页响应音讯。
Result 类:

package com.gitegg.platform.boot.common.base;

import com.gitegg.platform.boot.common.enums.ResultCodeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;

/**
 * @ClassName: Result
 * @Description: 自定义通用响应类
 * @author GitEgg
 * @date 2020 年 09 月 19 日 下午 9:24:50
 */
@ApiModel(description = "通用响应类")
@Getter
@ToString
public class Result<T> {@ApiModelProperty(value = "是否胜利", required = true)
    private boolean success;
    
    @ApiModelProperty(value ="响应代码", required = true)
    private int code;

    @ApiModelProperty(value ="提示信息", required = true)
    private String msg;

    @ApiModelProperty(value ="响应数据")
    private T data;
    
    /**
     * 
     * @param code
     * @param data
     * @param msg
     */
    private Result(int code, T data, String msg) {
        this.success = ResultCodeEnum.SUCCESS.code == code;
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 
     * @param resultCodeEnum
     */
    private Result(ResultCodeEnum resultCodeEnum) {this(resultCodeEnum.code, null, resultCodeEnum.msg);
    }

    /**
     * 
     * @param resultCodeEnum
     * @param msg
     */
    private Result(ResultCodeEnum resultCodeEnum , String msg) {this(resultCodeEnum, null, msg);
    }

    /**
     * 
     * @param resultCodeEnum
     * @param data
     */
    private Result(ResultCodeEnum resultCodeEnum , T data) {this(resultCodeEnum, data, resultCodeEnum.msg);
    }

    /**
     * 
     * @param resultCodeEnum
     * @param data
     * @param msg
     */
    private Result(ResultCodeEnum resultCodeEnum , T data, String msg) {this(resultCodeEnum.code, data, msg);
    }

    /**
     * 
     *
     * @param data 数据
     * @param <T>  T 响应数据
     * @
     */
    public static <T> Result<T> data(T data) {return data(data, ResultCodeEnum.SUCCESS.msg);
    }

    /**
     * 
     *
     * @param data 数据
     * @param msg  音讯
     * @param <T>  T 响应数据
     * @
     */
    public static <T> Result<T> data(T data, String msg) {return data(ResultCodeEnum.SUCCESS.code, data, msg);
    }

    /**
     * 
     *
     * @param code 状态码
     * @param data 数据
     * @param msg  音讯
     * @param <T>  T 响应数据
     * @
     */
    public static <T> Result<T> data(int code, T data, String msg) {return new Result<>(code, data, msg);
    }

    /**
     * 返回 Result
     *
     * @param 
     * @param <T>  T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> success() {return new Result<>(ResultCodeEnum.SUCCESS);
    }
    
    /**
     * 返回 Result
     *
     * @param msg 音讯
     * @param <T> T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> success(String msg) {return new Result<>(ResultCodeEnum.SUCCESS, msg);
    }

    /**
     * 返回 Result
     *
     * @param 
     * @param <T>  T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> success(ResultCodeEnum resultCodeEnum) {return new Result<>(resultCodeEnum);
    }

    /**
     * 返回 Result
     *
     * @param 
     * @param msg   提示信息
     * @param <T>  T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> success(ResultCodeEnum resultCodeEnum , String msg) {return new Result<>(resultCodeEnum, msg);
    }
    
    /**
     * 返回 Result
     *
     * @param <T> T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> error() {return new Result<>(ResultCodeEnum.ERROR, ResultCodeEnum.ERROR.msg);
    }

    /**
     * 返回 Result
     *
     * @param msg 音讯
     * @param <T> T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> error(String msg) {return new Result<>(ResultCodeEnum.ERROR, msg);
    }


    /**
     * 返回 Result
     *
     * @param code 状态码
     * @param msg  音讯
     * @param <T>  T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> error(int code, String msg) {return new Result<>(code, null, msg);
    }

    /**
     * 返回 Result
     *
     * @param 
     * @param <T>  T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> error(ResultCodeEnum resultCodeEnum) {return new Result<>(resultCodeEnum);
    }

    /**
     * 返回 Result
     *
     * @param 
     * @param msg   提示信息
     * @param <T>  T 响应数据
     * @返回 Result
     */
    public static <T> Result<T> error(ResultCodeEnum resultCodeEnum , String msg) {return new Result<>(resultCodeEnum, msg);
    }
    
    /**
     * 
     * @param <T>
     * @param flag
     * @return
     */
    public static <T> Result<T> result(boolean flag) {return flag ? Result.success("操作胜利") : Result.error("操作失败");
    }

}

PageResult 类:

package com.gitegg.platform.boot.common.base;

import java.util.List;

import com.gitegg.platform.boot.common.enums.ResultCodeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @ClassName: PageResult
 * @Description: 通用分页返回
 * @author GitEgg
 * @date
 * @param <T>
 */
@Data
@ApiModel("通用分页响应类")
public class PageResult<T> {@ApiModelProperty(value = "是否胜利", required = true)
    private boolean success;

    @ApiModelProperty(value ="响应代码", required = true)
    private int code;

    @ApiModelProperty(value ="提示信息", required = true)
    private String msg;

    @ApiModelProperty(value ="总数量", required = true)
    private long count;

    @ApiModelProperty(value ="分页数据")
    private List<T> data;

    public PageResult(long total, List<T> rows) {
        this.count = total;
        this.data = rows;
        this.code = ResultCodeEnum.SUCCESS.code;
        this.msg = ResultCodeEnum.SUCCESS.msg;
    }
}

3、自定义通用响应音讯枚举类 ResultCodeEnum。

package com.gitegg.platform.boot.common.enums;


/**
 * @ClassName: ResultCodeEnum
 * @Description: 自定义返回码枚举
 * @author GitEgg
 * @date 2020 年 09 月 19 日 下午 11:49:45
 */
public enum ResultCodeEnum {

    /**
     * 胜利
     */
    SUCCESS(200, "操作胜利"),

    /**
     * 零碎谬误
     */
    ERROR(500, "零碎谬误"),

    /**
     * 操作失败
     */
    FAILED(101, "操作失败"),

    /**
     * 未登录 / 登录超时
     */
    UNAUTHORIZED(102, "登录超时"),

    /**
     * 参数谬误
     */
    PARAM_ERROR(103, "参数谬误"),

    /**
     * 参数谬误 - 已存在
     */
    INVALID_PARAM_EXIST(104, "申请参数已存在"),

    /**
     * 参数谬误
     */
    INVALID_PARAM_EMPTY(105, "申请参数为空"),

    /**
     * 参数谬误
     */
    PARAM_TYPE_MISMATCH(106, "参数类型不匹配"),

    /**
     * 参数谬误
     */
    PARAM_VALID_ERROR(107, "参数校验失败"),

    /**
     * 参数谬误
     */
    ILLEGAL_REQUEST(108, "非法申请"),

    /**
     * 验证码谬误
     */
    INVALID_VCODE(204, "验证码谬误"),

    /**
     * 用户名或明码谬误
     */
    INVALID_USERNAME_PASSWORD(205, "账号或明码谬误"),

    /**
     *
     */
    INVALID_RE_PASSWORD(206, "两次输出明码不统一"),

    /**
     * 用户名或明码谬误
     */
    INVALID_OLD_PASSWORD(207, "旧明码谬误"),

    /**
     * 用户名反复
     */
    USERNAME_ALREADY_IN(208, "用户名已存在"),

    /**
     * 用户不存在
     */
    INVALID_USERNAME(209, "用户名不存在"),

    /**
     * 角色不存在
     */
    INVALID_ROLE(210, "角色不存在"),

    /**
     * 角色不存在
     */
    ROLE_USED(211, "角色应用中,不可删除"),

    /**
     * 没有权限
     */
    NO_PERMISSION(403, "以后用户无该接口权限");

    public int code;

    public String msg;

    ResultCodeEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {return code;}

    public void setCode(int code) {this.code = code;}

    public String getMsg() {return msg;}

    public void setMsg(String msg) {this.msg = msg;}
}

4、自定义异样类 BusinessException 和 SystemException

package com.gitegg.platform.boot.common.exception;

import com.gitegg.platform.boot.common.enums.ResultCodeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

/**
 * @ClassName: BusinessException
 * @Description: 业务解决异样
 * @author GitEgg
 * @date
 */
@Getter
@Setter
public class BusinessException extends RuntimeException {

    private int code;

    private String msg;

    public BusinessException() {
        this.code = ResultCodeEnum.FAILED.code;
        this.msg = ResultCodeEnum.FAILED.msg;
    }

    public BusinessException(String message) {
        this.code = ResultCodeEnum.FAILED.code;
        this.msg = message;
    }

    public BusinessException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public BusinessException(Throwable cause) {super(cause);
    }

    public BusinessException(String message, Throwable cause) {super(message, cause);
    }

}
package com.gitegg.platform.boot.common.exception;

import com.gitegg.platform.boot.common.enums.ResultCodeEnum;
import lombok.Getter;

/**
 * @ClassName: SystemException
 * @Description: 零碎解决异样
 * @author GitEgg
 * @date
 */
@Getter
public class SystemException extends RuntimeException {

    private int code;

    private String msg;

    public SystemException() {
        this.code = ResultCodeEnum.ERROR.code;
        this.msg = ResultCodeEnum.ERROR.msg;
    }

    public SystemException(String message) {
        this.code = ResultCodeEnum.ERROR.code;
        this.msg = message;
    }

    public SystemException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public SystemException(Throwable cause) {super(cause);
    }

    public SystemException(String message, Throwable cause) {super(message, cause);
    }

}

5、自定义对立异样解决类 GitEggControllerAdvice.java

package com.gitegg.platform.boot.common.advice;

import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.platform.boot.common.enums.ResultCodeEnum;
import com.gitegg.platform.boot.common.exception.BusinessException;
import com.gitegg.platform.boot.common.exception.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.ui.Model;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

@Slf4j
@RestControllerAdvice
public class GitEggControllerAdvice {

    /**
     * 服务名
     */
    @Value("${spring.application.name}")
    private String serverName;

    /**
     * 微服务零碎标识
     */
    private String errorSystem;

    @PostConstruct
    public void init() {this.errorSystem = new StringBuffer()
                .append(this.serverName)
                .append(":").toString();}

    /**
     * 利用到所有 @RequestMapping 注解办法,在其执行之前初始化数据绑定器
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) { }

    /**
     * 把值绑定到 Model 中,使全局 @RequestMapping 能够获取到该值
     */
    @ModelAttribute
    public void addAttributes(Model model) { }

    /**
     * 全局异样捕获解决
     */
    @ExceptionHandler(value = {Exception.class})
    public Result handlerException(Exception exception, HttpServletRequest request) {log.error("申请门路 uri={}, 零碎外部出现异常:{}", request.getRequestURI(), exception);
        Result result = Result.error(ResultCodeEnum.ERROR, errorSystem + exception.toString());
        return result;
    }

    /**
     * 非法申请异样
     */
    @ExceptionHandler(value = {
            HttpMediaTypeNotAcceptableException.class,
            HttpMediaTypeNotSupportedException.class,
            HttpRequestMethodNotSupportedException.class,
            MissingServletRequestParameterException.class,
            NoHandlerFoundException.class,
            MissingPathVariableException.class,
            HttpMessageNotReadableException.class
    })
    public Result handlerSpringAOPException(Exception exception) {Result result = Result.error(ResultCodeEnum.ILLEGAL_REQUEST, errorSystem + exception.getMessage());
        return result;
    }

    /**
     * 非法申请异样 - 参数类型不匹配
     */
    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public Result handlerSpringAOPException(MethodArgumentTypeMismatchException exception) {Result result = Result.error(ResultCodeEnum.PARAM_TYPE_MISMATCH, errorSystem + exception.getMessage());
        return result;
    }

    /**
     * 非法申请 - 参数校验
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public Result handlerMethodArgumentNotValidException(MethodArgumentNotValidException methodArgumentNotValidException) {
        // 获取异样字段及对应的异样信息
        StringBuffer stringBuffer = new StringBuffer();
        methodArgumentNotValidException.getBindingResult().getFieldErrors().stream()
                .map(t -> t.getField()+"=>"+t.getDefaultMessage()+" ")
                .forEach(e -> stringBuffer.append(e));
        String errorMessage = stringBuffer.toString();
        Result result = Result.error(ResultCodeEnum.PARAM_VALID_ERROR, errorSystem + errorMessage);
        return result;
    }

    /**
     * 非法申请异样 - 参数校验
     */
    @ExceptionHandler(value = {ConstraintViolationException.class})
    public Result handlerConstraintViolationException(ConstraintViolationException constraintViolationException) {String errorMessage = constraintViolationException.getLocalizedMessage();
        Result result = Result.error(ResultCodeEnum.PARAM_VALID_ERROR, errorSystem + errorMessage);
        return result;
    }

    /**
     * 自定义业务异样 -BusinessException
     */
    @ExceptionHandler(value = {BusinessException.class})
    public Result handlerCustomException(BusinessException exception) {String errorMessage = exception.getMsg();
        Result result = Result.error(exception.getCode(), errorSystem + errorMessage);
        return result;
    }

    /**
     * 自定义零碎异样 -SystemException
     */
    @ExceptionHandler(value = {SystemException.class})
    public Result handlerCustomException(SystemException exception) {String errorMessage = exception.getMsg();
        Result result = Result.error(exception.getCode(), errorSystem + errorMessage);
        return result;
    }

}

6、从新将 GitEgg-Platform 进行 install,在 GitEgg-Cloud 中的 gitegg-service 引入 gitegg-platform-boot

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>GitEgg-Cloud</artifactId>
        <groupId>com.gitegg.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gitegg-service</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>gitegg-service-base</module>
        <module>gitegg-service-bigdata</module>
        <module>gitegg-service-system</module>
    </modules>

    <dependencies>
        <!-- gitegg Spring Boot 自定义及扩大 -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-boot</artifactId>
        </dependency>
        <!-- gitegg 数据库驱动及连接池 -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-db</artifactId>
        </dependency>
        <!-- gitegg mybatis-plus -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-mybatis</artifactId>
        </dependency>
        <!-- gitegg swagger2-knife4j -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-swagger</artifactId>
        </dependency>
        <!-- spring boot web 外围包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring boot 衰弱监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

</project>

7、批改 SystemController.java、ISystemService.java 和 SystemServiceImpl.java 减少异样解决的测试代码

SystemController.java:

package com.gitegg.service.system.controller;

import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.platform.boot.common.exception.BusinessException;
import com.gitegg.service.system.service.ISystemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "system")
@AllArgsConstructor
@Api(tags = "gitegg-system")
public class SystemController {

    private final ISystemService systemService;

    @GetMapping(value = "list")
    @ApiOperation(value = "system list 接口")
    public Object list() {return systemService.list();
    }


    @GetMapping(value = "page")
    @ApiOperation(value = "system page 接口")
    public Object page() {return systemService.page();
    }

    @GetMapping(value = "exception")
    @ApiOperation(value = "自定义异样及返回测试接口")
    public Result<String> exception() {return Result.data(systemService.exception());
    }
}

ISystemService.java:

package com.gitegg.service.system.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gitegg.service.system.entity.SystemTable;

import java.util.List;

public interface ISystemService {List<SystemTable> list();

    Page<SystemTable> page();

    String exception();}

SystemServiceImpl.java:

package com.gitegg.service.system.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gitegg.platform.boot.common.exception.BusinessException;
import com.gitegg.service.system.entity.SystemTable;
import com.gitegg.service.system.mapper.SystemTableMapper;
import com.gitegg.service.system.service.ISystemService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 *
 */
@Service
@AllArgsConstructor
public class SystemServiceImpl implements ISystemService {

    private final SystemTableMapper systemTableMapper;

    @Override
    public List<SystemTable> list() {return systemTableMapper.list();
    }

    @Override
    public Page<SystemTable> page() {Page<SystemTable> page = new Page<>(1, 10);
        List<SystemTable> records = systemTableMapper.page(page);
        page.setRecords(records);
        return page;
    }

    @Override
    public String exception() {throw new BusinessException("自定义异样");
//        return "胜利取得数据";
    }
}

8、运行 GitEggSystemApplication,关上浏览器拜访:http://127.0.0.1:8001/doc.html,而后点击左侧的异样解决接口,应用 Swagger2 进行测试,即可看到后果

本文源码在 https://gitee.com/wmz1930/GitEgg 的 chapter-07 分支。

退出移动版