SpringBoot中對返回結果進行多語言切換方案(本文利用AOP實現)

相信很多朋友在做接口開發的時候返回給客戶端的提示需要根據不同的語言切換,如果是客戶端的那麼客戶端自己可以做,如果是服務端返回的,那就只能服務端在返回的同時做處理了,如果一個一個改,我的媽呀,什麼時候是個頭,唯一正確的方式就是使用AOP來實現,費話不多說,下面先貼上代碼:

import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springblade.core.tool.api.R;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 對請求參數進行攔截修改
 * @author yuxuan
 */
@Aspect
@Component
@AllArgsConstructor
@ConditionalOnProperty(prefix = "lang",name = "open",havingValue = "true")
public class LanguageAspect {

	private String objPreFix = "R";

	@Pointcut("execution(* com.rksj.controller.*.*(..))")
	public void annotationLangCut(){};

	/**
	 * 定義一個併發性Map用來存放信息
	 */
	Map<String, String> tmpMap = new ConcurrentHashMap<>();

	/**
	 * 在構造函數中進行初始化,後面可從配置文件中初始化
	 */
	public LanguageAspect(){
		//初始化 KEY爲簡體  VALUE爲  簡體###繁體###英文
		loadSysCfg();

	}

	/**
	 * 從配置文件加載
	 */
	private void loadSysCfg(){
		try{
			//加載配置文件
			Resource resource = new ClassPathResource("language");
			InputStream is = resource.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(is);
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String line = "";
			while( (line = bufferedReader.readLine()) != null ){
				//不爲空且以#號開頭的去掉,註釋部分
				if(StringUtils.isNotEmpty(line) && !line.startsWith("#")){
					String[] lines = line.split("###");
					tmpMap.put(lines[0], line);
				}
			}
		}catch (Exception e){
			e.printStackTrace();
		}
	}



	/**
	 * 攔截controller層返回的結果,修改msg字段
	 * @param point
	 * @param obj
	 */
	@AfterReturning(pointcut="annotationLangCut()",returning="obj")
	public void around(JoinPoint point, Object obj)  {
		Object backObj = obj;
		try{
			RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
			//從獲取RequestAttributes中獲取HttpServletRequest的信息
			HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
			String bladeLang = request.getHeader("x-language");
			if(!Objects.isNull(obj) && obj.toString().startsWith(objPreFix)){
				R<?> r = (R) obj;
				String tmpMsg = tmpMap.get(r.getMsg().trim());
				if(StringUtils.isNotEmpty(tmpMsg)){
					String[] tmpMsgs = tmpMsg.split("###");
					//說明格式無問題
					if(tmpMsgs.length == 3){
						if(!Objects.isNull(bladeLang)){
							//簡體
							if(bladeLang.equalsIgnoreCase("CN")){
								r.setMsg(tmpMsgs[0]);
								//繁體
							}else if(bladeLang.equalsIgnoreCase("TC")){
								r.setMsg(tmpMsgs[1]);
								//英文
							}else if(bladeLang.equalsIgnoreCase("EN")){
								r.setMsg(tmpMsgs[2]);
							}
							obj = r;
						}
					}
				}
			}
		}catch (Exception e){
			e.printStackTrace();
			//重新賦值給obj,防止try中途修改原始的值
			obj = backObj;
		}
	}
}

配置文件如下:

#格式爲 簡體中文###繁體中文###英文   行首以#開頭的爲註釋部分
成功###成功###Successful

需要在配置文件中配置

lang.open=true

則可以開啓此AOP攔截。R對象爲封裝的返回對象,其中msg爲提示信息。

是不是很簡單,感興趣的小夥伴可以關注我哦,每天更新干貨。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章