aop实现国际化i18n

1.在resource文件夹下添加i18n 夹及相关国际化配置properties文件
例如:message_zh_CN.properties 中文国际化文件里内容如下:
以实际的responseCode 获取对应的msg 翻译值。

0=成功
9999=系统异常
4=结果为空

message.properties是必须的,内容可以为空,但是必须有这个文件
在这里插入图片描述
2.项目配置文件里添加国际化配置,注:springboot项目里默认有国际化相关组件

spring:
  messages:
    basename: i18n/message #相对路径 开头不要添加斜杠
    encoding: UTF-8

3.代码连接国际化文件

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;

import java.util.Locale;

@Component
public class LocaleMessage {

    @Autowired
    private MessageSource messageSource;

    public String getMessage(String code){
        return this.getMessage(code,new Object[]{});
    }
    public String getMessage(String code,String defaultMessage){
        return this.getMessage(code,null,defaultMessage);
    }
    public String getMessage(String code,String defaultMessage,Locale locale){ return this.getMessage(code,null,defaultMessage,locale); }
    public String getMessage(String code,Locale locale){
        return this.getMessage(code,null,"",locale);
    }
    public String getMessage(String code,Object[] args){ return this.getMessage(code,args,""); }
    public String getMessage(String code,Object[] args,Locale locale){
        return this.getMessage(code,args,"",locale);
    }
    public String getMessage(String code,Object[] args,String defaultMessage){ return this.getMessage(code,args, defaultMessage,LocaleContextHolder.getLocale()); }
    public String getMessage(String code,Object[]args,String defaultMessage,Locale locale){
        return messageSource.getMessage(code,args, defaultMessage,locale); }

}

I18nUtils

import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class I18nUtils {

    @Autowired
    private LocaleMessage localeMessage;

    /**
     * 获取key
     *
     * @param key
     * @return
     */
    public  String getKey(String key) {
        String name = localeMessage.getMessage(key);
        return name;
    }

    /**
     * 获取指定哪个配置文件下的key
     *
     * @param key
     * @param local
     * @return
     */
    public  String getKey(String key, Locale local) {
        String name = localeMessage.getMessage(key, local);
        return name;
    }
}

4.切面中加入国际化处理

import com.midea.cloud.user.common.Response;
import com.midea.cloud.user.i18n.I18nUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Locale;

/**
 * weblog切面
 *
 * @author huangchong7
 * @date 2021/3/30 17:59
 */
@Aspect
@Component
public class WebI18nAspectConfig {

    public static final Logger log = LoggerFactory.getLogger(WebLogAspectConfig.class);


    @Autowired
    I18nUtils i18nUtils;

    public WebI18nAspectConfig () {
    }

    /**
     * 定义请求日志切入点,其切入点表达式有多种匹配方式,这里是指定路径
     */
    @Pointcut("execution(public * com.midea.cloud.user.controller.*.*(..))")
    public void i18nPointcut() {
    }


    /**
     * 前置通知:
     * 1. 在执行目标方法之前执行,比如请求接口之前的登录验证;
     * 2. 在前置通知中设置请求日志信息,如开始时间,请求参数,注解内容等
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before("i18nPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //打印请求的内容
        log.info("请求Url : {}", request.getRequestURL().toString());
        log.info("请求方式 : {}", request.getMethod());
        log.info("请求ip : {}", request.getRemoteAddr());
        log.info("请求方法 : {}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        log.info("请求参数 : {}", Arrays.toString(joinPoint.getArgs()));
    }

    /**
     * 返回通知:
     * 1. 在目标方法正常结束之后执行
     * 2. 在返回通知中补充请求日志信息,如返回时间,方法耗时,返回值,并且保存日志信息
     * 3. 国际化
     *
     * @param ret
     * @throws Throwable
     */
    @AfterReturning(returning = "ret", pointcut = "i18nPointcut()")
    public void doAfterReturning(Object ret) throws Throwable {
        Object resultObject = ret;
        try {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            //从获取RequestAttributes中获取HttpServletRequest的信息
            HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
            //在header里面传入需要使用的语言flag
            String langFlag = request.getHeader("lang");
            //在参数里传入需要的语言flag
            if (StringUtils.isEmpty(langFlag))
                langFlag = request.getParameter("lang");
            if (null != langFlag) {
                Response r = (Response) ret;
                String code = String.valueOf(r.getCode());
                String msg = r.getMsg().trim();
                if (StringUtils.isNotEmpty(msg)) {
                    if ("CN".equals(langFlag)) {
                        Locale locale = Locale.CHINA;
                        msg = i18nUtils.getKey(code, locale);
                    } else if ("EN".equals(langFlag)) {
                        Locale locale = Locale.US;
                        msg = i18nUtils.getKey(code, locale);
                    } else {
                        msg = i18nUtils.getKey(code);
                    }
                }
                r.setMsg(msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            //返回原值
            ret = resultObject;
        }
        // 处理完请求,返回内容
        log.info("请求返回 : {}", ret);
    }

    /**
     * 异常通知:
     * 1. 在目标方法非正常结束,发生异常或者抛出异常时执行
     * 1. 在异常通知中设置异常信息,并将其保存
     *
     * @param throwable
     */
    @AfterThrowing(value = "i18nPointcut()", throwing = "throwable")
    public void doAfterThrowing(Throwable throwable) {
        // 保存异常日志记录
        log.error("发生异常时间:{}", LocalDateTime.now());
        log.error("抛出异常:{}", throwable.getMessage());
    }
}

5.相关测试
响应码

package com.midea.cloud.user.enums;


public enum ResponseCode {
    //================== 通用系统错误码 ==================
    ERROR(9999, "system error"),
    SUCCESS(0, "success"),
    EMPTY(4, "result is empty");

    private int code;
    private String msg;

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

    public int getCode() {
        return code;
    }

    public String getStrCode() {
        return String.valueOf(code);
    }

    public String getMsg() {
        return msg;
    }

    /**
     * 通过错误码获取code对象
     *
     * @param errorCode
     * @return
     */
    public static ResponseCode getCode(int errorCode) {
        for (ResponseCode c : ResponseCode.values()) {
            if (errorCode == c.getCode()) {
                return c;
            }
        }
        return ERROR;
    }
}

响应类

import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * 响应类
 */
@Accessors(chain = true) //setter类型的链式编程
@Data
@ToString
public class Response implements Serializable {

    private static final long serialVersionUID = 1L;

    private int code = 0;

    private String msg = "success";

    private Long timestamp = System.currentTimeMillis();

    private Object data = null;


    public Response() {

    }


    public Response(Object data) {
        this.code = 0;
        this.timestamp = System.currentTimeMillis();
        this.msg = "success";
        this.data = data;
    }

    public Response(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.timestamp = timestamp;
        this.data = data;
    }

    public Response(int code, String msg, Object data, Long timestamp) {
        this.code = code;
        this.msg = msg;
        this.timestamp = timestamp;
        this.data = data;
    }

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

controller层

    @GetMapping("/getUserById")
    public Object getUserById(Integer id) {
        Response response = new Response();
        UserEntity userEntity = (UserEntity) redisUtils.get("BASE_USER_ID_" + id);
        if (null != userEntity)
            return response.setCode(ResponseCode.SUCCESS.getCode()).setMsg(ResponseCode.SUCCESS.getMsg()).setData(userEntity);
        userEntity = userMapper.selectByPrimaryKey(id);
        if (null != userEntity)
            redisUtils.set("BASE_USER_ID_" + id, userEntity);

        if (null!=userEntity)
            return response.setCode(ResponseCode.SUCCESS.getCode()).setMsg(ResponseCode.SUCCESS.getMsg()).setData(userEntity);


        return response.setCode(ResponseCode.EMPTY.getCode()).setMsg(ResponseCode.EMPTY.getMsg());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值