写在前面: 低头走路,更应抬头看路

为什么写这个

Spring作为Web层框架的经典框架,已经走过了十几年了。在项目过程中使用的点滴,如不整理便容易流于琐碎,不成系统。而单纯学习某个知识点不运用到项目之中变不深刻。近期打算把最近几个月做的项目整理一下,以作梳理和总结。这里主要记录下在项目中使用的国际化操作,因为要在系统支持中英文,所以可以使用国际化来对操作的日志信息进行记录,并做可视化以被查验。

怎么做

使用Spring的支持国际化bean

①org.springframework.context.support.ReloadableResourceBundleMessageSource(每次加载)
②org.springframework.context.support.ResourceBundleMessageSource(加载一次)

这里就直接写在项目中的配置方式:

<bean id="applicationContextUtil" class="com.jzvasp.common.utils.ApplicationContextUtil"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>com.jzvasp.common.log.global.logGlobalResource</value>
        </list>
    </property>
</bean>

上面的是多个国际化文件的配置,用list
如果是单文件的话,如下设置:

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
     <property name="basename"> 
          <value>com.jzvasp.common.log.global.logGlobalResource</value> 
     </property> 
</bean>

国际化资源文件:

我们在com.jzvasp.common.log.global包下建两个文件:
①logGlobalResource_en_US.properties US资源
exportHeat = user “{0}” export heat statistics “{1}”
sumExportRating = export Rating Statistics Excel
②logGlobalResource_zh_CN.properties 中文资源
exportHeat = 用户 “{0}” 导出热度统计 “{1}”
sumExportRating = 导出收视率统计Excel

ApplicationContext

在使用中,为了拿到messageSource对象,我们需要先获得ApplicationContext对象,可以通过它的方法:
Object org.springframework.beans.factory.BeanFactory.getBean(String key)获取。
自定义ApplicationContextUtil.java

public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context)throws BeansException {
        ApplicationContextUtil.context = context;
    }

    public static ApplicationContext getContext() {
        return context;
    }

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    public static void setContext(ApplicationContext context) {
        ApplicationContextUtil.context = context;
    }

    public static Object getBean(String key){
        return context.getBean(key);
    }
}

自定义添加log的参数:

public class AddLogParam {
    private String key;         //国际化日志文件的key
    private String key1;        //子key,非必要
    private Object[] param;     //key值里面可能要的参数,没有参数就为null
    private String state;       //操作状态,暂时1表示成功,0表示失败
    private String username;    //操作者名

    public AddLogParam(){}

    public AddLogParam(String key, Object[] param, String state) {
        super();
        this.key = key;
        this.param = param;
        this.state = state;
    }
    public AddLogParam(String key, Object[] param, String state, String username) {
        super();
        this.key = key;
        this.param = param;
        this.state = state;
        this.username = username;
    }

    public AddLogParam(String key, String key1, Object[] param, String state, String username) {
        super();
        this.key = key;
        this.key1 = key1;
        this.param = param;
        this.state = state;
        this.username = username;
    }

    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getKey1() {
        return key1;
    }

    public void setKey1(String key1) {
        this.key1 = key1;
    }
    public Object[] getParam() {
        return param;
    }
    public void setParam(Object[] param) {
        this.param = param;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

封装LogService如下:

public boolean addLog(AddLogParam param, HttpServletRequest request) {
    if(param != null){
        String language = "zh_CN";
        Cookie myCookie[]=request.getCookies();//创建一个Cookie对象数组
        if(null!=myCookie && myCookie.length>0){
            for(int i=0;i<myCookie.length;i++){
                Cookie newCookie= myCookie[i];
                if(newCookie.getName().equals("jzad_language")){
                    language = newCookie.getValue();
                    break;
                }
            }
        }
        //从cookie中取出当前语言后,获取对应的国际化日志数据,getParam()数组的元素会赋值给国际化文件中的{0}等通配符
        String content = getMessage(param.getKey(), param.getParam(), language);
        String summary = getMessage(param.getKey1(), param.getParam(), language);
        LogBean log = new LogBean();
        log.setOperateContent(content);
        log.setSummary(summary);
        log.setState(param.getState());
        log.setUserName(param.getUsername());
        Date date = new Date();
        log.setAddTime(CommonsUtil.changeDateToString(date, CommonsUtil.DEFAULT_DATETIME_FORMAT));
        logDao.save(log);//将日志数据存到数据库中
        return true;
    }
    return false;
}

private static String getMessage(String key, Object[] params, String local) {
    MessageSource messageSource = (MessageSource) ApplicationContextUtil.getBean("messageSource");
    Locale cal = null;
    if ("zh_CN".equals(local)) {
        cal = Locale.CHINA;
    }
    if ("zh_TW".equals(local)) {
        cal = Locale.TAIWAN;
    }
    if ("en_US".equals(local)) {
        cal = Locale.US;
    }
    String msg = messageSource.getMessage(key, params, cal);
    return msg;
}

测试

在Action中如下使用即可:

UserJson user = (UserJson) session.get("user");
AddLogParam logparam = new AddLogParam("exportHeat", "sumExportRating", 
            new Object[] { user.getUserName(), "" }, "2", user.getUserName());

这里将国际化文件中的Key以及参数传递到Service层,然后通过getMessage获取完整信息并保存到数据库中。

结图:

spring 国际化 数据库 spring国际化配置_Source


如果本地测试,可以直接使用下面这种方式:

context = new ClassPathXmlApplicationContext(
                new String[] { "spring.xml" });

System.out.println(context.getMessage("exportHeat", new Object[]{"admin", ""}, Locale.US));
//user "admin" export heat statistics ""

结束

虽然只是一个很小的点,记录一下,以便后面用到的时候查看。