Skip to content

Commit

Permalink
feat: 新增国际化及全局异常码配置
Browse files Browse the repository at this point in the history
  • Loading branch information
wangjiangtao2 authored and Charles7c committed Jun 24, 2024
1 parent 07d9fdf commit ce08f28
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ public class PropertiesConstants {
*/
public static final String MESSAGING_WEBSOCKET = MESSAGING + StringConstants.DOT + "websocket";

/**
* 国际化配置
*/
public static final String I18N = WEB + StringConstants.DOT + "i18n";

private PropertiesConstants() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http:https://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.continew.starter.core.exception;

/**
* 统一错误码异常
*
* @author Jasmine
* @since 2.2.0
*/
public class GlobalException extends Exception {

private ResultInfoInterface resultInfo;

public GlobalException() {
}

public GlobalException(ResultInfoInterface resultInfo) {
this.resultInfo = resultInfo;
}

public ResultInfoInterface getResultInfo() {
return this.resultInfo;
}

public void setResultInfo(ResultInfoInterface resultInfo) {
this.resultInfo = resultInfo;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http:https://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.continew.starter.core.exception;

/**
* 接口返回码 所有业务异常都要继承该接口
*
* @author Jasmine
* @since 2.2.0
*/
public enum GlobalResultInfoEnum implements ResultInfoInterface {

/**
* 操作成功
*/
SUCCESS(200, "操作成功"),

/**
* 操作失败
*/
FAILED(500, "操作失败");

private int code;
private String messageKey;
private String defaultMessage;

GlobalResultInfoEnum(int code, String defaultMessage) {
this.code = code;
this.defaultMessage = defaultMessage;
}

GlobalResultInfoEnum(int code, String messageKey, String defaultMessage) {
this.code = code;
this.messageKey = messageKey;
this.defaultMessage = defaultMessage;
}

@Override
public int getCode() {
return this.code;
}

@Override
public String getMessageKey() {
return this.messageKey;
}

@Override
public String getDefaultMessage() {
return this.defaultMessage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http:https://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.continew.starter.core.exception;

/**
* 接口返回码与消息 所有业务异常都要继承该接口
*
* @author Jasmine
* @since 2.2.0
*/
public interface ResultInfoInterface {

/**
* 获取编码
*
* @return String
*/
int getCode();

/**
* 国际化消息key
*
* @return
*/
default String getMessageKey() {
return "";
}

/**
* 获取默认消息 若从国际化文件里没有获取到值,就取默认值
*
* @return String
*/
String getDefaultMessage();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
Expand All @@ -36,7 +38,11 @@
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.exception.BusinessException;
import top.continew.starter.core.exception.GlobalException;
import top.continew.starter.core.exception.ResultInfoInterface;
import top.continew.starter.web.autoconfigure.i18n.I18nProperties;
import top.continew.starter.web.model.R;
import top.continew.starter.web.util.MessageSourceUtils;

/**
* 全局异常处理器
Expand All @@ -49,6 +55,8 @@ public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

private static final String PARAM_FAILED = "请求地址 [{}],参数验证失败。";
@Resource
private I18nProperties i18nProperties;

/**
* 拦截自定义验证异常-错误请求
Expand Down Expand Up @@ -153,6 +161,23 @@ public R<Void> handleServiceException(BusinessException e, HttpServletRequest re
return R.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
}

/**
* 拦截全局应用异常
*/
@ExceptionHandler(GlobalException.class)
public R<Void> handleGlobalException(GlobalException e, HttpServletRequest request) {
log.error("请求地址 [{}],发生业务异常。", request.getRequestURI(), e);
ResultInfoInterface resultInfo = e.getResultInfo();
// 未开启,直接返回
if (!i18nProperties.getEnabled()) {
return R.fail(resultInfo.getCode(), resultInfo.getDefaultMessage());
}
// 以用户自定的messageKey优先,否则枚举当messageKey
String messageKey = StrUtil.blankToDefault(resultInfo.getMessageKey(), resultInfo.toString());
String message = MessageSourceUtils.getMessage(messageKey, resultInfo.getDefaultMessage());
return R.fail(resultInfo.getCode(), message);
}

/**
* 拦截未知的运行时异常
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;
import top.continew.starter.web.autoconfigure.i18n.I18nProperties;

/**
* 全局异常处理器自动配置
Expand All @@ -40,6 +42,7 @@
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(BasicErrorController.class)
@Import({GlobalExceptionHandler.class, GlobalErrorHandler.class})
@EnableConfigurationProperties(I18nProperties.class)
public class GlobalExceptionHandlerAutoConfiguration {

private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandlerAutoConfiguration.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http:https://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.continew.starter.web.autoconfigure.i18n;

import org.springframework.boot.context.properties.ConfigurationProperties;
import top.continew.starter.core.constant.PropertiesConstants;

/**
* 国际化 配置属性
*
* @author Jasmine
* @since 2.2.0
*/
@ConfigurationProperties(prefix = PropertiesConstants.I18N)
public class I18nProperties {

/**
* 国际化开启 true-开启, false-关闭
*/
private Boolean enabled;

public Boolean getEnabled() {
return enabled;
}

public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http:https://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.continew.starter.web.util;

import cn.hutool.extra.spring.SpringUtil;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;

/**
* @author Jasmine
* @since 2.2.0
*/
public class MessageSourceUtils {

private static final MessageSource messageSource = SpringUtil.getBean(MessageSource.class);

private static final Object[] emptyArray = new Object[] {};

public static String getMessage(String key) {
return getMessage(key, emptyArray);
}

public static String getMessage(String key, String defaultMessage) {
return getMessage(key, defaultMessage, emptyArray);
}

public static String getMessage(String msgKey, Object... args) {
return getMessage(msgKey, msgKey, args);
}

public static String getMessage(String msgKey, String defaultMessage, Object... args) {
try {
return messageSource.getMessage(msgKey, args, LocaleContextHolder.getLocale());
} catch (Exception e) {
return defaultMessage;
}
}

}

0 comments on commit ce08f28

Please sign in to comment.