[Spring MVC] - 从数据库读取MessageSource
Spring MVC中使用MessageSource默认是写在properties文件当中,以支持国际化。
但很多时候我们需要把数据写到数据库当中,而不是在properties文件当中,以方便日常维护。
1、先看Spring配置
- <!-- 默认的注解映射的支持 -->
- <mvc:annotation-driven validator="validator" conversion-service="conversionService" />
- <!-- 资源文件 -->
- <bean id="propertiesMessageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
- <property name="basenames">
- <list>
- <value>resource</value>
- <value>validation</value>
- </list>
- </property>
- </bean>
- <bean id="databaseMessageSource" class="com.obs2.util.MessageResource">
- <property name="parentMessageSource" ref="propertiesMessageSource"/>
- </bean>
- <bean id="messageInterpolator" class="com.obs2.util.MessageResourceInterpolator">
- <property name="messageResource" ref="databaseMessageSource"/>
- </bean>
- <!-- 验证器 -->
- <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
- <property name="messageInterpolator" ref="messageInterpolator"/>
- </bean>
这里定义了一个propertiesMessageSource,一个databaseMessageSourcer,和一个messageInterpolator。
propertiesMessageSource用于读取properties文件
databaseMessageSourcer用于读取数据库的数据配置,其中,有一个属性设置它的父MessageSource为propertiesMessageSource。意思是如果数据库找不到对应的数据,到properties文件当中查找。
messageInterpolator是个拦截器。
2、数据库的POJO定义:
- package com.obs2.dao.impl.bean;
- import java.io.Serializable;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Table;
- @Entity
- @SuppressWarnings("serial")
- @Table(name="resource")
- public class Resource implements Serializable {
- @Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
- @Column(name="resource_id")
- private long resourceId;
- @Column(name="name", length=50, nullable=false)
- private String name;
- @Column(name="text", length=1000, nullable=false)
- private String text;
- @Column(name="language", length=5, nullable=false)
- private String language;
- public long getResourceId() {
- return resourceId;
- }
- public void setResourceId(long resourceId) {
- this.resourceId = resourceId;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getText() {
- return text;
- }
- public void setText(String text) {
- this.text = text;
- }
- public String getLanguage() {
- return language;
- }
- public void setLanguage(String language) {
- this.language = language;
- }
- }
定义了一张表[resource],字段有:[resource_id]、[name]、[text]、[language]
具体的DAO、Service操作方法这里忽略不写了。
3、读取数据库的MessageResource类
- package com.obs2.util;
- import java.text.MessageFormat;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
- import javax.annotation.Resource;
- import org.springframework.context.ResourceLoaderAware;
- import org.springframework.context.support.AbstractMessageSource;
- import org.springframework.core.io.DefaultResourceLoader;
- import org.springframework.core.io.ResourceLoader;
- import com.obs2.service.ResourceService;
- /**
- * 取得资源数据
- * @author Robin
- *
- */
- public class MessageResource extends AbstractMessageSource implements ResourceLoaderAware {
- @SuppressWarnings("unused")
- private ResourceLoader resourceLoader;
- @Resource
- private ResourceService resourceService;
- /**
- * Map切分字符
- */
- protected final String MAP_SPLIT_CODE = "|";
- protected final String DB_SPLIT_CODE = "_";
- private final Map<String, String> properties = new HashMap<String, String>();
- public MessageResource() {
- // reload();
- }
- public void reload() {
- properties.clear();
- properties.putAll(loadTexts());
- }
- protected Map<String, String> loadTexts() {
- Map<String, String> mapResource = new HashMap<String, String>();
- List<com.obs2.service.bean.Resource> resources = resourceService.findAll();
- for (com.obs2.service.bean.Resource item : resources) {
- String code = item.getName() + MAP_SPLIT_CODE + item.getLanguage();
- mapResource.put(code, item.getText());
- }
- return mapResource;
- }
- private String getText(String code, Locale locale) {
- String localeCode = locale.getLanguage() + DB_SPLIT_CODE + locale.getCountry();
- String key = code + MAP_SPLIT_CODE + localeCode;
- String localeText = properties.get(key);
- String resourceText = code;
- if(localeText != null) {
- resourceText = localeText;
- }
- else {
- localeCode = Locale.ENGLISH.getLanguage();
- key = code + MAP_SPLIT_CODE + localeCode;
- localeText = properties.get(key);
- if(localeText != null) {
- resourceText = localeText;
- }
- else {
- try {
- if(getParentMessageSource() != null) {
- resourceText = getParentMessageSource().getMessage(code, null, locale);
- }
- } catch (Exception e) {
- logger.error("Cannot find message with code: " + code);
- }
- }
- }
- return resourceText;
- }
- @Override
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
- }
- @Override
- protected MessageFormat resolveCode(String code, Locale locale) {
- String msg = getText(code, locale);
- MessageFormat result = createMessageFormat(msg, locale);
- return result;
- }
- @Override
- protected String resolveCodeWithoutArguments(String code, Locale locale) {
- String result = getText(code, locale);
- return result;
- }
- }
主要是重载AbstractMessageSource和ResourceLoaderAware,以实现Spring MVC的MessageSource国际化调用。
类中的reload()方法,我把它写到了一个ServletListener当中,让项目启动时,自动加载数据到static的map中。
4、这是Listener:
- package com.obs2.util;
- import javax.servlet.ServletContext;
- import javax.servlet.ServletContextAttributeEvent;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
- import javax.servlet.http.HttpSessionEvent;
- import org.springframework.web.context.WebApplicationContext;
- import org.springframework.web.context.support.WebApplicationContextUtils;
- /**
- * 系统启动监听
- * @author Robin
- *
- */
- public class SystemListener implements ServletContextListener {
- /**
- * context初始化时激发
- */
- @Override
- public void contextInitialized(ServletContextEvent e) {
- //------------------------------------------------------------
- // 取得ServletContext
- //------------------------------------------------------------
- ServletContext context = e.getServletContext();
- WebApplicationContext applicationContext = WebApplicationContextUtils .getWebApplicationContext(context);
- //------------------------------------------------------------
- // 设置国际化多语言
- //------------------------------------------------------------
- MessageResource messageSource = applicationContext.getBean(MessageResource.class);
- messageSource.reload();
- }
- /**
- * context删除时激发
- */
- @Override
- public void contextDestroyed(ServletContextEvent e) {
- }
- /**
- * 创建一个 session时激发
- * @param e
- */
- public void sessionCreated(HttpSessionEvent e) {
- }
- /**
- * 当一个 session失效时激发
- * @param e
- */
- public void sessionDestroyed(HttpSessionEvent e) {
- }
- /**
- * 设置 context的属性,它将激发attributeReplaced或attributeAdded方法
- * @param e
- */
- public void setContext(HttpSessionEvent e) {
- }
- /**
- * 增加一个新的属性时激发
- * @param e
- */
- public void attributeAdded(ServletContextAttributeEvent e) {
- }
- /**
- * 删除一个新的属性时激发
- * @param e
- */
- public void attributeRemoved(ServletContextAttributeEvent e) {
- }
- /**
- * 属性被替代时激发
- * @param e
- */
- public void attributeReplaced(ServletContextAttributeEvent e) {
- }
- }
当然了,Listener需要加入到web.xml当中:
- <!-- 系统启动监听 -->
- <listener>
- <listener-class>com.obs2.util.SystemListener</listener-class>
- </listener>
4、Interceptor拦截器
- package com.obs2.util;
- import java.text.MessageFormat;
- import java.util.Iterator;
- import java.util.Locale;
- import java.util.Map;
- import java.util.Map.Entry;
- import javax.annotation.Resource;
- import javax.validation.MessageInterpolator;
- import org.springframework.binding.message.MessageBuilder;
- /**
- * 拦截Annotation验证信息
- * @author Robin
- *
- */
- public class MessageResourceInterpolator implements MessageInterpolator {
- @Resource
- private MessageResource messageResource;
- public void setMessageResource(MessageResource messageResource) {
- this.messageResource = messageResource;
- }
- @Override
- public String interpolate(String messageTemplate, Context context) {
- String messageTemp = null;
- if(messageTemplate.startsWith("{") && messageTemplate.endsWith("}")) {
- messageTemp = messageTemplate.substring(1, messageTemplate.length() - 1);
- }
- else {
- return messageTemplate;
- }
- String[] params = (String[]) context.getConstraintDescriptor().getAttributes().get("params");
- MessageBuilder builder = new MessageBuilder().code(messageTemp);
- if (params != null) {
- for (String param : params) {
- builder = builder.arg(param);
- }
- }
- String result = builder.build().resolveMessage(messageResource, Locale.ENGLISH).getText();
- return result;
- }
- @Override
- public String interpolate(String messageTemplate, Context context, Locale locale) {
- String messageTemp = null;
- if(messageTemplate.startsWith("{") && messageTemplate.endsWith("}")) {
- messageTemp = messageTemplate.substring(1, messageTemplate.length() - 1);
- }
- else {
- return messageTemplate;
- }
- String[] params = (String[]) context.getConstraintDescriptor().getAttributes().get("params");
- MessageBuilder builder = new MessageBuilder().code(messageTemp);
- if (params != null) {
- builder = builder.args(params);
- }
- String result = builder.build().resolveMessage(messageResource, locale).getText();
- return result;
- }
- }
事实上,不使用拦截器,上面的数据库MessageSource类已经可以工作了。但在使用hibernate的Annotation的validator时,不加入拦截器,是不行的,它不会触发。
这类里调用了一个jar包:spring-binding-2.3.1.RELEASE.jar
自行上网搜搜下载。
一切完成,测试下,写一个domain entity:
- package com.obs2.controller.bean;
- import javax.validation.constraints.Min;
- import org.hibernate.validator.constraints.NotEmpty;
- import com.obs2.controller.validator.UserName;
- public class Account {
- @UserName(format="^[\\w_]+$", message="{valid.userName}", min=6, max=30)
- private String userName;
- @NotEmpty(message="{valid.required}")
- private String password;
- @Min(value=18, message="{valid.ageMin}")
- private int age;
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
写一个简单的view(这里使用的是freemarker)
- <#assign c=JspTaglibs["http://java.sun.com/jsp/jstl/core"] />
- <#assign fmt=JspTaglibs["http://java.sun.com/jsp/jstl/fmt"] />
- <#assign fn=JspTaglibs["http://java.sun.com/jsp/jstl/functions"] />
- <#assign st=JspTaglibs["http://www.springframework.org/tags"] />
- <#assign form=JspTaglibs["http://www.springframework.org/tags/form"] />
- <head>
- <title>Login</title>
- </head>
- <body>
- <@form.form action="${request.contextPath}/passport/login" method="post" modelAttribute="account">
- User name:<@form.input path="userName"/><@form.errors path="userName"/><br/>
- Password:<@form.password path="password"/><@form.errors path="password" /><br/>
- Age:<@form.input path="age"/><@form.errors path="age" /><br/>
- <input type="submit" value="Login" />
- </@form.form>
- </body>
将看到:
这种方法还有一个小BUG,就是在使用annotation validator时,如果使用了替换符,似乎不起作用。暂时没研究出来,谁搞出来了,麻烦留个言提示下。so thx.
代码中直接调用,可以这样写:
- resource.getMessage("valid.ageMin", new Object[]{"age",18}, request.getLocale())
[Spring MVC] - 从数据库读取MessageSource的更多相关文章
- Spring MVC 属性文件读取注入到静态字段
目录(?)[-] servlet-contextxml configproperties 示例属性 ConfigInfo 对应的配置bean 使用 在项目中,有些参数需要配置到属性文件xxx.pr ...
- spring mvc中的service和controller中读取不到properties值
根据web.xml读取配置文件中的顺序来看 controller层和service层来自于spring mvc.xml中读取,所以必须要在spring mvc.xml中配置读取资源文件夹方式
- Spring MVC程序中得到静态资源文件css,js,图片
转载自:http://www.blogjava.net/fiele/archive/2014/08/24/417283.html 用 Spring MVC 开发应用程序,对于初学者有一个很头疼的问题, ...
- Spring MVC程序中得到静态资源文件css,js,图片文件的路径问题总结
上一篇 | 下一篇 Spring MVC程序中得到静态资源文件css,js,图片 文件的路径 问题总结 作者:轻舞肥羊 日期:2012-11-26 http://www.blogjava.net/fi ...
- ssm整合说明与模板-Spring Spring MVC Mybatis整合开发
ssm整合说明 spring+spring mvc+mybatis 说明 源码下载 由于之前存在ssh框架,spring+struts+hibernate,其中spring负责aop与ioc,所以一般 ...
- Spring MVC程序中怎么得到静态资源文件css,js,图片文件的路径问题
问题描述 在用springmvc开发应用程序的时候.对于像我一样的初学者,而且还是自学的人,有一个很头疼的问题.那就是数据都已经查出来了,但是页面的样式仍然十分简陋,加载不了css.js,图片等资源文 ...
- spring boot --- 使用 注解 读取 properties 文件 信息
1.前言 以前使用spring MVC框架 ,读取properties 配置文件需要写一大堆东西 ,也许 那时候 不怎么使用注解 ,现在使用spring boot ,发现了非常简便的办法---使用注解 ...
- Spring MVC基础知识整理➣Spring+SpringMVC+Hibernate整合操作数据库
概述 Hibernate是一款优秀的ORM框架,能够连接并操作数据库,包括保存和修改数据.Spring MVC是Java的web框架,能够将Hibernate集成进去,完成数据的CRUD.Hibern ...
- Spring MVC篇二、使用JdbcTemplate进行数据库操作
上一篇只是一个简单的Spring MVC框架,接下来添加一些跟数据库的交互. 一.添加jdbc相关配置 在maven中添加相关依赖后,配置数据库访问参数及数据源.数据库参数使用配置文件,代码如下: ...
随机推荐
- 重载运算符:类成员函数or友元函数
类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...
- 安装PLSQL,登录报“无法解析指定的连接标识符的错误”
安装PLSQL,本地不需要安装oracle服务器,但要安装oracle客户端. 一.安装客户端需要配置服务命名,tnsnames.oRA文件和监听(因为我开始没有配置监听,所以一直报无法解析制定的连接 ...
- ASP.NET Repeater 控件分页
protected void Page_Load(object sender, EventArgs e) { HttpContext context = HttpContext.Current; co ...
- oracle 将多字段数据合成一个
1.系统默认 WMSYS.WM_CONCAT(A.ID), 2.再进行替换 REPLACE(WMSYS.WM_CONCAT(A.ID),',','|'), (张)
- sql server 2008中清除数据库日志的sql语句
第一步: Use 数据库名 Select NAME,size From sys.database_files 将“数据库名”改为需要清除日志的数据库名字,点击“执行”查询出需要清除的日志名称:**_ ...
- mvc4 部署http错误403.14 forbidden
1. 检查服务器上是否安装了“HTTP重定向”功能和“静态内容压缩”功能(在添加/删除程序或增加角色处安装).这是我所遇到的问题:2. 应用程序池要被配置为“集成”3. 把.net 4.0安装在iis ...
- Unity3D–RectTransfrom 记录笔记
一.基本要点 部分来源:http://www.2fz1.com/post/unity-ugui-recttransform/ RectTransform继承于Trasnfrom , 在Trasnfor ...
- AIX上通过IPSEC进行IP包过滤
AIX上的IPSEC 在AIX可以通过以下步骤打开IP Security smitty ipsec4 --> Start/Stop IP Security --> Start IP Sec ...
- myeclipse10中文注释乱码问题
将别人的项目或JAVA文件导入到自己的Eclipse中时,常常会出现JAVA文件的中文注释变成乱码的情况,主要原因就是别人的IDE编码格式和自己的Eclipse编码格式不同. 总结网上的建议和自己的体 ...
- 用bugzilla统计BUG
bugzilla—— reports—— Tabular reports—— 选择版本号啥的跟search一样 上面的行标Vertical Axis选Resolution:列标Horizontal A ...