业务场景
之前文章中已经描述了具体的业务场景,可以点击此处查看。现在完成上篇文章中业务场景3(对需要返回给前端的实体表或者VO实体中含有需要切换语言的字段进行切换语言)
实现步骤
1、定两个注解I18nModel,I18nModelProperty
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
** 这个注解在实体类上使用 用来标记哪些实体是需要转换的
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface I18nModel {
String value() default "";
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 多语言转换属性注解,用在字段上面
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface I18nModelProperty {
/**
* 目标字段
*/
String target();
/**
* 当前字段语言
*/
String language() default "zh-CN";
}
2、接着我们使用aop对spring的ResponseBody返回对象进行统一处理
import com.ljz.xd.easyadmincommon.annotation.I18nModel;
import com.ljz.xd.easyadmincommon.annotation.I18nModelProperty;
import com.ljz.xd.easyadmincommon.result.model.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.lang.reflect.Field;
@ControllerAdvice
public class ResultBodyAdvice implements ResponseBodyAdvice {
private static Logger logger = LoggerFactory.getLogger(ResultBodyAdvice.class);
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//只对自定义封装的实体做处理
if(body instanceof R){
//获取返回数据,并判断是否是需要转换的实体
Object data = ((R<?>) body).getData();
if(data != null && data.getClass().isAnnotationPresent(I18nModel.class)){
//如果是的话接着,判断那些字段需要转换
Field[] fields = data.getClass().getDeclaredFields();
for(Field field : fields){
if(field.isAnnotationPresent(I18nModelProperty.class)){
//获取注解对应的参数
I18nModelProperty i18nModelProperty = field.getAnnotation(I18nModelProperty.class);
String currentLanguage = LocaleContextHolder.getLocale().toLanguageTag();
//判断是否是当前语言
if(currentLanguage.equals(i18nModelProperty.language())){
try {
field.setAccessible(true);
//获取字段属性值
Object o = field.get(data);
//替换到目标位置
Field targetField = data.getClass().getDeclaredField(i18nModelProperty.target());
targetField.setAccessible(true);
targetField.set(data, o);
} catch (IllegalAccessException e) {
logger.error("获取i18nProperty值的时候失败",e);
} catch (NoSuchFieldException e) {
logger.error("i18nProperty替换指定字段的值的时候失败",e);
}
}
}
}
}
}
return body;
}
}
3、上面这样就可以了,下面展示下效果和使用
import com.ljz.xd.easyadmincommon.annotation.I18nModel;
import com.ljz.xd.easyadmincommon.annotation.I18nModelProperty;
/**
* 登录用户信息实体类
*
* @author ljz
* @date 2023/1/9 10:14
*/
@Data
@toString
@I18nModel
public class LoginUser {
//用户id
private Long userId;
//用户姓名
private String userName;
//用户密码
private String password;
//登录账号
private String loginAccount;
//这边是不同语言的查找出来的值,设置上目标字段名和当前字段对应的语言code
@I18nModelProperty(target = "userName",language = "en-US")
private String userNameEn;
}
@PostMapping("test")
public R<LoginUser> test(){
LoginUser user = new LoginUser();
user.setUserNameEn("testUser");
user.setUserName("测试用户");
return R.ok(user);
}
postman请求时当zh-CN的时候
请求当en-US时
可以看到上面的返回值中userName会根据语言返回不同的值,这样未来要是新增语言时前端就不用重新绑定字段