平时开发过程中,无可避免咱们须要解决各类异样,所以这里咱们在公共模块中自定义对立异样,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@ToStringpublic 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@Setterpublic 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 */@Getterpublic 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@RestControllerAdvicepublic 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@AllArgsConstructorpublic 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分支。