ITKeyword,专注技术干货聚合推荐

注册 | 登录

spring mvc结合freemarker,使用hibernate validation框架做校验及国际化

gaoshanliushui2009 分享于 2015-05-30

推荐:Spring MVC国际化和整合Freemarker的国际化

spring 版本4.1.2  书写国际化文件 messages_en_US.properties  英语 loginFrom.username=login usernameloginFrom.password=login passwordlocale.selection

2019阿里云全部产品优惠券(新购或升级都可以使用,强烈推荐)
领取地址https://promotion.aliyun.com/ntms/yunparter/invite.html



源自:

spring mvc结合freemarker,使用hibernate validation框架做校验及国际化


搭建Spring,Spring MVC,Mybatis,freemarker等集成开发环境,为了增加数据校验和国际化花了好几天的时间(其实可以手动编写校验代码,或者使用spring mvc自带校验但不怎么好,故实现hibernate validation),本来如果阅读源代码会可能更快,但是没有时间静下心来阅读,只有工作间隙中去网上查资料,但是尝试了很多次都没能成功,直到今天发现了Spring mvc集成hibernate的validation框架的潜规则后才算成功,Spring MVC校验有两种:1是继承org.springframework.validation.Validator类,2是使用JSR303规范Hibernate Validator,下面讲第2种实现。

 

前提spring和spring mvc是3.2.5版,hibernate的validation是4.2.0版,mybatis是3.2.3,freemarker是2.3.20版(这里再废话下,网上找了一堆全是抄来抄去,就算抄也先验证ok后再转发)。这里主要采用的是spring mvc与freemarker结合做web页面传入到controller的数据验证及国际化验证消息。目前我验证freemarker的ftl文件有两种方式:(1)结合spring mvc的spring.tld和spring-form.tld标签库实现;(2)结合spring mvc的spring.ftl宏定义文件实现。

 

两种实现都需要配合错误消息文件,消息文件:A自定义消息文件名,B使用hibernate的默认的消息文件名,它是在hibernate-validator-4.2.0.Final.jar包中的/org/hibernate/validator/ValidationMessages.properties中。建议使用hibernate的默认名称。

 

以下把两种共同的配置如下

1.      web.xml的配置

<web-appxmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0">

  <display-name>mwsys-shop</display-name>

 

  <context-param>

     <param-name>contextConfigLocation</param-name>

     <param-value>/WEB-INF/classes/config/spring/*.xml</param-value>

  </context-param>

  <context-param>

     <param-name>log4jConfigLocation</param-name>

     <param-value>/WEB-INF/classes/log4j.properties</param-value>

  </context-param>

  <context-param>

     <param-name>webAppRootKey</param-name>

     <param-value>mwsys-shop</param-value>

  </context-param>

  <listener>

  <listener-class>freemarker.ext.jsp.EventForwarding</listener-class>

  </listener>

  <listener>

     <listener-class>

        org.springframework.web.context.ContextLoaderListener

     </listener-class>

  </listener>

  <listener>

     <listener-class>

        org.springframework.web.util.Log4jConfigListener

     </listener-class>

  </listener>

 

  <servlet>

     <servlet-name>remoting</servlet-name>

     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

     <init-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/classes/config/spring/spring-mvc-main.xml</param-value>

     </init-param>

     <load-on-startup>1</load-on-startup>

  </servlet>

 

  <servlet-mapping>

     <servlet-name>remoting</servlet-name>

     <url-pattern>/*</url-pattern>

  </servlet-mapping>

</web-app>

 

2.      spring mvc配置spring-mvc-main.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

  xmlns:context="http://www.springframework.org/schema/context"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:mvc="http://www.springframework.org/schema/mvc"

  xsi:schemaLocation="

       http://www.springframework.org/schema/beans    

       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

       http://www.springframework.org/schema/context

       http://www.springframework.org/schema/context/spring-context-3.0.xsd

       http://www.springframework.org/schema/mvc 

     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

 

  <context:component-scan base-package="com.maowu.shop.view" />

  <mvc:annotation-driven />

 

  <!-- FreeMarker configuration -->

  <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

     <property name="templateLoaderPath" value="/WEB-INF/ftl/" />

     <property name="freemarkerVariables">

        <map>

           <entry key="xml_escape" value-ref="fmXmlEscape" />

           <entry key="BASEPATH" value="http://localhost:8080/shop/"></entry>

           <entry key="IMGBASEPATH" value="http://localhost:8080/shop/res/file/"></entry>

           <entry key="RESBASEPATH" value="../../"></entry>

        </map>

     </property>

  </bean>

  <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

     <property name="contentType" value="text/html;charset=UTF-8" />

     <property name="cache" value="true" />

     <property name="prefix" value="" />

     <property name="suffix" value=".ftl" />

  </bean>

  <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />

  

  <!-- exception handling configuration -->

  <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

     <!-- 定义默认的异常处理页面,当该异常类型的注册时使用 --> 

     <property name="defaultErrorView" value="error/error" />

     <!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception --> 

     <property name="exceptionAttribute" value="ex" />

     <!-- 全局异常记录到日志中,若warnLogCategory不为空,spring就会使用apache的org.apache.commons.logging.Log日志工具,记录这个异常级别是warn -->

     <property name="warnLogCategory" value="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" />

     <property name="exceptionMappings">

        <map>

           <entry key="RemoteAccessException" value="error/remote_error" />

        </map>

     </property>

  </bean>

 

  <!-- bind i18n messages properties,this just setting zh_CN message -->

  <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 

      <property name="useCodeAsDefaultMessage" value="false"/> 

      <property name="defaultEncoding" value="UTF-8"/> 

      <property name="fallbackToSystemLocale" value="true"/> 

      <property name="basenames"> 

          <list> 

              <value>classpath:bundle/messages</value>    

              <value>classpath:bundle/ValidationMessages</value>

          </list> 

      </property> 

  </bean>

  <!-- setting validation implementor,actually HibernateValidator is java validation interface default implementor-->

  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 

      <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/> 

      <property name="validationMessageSource" ref="messageSource"/> 

  </bean>

 

  

</beans>

 

3.      UserVo的源代码

import javax.validation.constraints.Max;

import javax.validation.constraints.Size;

 

publicclass UserVo

{

   @Size(min = 2, max = 6, message ="{size.u.name.len}")

   private Stringname;

 

   @Max(value = 1, message ="{Max.sex}")

   privateintsex;

 

   public String getName()

   {

       returnname;

   }

 

   publicvoid setName(String name)

   {

       this.name = name;

   }

 

   publicint getSex()

   {

       returnsex;

   }

 

   publicvoid setSex(int sex)

   {

       this.sex = sex;

推荐:整合Spring MVC,mybatis,hibernate,freemarker框架实现的自定义注解Validator验证机制实现对敏感词过滤的代码分享

整合Spring MVC,mybatis,hibernate,freemarker框架实现的自定义注解Validator验证机制实现对敏感词过滤的代码分享 博客分类: java spring hibernate 自定义注

   }

 

   @Override

   public String toString()

   {

       return String.format("UserVo [name=%s, sex=%s]",name,sex);

   }

}

 

4.      需要把spring.tld和spring-form.tld两个文件加入webapp的目录下

 

5.      ValidationMessages.properties国际化消息(校验的错误消息)

size.u.name.len=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A\u957F\u5EA6\u5728{min}\u548C{max}\u4E4B\u95F4

Max.sex=\u8D85\u8FC7\u6700\u5927\u503C{value}

 

6.      messages.properties国家化消息(非校验的错误消息)

u.reg.welcome=\u6B22\u8FCE\u6CE8\u518C

 

7.      成功后的user_reg_ok.ftl页面:

        数据没问题,注册成功!

 

以下是不同部分

 

第一种:使用spring.ftl结合Hibernate Validator

1)Controller的代码

@RequestMapping(value ="user/reg0", method = RequestMethod.GET)

   public String reg0(ModelMap model)

   {

       UserVo userVo = new UserVo();

       model.addAttribute("userVo", userVo);

       return"user/user_reg0";

   }

 

   @RequestMapping(value ="user/reg0", method = RequestMethod.POST)

   public String reg0(@Valid@ModelAttribute UserVo userVo, BindingResult result, ModelMap model)

   {

       System.out.println(userVo.toString());

       if (result.hasErrors())

       {

           return"user/user_reg0";

       }

       else

       {

           return"user/user_reg_ok";

       }

}

 

2)user_reg0.ftl代码

<#import"/spring.ftl" as spring />

<html>

<style> 

.error { 

   color: #ff0000; 

   font-weight: bold; 

</style>

  <body>

     <div><br/></div>

     <@spring.message code="u.reg.welcome" />

     <br/>

     <form method="POST" action="/shop/user/reg0" id="user_validator">

        <@spring.bind "userVo.name" />

        <input type="input" name="name" value=""/>

        <@spring.showErrors "<br/>"/>

        

        <@spring.bind "userVo.sex" />

        <input type="input" name="sex" value=""/>

        <input type="submit" value="提交"/>

        <@spring.showErrors "<br/>"/>

     </form>

  </body>

</html>

 

第二种:使用spring.tld和spring-form.tld结合Hibernate Validator

1) Controller代码

@RequestMapping(value ="user/reg1", method = RequestMethod.GET)

   public String reg1(ModelMap model)

   {

       return"user/user_reg1";

   }

 

   @RequestMapping(value ="user/reg1", method = RequestMethod.POST)

   public String reg1(@Valid@ModelAttribute UserVo userVo, BindingResult result, ModelMap model)

   {

       System.out.println(userVo.toString());

       if (result.hasErrors())

       {

           return"user/user_reg1";

       }

       else

       {

           return"user/user_reg_ok";

       }

   }

 

2) user_reg1.ftl代码文件

<#assign spring=JspTaglibs["/WEB-INF/spring.tld"]/>

<#assign form=JspTaglibs["/WEB-INF/spring-form.tld"]/>

<html>

<style> 

.error { 

   color: #ff0000; 

   font-weight: bold; 

</style>

  <body>

     <@spring.message code="u.reg.welcome" />

     <div><br/></div>

     <@form.form method="POST" action="/shop/user/reg1" commandName="userVo" id="user_validator">

        <input type="input" name="name" value=""/>

        <@form.errors path = "name" />

 

        <input type="input" name="sex" value=""/>

        <@form.errors path = "sex" />

        <input type="submit" value="提交"/>

     </@form.form>

  </body>

</html>

以上就是两种配置的实际可以运行的源码,调试时注意各文件的存放路径。

 

以下是对上面的两种的总结:

 

验证错误消息文件名字:是默认名ValidationMessages.properties,编译后存放在classes目录下则:消息key名可以自定义,消息内容可以包含参数(如上面代码中的“{min}”)

 

验证错误消息文件名字:是自定义名ErrorMessages.properties,编译后存放在classes目录下则:消息key名不可自定义,需用hibernate validation的消息key格式(下面会讲解),消息内容不可包含参数(如上面代码中的“{min}”)

 

验证错误消息文件名字:是默认名ValidationMessages.properties,编译后不放在classes目录下则:消息key名不可自定义,需用hibernate validation的消息key格式(下面会讲解),消息内容不可包含参数(如上面代码中的“{min}”)

 

如果消息内容中包含参数则会报:java.lang.IllegalArgumentException: can't parse argument number: xxx异常。(xxx是参数名)

 

 

以下是对hibernate validation默认的错误消息文件及默认错误消息键值说明:

默认的提供的错误消息文件名如下:

ValidationMessages.properties

ValidationMessages_de.properties

ValidationMessages_en.properties

ValidationMessages_es.properties

ValidationMessages_fr.properties

ValidationMessages_hu.properties

ValidationMessages_mn_MN.properties

ValidationMessages_pt_BR.properties

ValidationMessages_tr.properties

ValidationMessages_zh_CN.properties

 

 

默认的错误消息Key:验证约束注解的全限定类名.message,默认将为验证的对象自动生成如下错误消息键:

验证错误注解简单类名.验证对象名.字段名

验证错误注解简单类名.字段名

验证错误注解简单类名.字段类型全限定类名

验证错误注解简单类名

 

使用的优先级是:从高到低,即最前边的具有最高的优先级,而且以上所有默认的错误消息键优先级高于自定义的错误消息键。

 

总结:一般来说消息key是要自定义的,而且消息内容可以传参数,所以我们使用默认文件名且存放在classes目录下。





评论
3 楼 sqbzo 2015-03-08   能提供一下源码做测试吗 2 楼 沙漠绿树 2014-06-20   不是的,这个时候就可以使用校验组,每组对应一系列属性的校验。 1 楼 alexwuwzj 2014-06-11   如果同一个VO,出现两种不同的校验要求,比如新增时要求3个属性不能为空,而在更新时只需要2个属性不能为空,那这种方式的校验如何处理?是否需要再建一个VO?请指教 

推荐:Spring mvc+hibernate+freemarker(开源项目),Spring mvc+hibernate+freemarker(开源项目)

Spring mvc+hibernate+freemarker(开源项目) 分类:  java 2014-03-30 11:48  3531人阅读  评论(1)  收藏  举报  今天我为大家做了一个 spring3 MVC 的例子,希

 源自: spring mvc结合freemarker,使用hibernate validation框架做校验及国际化 搭建Spring,Spring MVC,Mybatis,freemarker等集成开发环境,为了增加数据校验和国际化花了好几天的时间(

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。