mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	完善 SpringMVC 组件,增加统一 /api/ 前缀的封装
This commit is contained in:
		| @ -1,5 +1,6 @@ | |||||||
| { | { | ||||||
|   "local": { |   "local": { | ||||||
|     "baseUrl": "http://127.0.0.1:8080" |     "baseUrl": "http://127.0.0.1:8080/api", | ||||||
|  |     "token": "eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2MDk2ODE2MzEsInN1YiI6ImE3ZGE1MWE2YWUyYTQxOWRhNmExYTlkYmJiMTVmZjc4In0.RXG7alSz64lE9oPSgbnYT_KsX7kvoHVhF5oHxXHztr1KjsttOqOppSmHGBYFI7Y75bsjEBSxSqbGsS1O1S2b1w" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ ENV = 'development' | |||||||
|  |  | ||||||
| # 若依管理系统/开发环境 | # 若依管理系统/开发环境 | ||||||
| VUE_APP_BASE_API = '/dev-api' | VUE_APP_BASE_API = '/dev-api' | ||||||
|  | # VUE_APP_BASE_API = '/api' | ||||||
|  |  | ||||||
| # 路由懒加载 | # 路由懒加载 | ||||||
| VUE_CLI_BABEL_TRANSPILE_MODULES = true | VUE_CLI_BABEL_TRANSPILE_MODULES = true | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ export function logout() { | |||||||
| // 获取验证码 | // 获取验证码 | ||||||
| export function getCodeImg() { | export function getCodeImg() { | ||||||
|   return request({ |   return request({ | ||||||
|     url: '/captchaImage', |     url: '/captcha/get-image', | ||||||
|     method: 'get' |     method: 'get' | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
| @ -8,7 +8,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' | |||||||
| // 创建axios实例 | // 创建axios实例 | ||||||
| const service = axios.create({ | const service = axios.create({ | ||||||
|   // axios中请求配置有baseURL选项,表示请求URL公共部分 |   // axios中请求配置有baseURL选项,表示请求URL公共部分 | ||||||
|   baseURL: process.env.VUE_APP_BASE_API, |   baseURL: process.env.VUE_APP_BASE_API + '/api/', // 此处的 /api/ 地址,原因是后端的基础路径为 /api/ | ||||||
|   // 超时 |   // 超时 | ||||||
|   timeout: 10000 |   timeout: 10000 | ||||||
| }) | }) | ||||||
| @ -76,13 +76,13 @@ service.interceptors.response.use(res => { | |||||||
|       }) |       }) | ||||||
|       return Promise.reject('error') |       return Promise.reject('error') | ||||||
|     } else { |     } else { | ||||||
|       return res.data |       return res.data.data // 第二层 data 才是后端返回的 CommonResult.data | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   error => { |   error => { | ||||||
|     console.log('err' + error) |     console.log('err' + error) | ||||||
|     let { message } = error; |     let { message } = error; | ||||||
|     if (message == "Network Error") { |     if (message === "Network Error") { | ||||||
|       message = "后端接口连接异常"; |       message = "后端接口连接异常"; | ||||||
|     } |     } | ||||||
|     else if (message.includes("timeout")) { |     else if (message.includes("timeout")) { | ||||||
|  | |||||||
| @ -57,9 +57,7 @@ public class SwaggerAutoConfiguration { | |||||||
|                 .paths(PathSelectors.any()) |                 .paths(PathSelectors.any()) | ||||||
|                 .build() |                 .build() | ||||||
|                 .securitySchemes(securitySchemes()) |                 .securitySchemes(securitySchemes()) | ||||||
|                 .securityContexts(securityContexts()) |                 .securityContexts(securityContexts()); | ||||||
| //                .pathMapping() TODO 芋艿:稍后解决,统一 api 前缀 |  | ||||||
|                 ; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -0,0 +1,80 @@ | |||||||
|  | package cn.iocoder.dashboard.framework.web.config; | ||||||
|  |  | ||||||
|  | import com.alibaba.fastjson.serializer.SerializerFeature; | ||||||
|  | import com.alibaba.fastjson.support.config.FastJsonConfig; | ||||||
|  | import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; | ||||||
|  | import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.core.annotation.Order; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
|  | import org.springframework.http.converter.HttpMessageConverter; | ||||||
|  | import org.springframework.web.bind.annotation.RestController; | ||||||
|  | import org.springframework.web.cors.CorsConfiguration; | ||||||
|  | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||||||
|  | import org.springframework.web.filter.CorsFilter; | ||||||
|  | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; | ||||||
|  | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||||||
|  |  | ||||||
|  | import javax.annotation.Resource; | ||||||
|  | import java.nio.charset.Charset; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.function.Predicate; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Web 配置类 | ||||||
|  |  */ | ||||||
|  | @Configuration | ||||||
|  | @EnableConfigurationProperties(WebProperties.class) | ||||||
|  | public class WebConfiguration implements WebMvcConfigurer { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private WebProperties webProperties; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void configurePathMatch(PathMatchConfigurer configurer) { | ||||||
|  |         configurer.addPathPrefix(webProperties.getApiPrefix(), clazz -> | ||||||
|  |                 clazz.isAnnotationPresent(RestController.class) | ||||||
|  |                 && clazz.getPackage().getName().contains("cn.iocoder.dashboard")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // ========== MessageConverter 相关 ========== | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | ||||||
|  |         // 创建 FastJsonHttpMessageConverter 对象 | ||||||
|  |         FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); | ||||||
|  |         // 自定义 FastJson 配置 | ||||||
|  |         FastJsonConfig fastJsonConfig = new FastJsonConfig(); | ||||||
|  |         fastJsonConfig.setCharset(Charset.defaultCharset()); // 设置字符集 | ||||||
|  |         fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, // 剔除循环引用 | ||||||
|  |                 SerializerFeature.WriteNonStringKeyAsString); // 解决 Integer 作为 Key 时,转换为 String 类型,避免浏览器报错 | ||||||
|  |         fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); | ||||||
|  |         // 设置支持的 MediaType | ||||||
|  |         fastJsonHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); | ||||||
|  |         // 添加到 converters 中 | ||||||
|  |         converters.add(0, fastJsonHttpMessageConverter); // 注意,添加到最开头,放在 MappingJackson2XmlHttpMessageConverter 前面 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // ========== Filter 相关 ========== | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建 CorsFilter Bean,解决跨域问题 | ||||||
|  |      */ | ||||||
|  |     @Bean | ||||||
|  |     @Order(Integer.MIN_VALUE) | ||||||
|  |     public CorsFilter corsFilter() { | ||||||
|  |         // 创建 CorsConfiguration 对象 | ||||||
|  |         CorsConfiguration config = new CorsConfiguration(); | ||||||
|  |         config.setAllowCredentials(true); | ||||||
|  |         config.addAllowedOriginPattern("*"); // 设置访问源地址 | ||||||
|  |         config.addAllowedHeader("*"); // 设置访问源请求头 | ||||||
|  |         config.addAllowedMethod("*"); // 设置访问源请求方法 | ||||||
|  |         // 创建 UrlBasedCorsConfigurationSource 对象 | ||||||
|  |         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||||||
|  |         source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置 | ||||||
|  |         return new CorsFilter(source); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,27 @@ | |||||||
|  | package cn.iocoder.dashboard.framework.web.config; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import org.springframework.boot.context.properties.ConfigurationProperties; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; | ||||||
|  |  | ||||||
|  | import javax.validation.constraints.NotNull; | ||||||
|  |  | ||||||
|  | @ConfigurationProperties(prefix = "yudao.web") | ||||||
|  | @Validated | ||||||
|  | @Data | ||||||
|  | public class WebProperties { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀 | ||||||
|  |      * | ||||||
|  |      * | ||||||
|  |      * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题 | ||||||
|  |      *      这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。 | ||||||
|  |      * | ||||||
|  |      * @see WebConfiguration#configurePathMatch(PathMatchConfigurer) | ||||||
|  |      */ | ||||||
|  |     @NotNull(message = "API 前缀不能为空") | ||||||
|  |     private String apiPrefix; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,257 @@ | |||||||
|  | package cn.iocoder.dashboard.framework.web.core.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.common.exception.GlobalException; | ||||||
|  | import cn.iocoder.dashboard.common.exception.ServiceException; | ||||||
|  | import cn.iocoder.dashboard.common.pojo.CommonResult; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.validation.BindException; | ||||||
|  | import org.springframework.validation.FieldError; | ||||||
|  | import org.springframework.web.HttpRequestMethodNotSupportedException; | ||||||
|  | import org.springframework.web.bind.MethodArgumentNotValidException; | ||||||
|  | import org.springframework.web.bind.MissingServletRequestParameterException; | ||||||
|  | import org.springframework.web.bind.annotation.ExceptionHandler; | ||||||
|  | import org.springframework.web.bind.annotation.RestControllerAdvice; | ||||||
|  | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; | ||||||
|  | import org.springframework.web.servlet.NoHandlerFoundException; | ||||||
|  |  | ||||||
|  | import javax.servlet.http.HttpServletRequest; | ||||||
|  | import javax.validation.ConstraintViolation; | ||||||
|  | import javax.validation.ConstraintViolationException; | ||||||
|  | import javax.validation.ValidationException; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.*; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号 | ||||||
|  |  */ | ||||||
|  | @RestControllerAdvice | ||||||
|  | @Slf4j | ||||||
|  | public class GlobalExceptionHandler { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理所有异常,主要是提供给 Filter 使用 | ||||||
|  |      * 因为 Filter 不走 SpringMVC 的流程,但是我们又需要兜底处理异常,所以这里提供一个全量的异常处理过程,保持逻辑统一。 | ||||||
|  |      * | ||||||
|  |      * @param request 请求 | ||||||
|  |      * @param ex 异常 | ||||||
|  |      * @return 通用返回 | ||||||
|  |      */ | ||||||
|  |     public CommonResult<?> allExceptionHandler(HttpServletRequest request, Throwable ex) { | ||||||
|  |         if (ex instanceof MissingServletRequestParameterException) { | ||||||
|  |             return missingServletRequestParameterExceptionHandler((MissingServletRequestParameterException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof MethodArgumentTypeMismatchException) { | ||||||
|  |             return methodArgumentTypeMismatchExceptionHandler((MethodArgumentTypeMismatchException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof MethodArgumentNotValidException) { | ||||||
|  |             return methodArgumentNotValidExceptionExceptionHandler((MethodArgumentNotValidException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof BindException) { | ||||||
|  |             return bindExceptionHandler((BindException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof ConstraintViolationException) { | ||||||
|  |             return constraintViolationExceptionHandler((ConstraintViolationException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof ValidationException) { | ||||||
|  |             return validationException((ValidationException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof NoHandlerFoundException) { | ||||||
|  |             return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof HttpRequestMethodNotSupportedException) { | ||||||
|  |             return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof ServiceException) { | ||||||
|  |             return serviceExceptionHandler((ServiceException) ex); | ||||||
|  |         } | ||||||
|  |         if (ex instanceof GlobalException) { | ||||||
|  |             return globalExceptionHandler(request, (GlobalException) ex); | ||||||
|  |         } | ||||||
|  |         return defaultExceptionHandler(request, ex); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 SpringMVC 请求参数缺失 | ||||||
|  |      * | ||||||
|  |      * 例如说,接口上设置了 @RequestParam("xx") 参数,结果并未传递 xx 参数 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(value = MissingServletRequestParameterException.class) | ||||||
|  |     public CommonResult<?> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex) { | ||||||
|  |         log.warn("[missingServletRequestParameterExceptionHandler]", ex); | ||||||
|  |         return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s", ex.getParameterName())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 SpringMVC 请求参数类型错误 | ||||||
|  |      * | ||||||
|  |      * 例如说,接口上设置了 @RequestParam("xx") 参数为 Integer,结果传递 xx 参数类型为 String | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(MethodArgumentTypeMismatchException.class) | ||||||
|  |     public CommonResult<?> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) { | ||||||
|  |         log.warn("[missingServletRequestParameterExceptionHandler]", ex); | ||||||
|  |         return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 SpringMVC 参数校验不正确 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(MethodArgumentNotValidException.class) | ||||||
|  |     public CommonResult<?> methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) { | ||||||
|  |         log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex); | ||||||
|  |         FieldError fieldError = ex.getBindingResult().getFieldError(); | ||||||
|  |         assert fieldError != null; // 断言,避免告警 | ||||||
|  |         return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 SpringMVC 参数绑定不正确,本质上也是通过 Validator 校验 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(BindException.class) | ||||||
|  |     public CommonResult<?> bindExceptionHandler(BindException ex) { | ||||||
|  |         log.warn("[handleBindException]", ex); | ||||||
|  |         FieldError fieldError = ex.getFieldError(); | ||||||
|  |         assert fieldError != null; // 断言,避免告警 | ||||||
|  |         return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 Validator 校验不通过产生的异常 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(value = ConstraintViolationException.class) | ||||||
|  |     public CommonResult<?> constraintViolationExceptionHandler(ConstraintViolationException ex) { | ||||||
|  |         log.warn("[constraintViolationExceptionHandler]", ex); | ||||||
|  |         ConstraintViolation<?> constraintViolation = ex.getConstraintViolations().iterator().next(); | ||||||
|  |         return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", constraintViolation.getMessage())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 Dubbo Consumer 本地参数校验时,抛出的 ValidationException 异常 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(value = ValidationException.class) | ||||||
|  |     public CommonResult<?> validationException(ValidationException ex) { | ||||||
|  |         log.warn("[constraintViolationExceptionHandler]", ex); | ||||||
|  |         // 无法拼接明细的错误信息,因为 Dubbo Consumer 抛出 ValidationException 异常时,是直接的字符串信息,且人类不可读 | ||||||
|  |         return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 SpringMVC 请求地址不存在 | ||||||
|  |      * | ||||||
|  |      * 注意,它需要设置如下两个配置项: | ||||||
|  |      * 1. spring.mvc.throw-exception-if-no-handler-found 为 true | ||||||
|  |      * 2. spring.mvc.static-path-pattern 为 /statics/** | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(NoHandlerFoundException.class) | ||||||
|  |     public CommonResult<?> noHandlerFoundExceptionHandler(NoHandlerFoundException ex) { | ||||||
|  |         log.warn("[noHandlerFoundExceptionHandler]", ex); | ||||||
|  |         return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理 SpringMVC 请求方法不正确 | ||||||
|  |      * | ||||||
|  |      * 例如说,A 接口的方法为 GET 方式,结果请求方法为 POST 方式,导致不匹配 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(HttpRequestMethodNotSupportedException.class) | ||||||
|  |     public CommonResult<?> httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { | ||||||
|  |         log.warn("[httpRequestMethodNotSupportedExceptionHandler]", ex); | ||||||
|  |         return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理业务异常 ServiceException | ||||||
|  |      * | ||||||
|  |      * 例如说,商品库存不足,用户手机号已存在。 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(value = ServiceException.class) | ||||||
|  |     public CommonResult<?> serviceExceptionHandler(ServiceException ex) { | ||||||
|  |         log.info("[serviceExceptionHandler]", ex); | ||||||
|  |         return CommonResult.error(ex.getCode(), ex.getMessage()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理全局异常 ServiceException | ||||||
|  |      * | ||||||
|  |      * 例如说,Dubbo 请求超时,调用的 Dubbo 服务系统异常 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(value = GlobalException.class) | ||||||
|  |     public CommonResult<?> globalExceptionHandler(HttpServletRequest req, GlobalException ex) { | ||||||
|  |         // 系统异常时,才打印异常日志 | ||||||
|  |         if (INTERNAL_SERVER_ERROR.getCode().equals(ex.getCode())) { | ||||||
|  |             // 插入异常日志 | ||||||
|  |             this.createExceptionLog(req, ex); | ||||||
|  |         // 普通全局异常,打印 info 日志即可 | ||||||
|  |         } else { | ||||||
|  |             log.info("[globalExceptionHandler]", ex); | ||||||
|  |         } | ||||||
|  |         // 返回 ERROR CommonResult | ||||||
|  |         return CommonResult.error(ex); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 处理系统异常,兜底处理所有的一切 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(value = Exception.class) | ||||||
|  |     public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) { | ||||||
|  |         log.error("[defaultExceptionHandler]", ex); | ||||||
|  |         // 插入异常日志 | ||||||
|  |         this.createExceptionLog(req, ex); | ||||||
|  |         // 返回 ERROR CommonResult | ||||||
|  |         return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMessage()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // TODO 芋艿:增加异常日志 | ||||||
|  |     public void createExceptionLog(HttpServletRequest req, Throwable e) { | ||||||
|  | //        // 插入异常日志 | ||||||
|  | //        SystemExceptionLogCreateDTO exceptionLog = new SystemExceptionLogCreateDTO(); | ||||||
|  | //        try { | ||||||
|  | //            // 增加异常计数 metrics TODO 暂时去掉 | ||||||
|  | ////            EXCEPTION_COUNTER.increment(); | ||||||
|  | //            // 初始化 exceptionLog | ||||||
|  | //            initExceptionLog(exceptionLog, req, e); | ||||||
|  | //            // 执行插入 exceptionLog | ||||||
|  | //            createExceptionLog(exceptionLog); | ||||||
|  | //        } catch (Throwable th) { | ||||||
|  | //            log.error("[createExceptionLog][插入访问日志({}) 发生异常({})", JSON.toJSONString(exceptionLog), ExceptionUtils.getRootCauseMessage(th)); | ||||||
|  | //        } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | //    // TODO 优化点:后续可以增加事件 | ||||||
|  | //    @Async | ||||||
|  | //    public void createExceptionLog(SystemExceptionLogCreateDTO exceptionLog) { | ||||||
|  | //        try { | ||||||
|  | //            systemExceptionLogRpc.createSystemExceptionLog(exceptionLog); | ||||||
|  | //        } catch (Throwable th) { | ||||||
|  | //            log.error("[addAccessLog][插入异常日志({}) 发生异常({})", JSON.toJSONString(exceptionLog), ExceptionUtils.getRootCauseMessage(th)); | ||||||
|  | //        } | ||||||
|  | //    } | ||||||
|  | // | ||||||
|  | //    private void initExceptionLog(SystemExceptionLogCreateDTO exceptionLog, HttpServletRequest request, Throwable e) { | ||||||
|  | //        // 设置账号编号 | ||||||
|  | //        exceptionLog.setUserId(CommonWebUtil.getUserId(request)); | ||||||
|  | //        exceptionLog.setUserType(CommonWebUtil.getUserType(request)); | ||||||
|  | //        // 设置异常字段 | ||||||
|  | //        exceptionLog.setExceptionName(e.getClass().getName()); | ||||||
|  | //        exceptionLog.setExceptionMessage(ExceptionUtil.getMessage(e)); | ||||||
|  | //        exceptionLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e)); | ||||||
|  | //        exceptionLog.setExceptionStackTrace(ExceptionUtil.getStackTrace(e)); | ||||||
|  | //        StackTraceElement[] stackTraceElements = e.getStackTrace(); | ||||||
|  | //        Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空"); | ||||||
|  | //        StackTraceElement stackTraceElement = stackTraceElements[0]; | ||||||
|  | //        exceptionLog.setExceptionClassName(stackTraceElement.getClassName()); | ||||||
|  | //        exceptionLog.setExceptionFileName(stackTraceElement.getFileName()); | ||||||
|  | //        exceptionLog.setExceptionMethodName(stackTraceElement.getMethodName()); | ||||||
|  | //        exceptionLog.setExceptionLineNumber(stackTraceElement.getLineNumber()); | ||||||
|  | //        // 设置其它字段 | ||||||
|  | //        exceptionLog.setTraceId(MallUtils.getTraceId()) | ||||||
|  | //                .setApplicationName(applicationName) | ||||||
|  | //                .setUri(request.getRequestURI()) // TODO 提升:如果想要优化,可以使用 Swagger 的 @ApiOperation 注解。 | ||||||
|  | //                .setQueryString(HttpUtil.buildQueryString(request)) | ||||||
|  | //                .setMethod(request.getMethod()) | ||||||
|  | //                .setUserAgent(HttpUtil.getUserAgent(request)) | ||||||
|  | //                .setIp(HttpUtil.getIp(request)) | ||||||
|  | //                .setExceptionTime(new Date()); | ||||||
|  | //    } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1 @@ | |||||||
|  | package cn.iocoder.dashboard.framework.web.core; | ||||||
| @ -0,0 +1,4 @@ | |||||||
|  | /** | ||||||
|  |  * 针对 SpringMVC 的基础封装 | ||||||
|  |  */ | ||||||
|  | package cn.iocoder.dashboard.framework.web; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | <http://www.iocoder.cn/Spring-Boot/SpringMVC/?dashboard> | ||||||
| @ -20,6 +20,8 @@ spring: | |||||||
|  |  | ||||||
| # 芋道配置项,设置当前项目所有自定义的配置 | # 芋道配置项,设置当前项目所有自定义的配置 | ||||||
| yudao: | yudao: | ||||||
|  |   web: | ||||||
|  |     api-prefix: /api | ||||||
|   security: |   security: | ||||||
|     token-header: Authorization |     token-header: Authorization | ||||||
|     token-secret: abcdefghijklmnopqrstuvwxyz |     token-secret: abcdefghijklmnopqrstuvwxyz | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV