长沙企业建网站费用,移动互联网开发课程设计报告,企业网易邮箱,做音乐网站需要版权么文章目录 处理转发失败的情况全局参数同一返回格式操作消息对象AjaxResult返回值状态描述对象AjaxStatus返回值枚举接口层StatusCode 全局异常处理器自定义通用异常定一个自定义异常覆盖默认的异常处理自定义异常处理工具 在上一篇章时我们有了一个简单的gateway网关 [Spring C… 文章目录 处理转发失败的情况全局参数同一返回格式操作消息对象AjaxResult返回值状态描述对象AjaxStatus返回值枚举接口层StatusCode 全局异常处理器自定义通用异常定一个自定义异常覆盖默认的异常处理自定义异常处理工具 在上一篇章时我们有了一个简单的gateway网关 [Spring Cloud] gateway简单搭建与请求转发-CSDN博客 现在我们需要根据这个网关进行一部分的改进 现在我们需要进一步的处理一些问题来使得网关更加完善。 本篇文章的完整代码文件已放置在gitee。 杉极简/gateway网关阶段学习
处理转发失败的情况
正常情况下我们请求了一个接口并得到了一个结果如下 但是我们依然要考虑如果访问到一个不存在的接口会得到什么样的结果 如果不做任何修改的时候我们会得到以下的结果 但这不是我们想要的。 我们想要如下返回结果。 因此我们需要配置一个全局异常处理器来处理。 为达到这个目的我们开始构建一些基础的功能描述如下。
全局参数
我们需要去创建一个全部配置如下所示 这里统一存放着我们需要读取的配置主要为全局使用的参数。具体配置方式如下所示 在网关项目中创建一个config文件夹用于存放网关的相关配置。当然能想做网关的人应该都熟练的会使用Spring Boot了在Spring Boot项目中这都是一些较为基础的内容 此时我们先配置一个全局异常捕捉-打印堆栈异常的参数用于本文的一些功能当中。
global:# 全局异常捕捉-打印堆栈异常printStackTrace: trueimport lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** author fir* date 2023/7/28 17:53*/
Data
Component
ConfigurationProperties(prefix global)
public class GlobalConfig {/*** 全局异常捕捉-打印堆栈异常*/private boolean printStackTrace;
}同一返回格式
创建一个result文件夹用于存放统一返回值的相关配置 该部分比较基础暂时只说明配置方式与代码。
操作消息对象AjaxResult
import java.io.Serializable;
import java.util.HashMap;/*** 操作消息-JSON** author fir*/
public class AjaxResult extends HashMapString, Object implements Serializable {private static final long serialVersionUID 1L;/*** 状态码*/public static final String CODE_TAG code;/*** 返回内容*/public static final String MSG_TAG msg;/*** 数据对象*/public static final String DATA_TAG data;/*** 初始化一个新创建的 AjaxResult 对象使其表示一个空消息。*/public AjaxResult() {}/*** 初始化一个新创建的 AjaxResult 对象** param code 状态码* param msg 状态描述*/public AjaxResult(int code, String msg) {super.put(CODE_TAG, code);super.put(MSG_TAG, msg);}/*** 初始化一个新创建的 AjaxResult 对象** param code 状态码* param msg 状态描述* param data 数据对象*/public AjaxResult(int code, String msg, Object data) {super.put(CODE_TAG, code);super.put(MSG_TAG, msg);if (data ! null) {super.put(DATA_TAG, data);}}/*** 返回成功消息** return 成功消息*/public static AjaxResult success() {AjaxStatus success AjaxStatus.SUCCESS;return AjaxResult.success(success.getCode(), success.getMsg());}/*** 返回成功数据** return 成功消息*/public static AjaxResult success(Object data) {AjaxStatus success AjaxStatus.SUCCESS;return AjaxResult.success(success.getMsg(), data);}/*** 返回成功数据** return 成功消息*/public static AjaxResult success(AjaxStatus success) {return AjaxResult.success(success.getMsg(), new HashMap(0));}/*** 返回成功消息** param code 状态吗* param msg 状态描述* return 消息体*/public static AjaxResult success(Integer code, String msg) {return new AjaxResult(code, msg);}/*** 返回成功消息** param msg 状态描述* param data 数据对象* return 成功消息*/public static AjaxResult success(String msg, Object data) {AjaxStatus success AjaxStatus.SUCCESS;return new AjaxResult(success.getCode(), msg, data);}/*** 返回特定状态描述** param statusCode 特定的枚举结果* param data 数据对象* return 请求结果*/public static AjaxResult success(StatusCode statusCode, Object data) {return new AjaxResult(statusCode.getCode(), statusCode.getMsg(), data);}/*** 返回错误消息** return 警告消息*/public static AjaxResult error() {return AjaxResult.error(AjaxStatus.LOSE_OPERATION.getMsg());}/*** 返回错误消息** param msg 状态描述* return 警告消息*/public static AjaxResult error(String msg) {return AjaxResult.error(msg, new HashMap(0));}/*** 返回错误消息** param msg 状态描述* param data 数据对象* return 警告消息*/public static AjaxResult error(String msg, Object data) {AjaxStatus loseEfficacy AjaxStatus.LOSE_EFFICACY;return new AjaxResult(loseEfficacy.getCode(), msg, data);}/*** 返回错误消息** param code 状态码* param msg 状态描述* return 警告消息*/public static AjaxResult error(int code, String msg) {return new AjaxResult(code, msg, new HashMap(0));}/*** 返回特定状态描述** param statusCode 特定的枚举结果* param data 数据对象* return 请求结果*/public static AjaxResult error(StatusCode statusCode, Object data) {return new AjaxResult(statusCode.getCode(), statusCode.getMsg(), data);}/*** 返回特定状态描述** param statusCode 特定的枚举结果* return 请求结果*/public static AjaxResult error(StatusCode statusCode) {return new AjaxResult(statusCode.getCode(), statusCode.getMsg(), new HashMap(0));}
}
返回值状态描述对象AjaxStatus
import lombok.Getter;/*** 返回值状态与描述* * author fir*/Getter
public enum AjaxStatus implements StatusCode {/*** 请求成功*/SUCCESS(200, 请求成功),/*** 登录成功*/SUCCESS_LOGIN(200, 登录成功),/*** 登出成功*/SUCCESS_LOGOUT(200, 登出成功),/*** 启动成功*/SUCCESS_FLOW_START(200, 启动成功),/*** 暂无数据*/NO_DATA(200, 暂无数据),/*** 错误请求*/BAD_REQUEST(400, 错误请求),/*** 登录过期*/EXPIRATION_TOKEN(401, 登录过期),/*** 服务不存在*/FAILED_SERVICE_DOES(404, 服务不存在),/*** 账号或密码为空*/NULL_LOGIN_DATA(480, 账号或密码为空),/*** 建立通信-通信建立失败*/FAILED_COMMUNICATION(481, 通信建立失败),/*** 接口不存在*/NULL_API(404, 接口不存在),/*** 建立通信-非法请求*/ILLEGAL_REQUEST(482, 非法请求),/*** 请求失败*/LOSE_EFFICACY(490, 请求失败),/*** 操作失败*/LOSE_OPERATION(491, 操作失败),/*** 请求失败*/FAILED(500, 请求失败),/*** 服务不可用(gateway网关总定义-所有未定义处理的异常都返回该异常)*/SERVICE_UNAVAILABLE(500, 服务不可用),/*** 请求整体加密-无效会话*/SESSION_INVALID(601, 无效会话),/*** 请求整体加密-会话过期*/SESSION_EXPIRE(602, 会话过期),/*** 防重放校验失败*/ANTI_REPLAY_VERIFY_FAILED(701, 防重放校验失败),/*** 防重放校验失败*/INTEGRITY_VERIFY_FAILED(801, 完整性校验失败),/*** 预留*/PASS(1000, 请求失败);private final int code;private final String msg;AjaxStatus(int code, String msg) {this.code code;this.msg msg;}
}返回值枚举接口层StatusCode
package com.fir.gateway.config.result;/*** 返回值枚举接口层* author 18714*/
public interface StatusCode {/*** 获取code信息** return code码*/int getCode();/*** 获取msg信息** return msg描述*/String getMsg();
}全局异常处理器
做两步
覆盖默认的异常处理。自定义异常处理。
自定义通用异常
通常的处理过程为抛出异常-全局异常捕捉-返回前端 通常在代码中对于某个特定的条件我们抛出一个自定义异常并携带特定的状态码与状态描述
if (session null) {throw new CustomException(AjaxStatus.SESSION_INVALID);
}而此时我们在开发环境中通常需要显示堆栈异常但是生成环境中大多数是不需要的此时我们就是用了全局参数配置在自定义异常工具这个类中我们配置了定义异常默认不打印堆栈异常。
定一个自定义异常
import com.fir.gateway.config.result.AjaxStatus;
import lombok.Getter;/*** 自定义通用异常* 抛出异常-全局异常捕捉-返回前端** author fir*/
Getter
public class CustomException extends RuntimeException {/*** code状态码*/private final int code;/*** 错误状态码*/private final AjaxStatus ajaxStatus;public CustomException(AjaxStatus ajaxStatus) {super(ajaxStatus.getMsg());this.code ajaxStatus.getCode();this.ajaxStatus ajaxStatus;}}覆盖默认的异常处理
此时我们覆盖默认的异常处理并使用自定义的异常处理工具JsonExceptionHandler。
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;import java.util.Collections;
import java.util.List;/*** 覆盖默认的异常处理* author fir*/
Configuration
EnableConfigurationProperties({ServerProperties.class, WebProperties.class})
public class ErrorHandlerConfiguration {private final ServerProperties serverProperties;private final ApplicationContext applicationContext;private final WebProperties webProperties;private final ListViewResolver viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public ErrorHandlerConfiguration(ServerProperties serverProperties,WebProperties webProperties,ObjectProviderListViewResolver viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer,ApplicationContext applicationContext) {this.serverProperties serverProperties;this.applicationContext applicationContext;this.webProperties webProperties;this.viewResolvers viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer serverCodecConfigurer;}BeanOrder(Ordered.HIGHEST_PRECEDENCE)public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {JsonExceptionHandler exceptionHandler new JsonExceptionHandler(errorAttributes,this.webProperties,this.serverProperties.getError(),this.applicationContext);exceptionHandler.setViewResolvers(this.viewResolvers);exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());return exceptionHandler;}}自定义异常处理工具
解决三个问题
处理自定义异常处理不存在的接口对于其他的异常统一返回一个指定的错误描述AjaxStatus.SERVICE_UNAVAILABLE。
package com.fir.gateway.config.exception;import com.fir.gateway.config.GlobalConfig;
import com.fir.gateway.config.result.AjaxResult;
import com.fir.gateway.config.result.AjaxStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;import javax.annotation.Resource;/*** 自定义异常处理工具* 异常时用JSON代替HTML异常信息** author fir*/
Slf4j
public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {/*** 网关参数配置*/Resourceprivate GlobalConfig globalConfig;public JsonExceptionHandler(ErrorAttributes errorAttributes, WebProperties webProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {super(errorAttributes, webProperties.getResources(), errorProperties, applicationContext);log.info(String.valueOf(errorProperties));log.info(String.valueOf(errorAttributes));}/*** 重构方法设置返回属性格式*/Overrideprotected MonoServerResponse renderErrorResponse(ServerRequest request) {Throwable errorThrowable getError(request);// 自定义异常默认不打印堆栈异常// 决定是否打印堆栈异常boolean printStackTrace globalConfig.isPrintStackTrace();if (printStackTrace) {errorThrowable.printStackTrace();}// 打印全局异常log.error(errorThrowable.getMessage());Class? errorClass errorThrowable.getClass();String simpleName errorClass.getSimpleName();AjaxStatus ajaxStatus;switch (simpleName) {case CustomException:// 处理自定义异常CustomException customException (CustomException) errorThrowable;ajaxStatus customException.getAjaxStatus();break;case NotFoundException:case ResponseStatusException:// 处理404ajaxStatus AjaxStatus.NULL_API;break;default:// 统一返回一个服务错误描述ajaxStatus AjaxStatus.SERVICE_UNAVAILABLE;break;}AjaxResult result AjaxResult.error(ajaxStatus);return ServerResponse.status(200).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(result));}
}