2014-06-14 28 views
2

我有一个应用程序在前端图层中使用JSF 2.2(使用primefaces),在业务层使用Spring 4。jsf 2.2 + Spring 4使用JSF语言环境的Spring验证器的JSR-349

我正在使用Tomcat 7.

我没有使用Spring MVC。表示层是纯JSF,我使用@ManagedProperty(#{someSpringBean})访问Spring beans

我正在使用JSR-349进行客户端和服务器端验证。 我有我的ValidationMessages.properties在类路径。

在客户端验证没有问题,因为Primefaces管理着所有东西。我需要Spring使用JSF当前语言环境(FacesContext.getCurrentInstance()。getViewRoot()。getLocale()))插入验证消息。

值得一提的是,我的应用程序的用户可以通过菜单选项更改区域设置。

那么,在服务器端验证中插入消息时,如何让Spring使用JSF语言环境?

我给你一些代码,这样你就可以更好地理解我的需求:

JSF豆

@ManagedBean 
@ViewScoped 
public class RegisterBean { 

    @ManagedProperty(value = "#{partnerServiceFacade}") 
    private PartnerServiceFacade partnerServiceFacade; 

    // properties...  

    public String registerPartner() { 
     ... 
     partner = partnerServiceFacade.registerPartner(partner); 
    }  
} 

门面接口:

@Validated  
public interface PartnerServiceFacade { 

    @PreAuthorize("hasRole('ROLE_USER')") 
    public Partner registerPartner(@Valid Partner toRegister); 

    //Other methods 
} 

JPA实体:

@Entity 
@Table(name = DBConstants.TABLE_PARTNER) 
@Inheritance(strategy = InheritanceType.JOINED) 
public class Partner extends XWeedDBEntity { 

    private static final long serialVersionUID = 5692151244956513381L; 

    @Id 
    @Column(name = DBConstants.PARTNER_COL_PARTNER_NUMBER) 
    private Integer partnerNumber; 

    @NotEmpty 
    @Column(name = DBConstants.PARTNER_COL_NAME, nullable = false) 
    private String name; 

    @NotEmpty 
    @Column(name = DBConstants.PARTNER_COL_SURNAME, nullable = false) 
    private String surname; 

    @NotEmpty 
    @Column(name = DBConstants.PARTNER_COL_LASTNAME) 
    private String lastname; 
} 

Spring conf配置:

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> 
    <property name="defaultEncoding" value="UTF-8"/> 
    <property name="basename" value="ValidationMessages" /> 
</bean> 

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
    <property name="validationMessageSource" ref="messageSource" /> 
</bean> 

在此先感谢!


我找到了解决方案。那就是:

春天验证配置:

<!-- SPRING MESSAGE LOCATOR --> 

<bean id="messageLocator" class="org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator"> 
    <constructor-arg index="0" ref="messageSource" /> 
</bean> 

<!-- SPRING LOCALE MESSAGE INTERPOLATOR --> 

<bean id="messageInterpolator" class="org.springframework.validation.beanvalidation.LocaleContextMessageInterpolator"> 
    <constructor-arg index="0"> 
     <bean id="hibernateMessageInterpolator" class="org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator"> 
      <constructor-arg name="userResourceBundleLocator" ref="messageLocator" /> 
      <constructor-arg name="cacheMessages" value="true"/> 
     </bean> 
    </constructor-arg> 
</bean> 

<!-- SPRING VALIDATOR --> 

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
    <property name="messageInterpolator" ref="messageInterpolator" /> 
</bean> 

<!-- SPRING ANNOTATION VALIDATION CONFIGURATION --> 

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"> 
    <property name="validator" ref="validator"/> 
</bean> 

阶段监听器来管理区域设置:

public class LocalePhaseListener implements PhaseListener { 

// Constants -------------------------------------------------------------------------------------------------------------- 

private static final long serialVersionUID = 3678092859009088388L; 

// Overridden methods ----------------------------------------------------------------------------------------------------- 

@Override 
public void afterPhase(PhaseEvent event) { 
} 

@Override 
public void beforePhase(PhaseEvent event) { 
    HttpSession session = (HttpSession) event.getFacesContext().getExternalContext().getSession(false); 
    Locale locale = ((UserBean) session.getAttribute("userBean")).getLocale(); 
    LocaleContextHolder.resetLocaleContext(); 
    LocaleContextHolder.setLocale(locale); 
} 

@Override 
public PhaseId getPhaseId() { 
    return PhaseId.INVOKE_APPLICATION; 
} 

}

使用LocaleContextMessageInterpolator你强制Spring使用在LocaleContextHolder的语言环境,并在PhaseListener中,您可以使用JSF语言环境填充LocaleContextHolder语言环境。

+1

Spring使用'LocalContextHolder'来检索上下文。创建集成代码,将JSF语言环境设置到'LocaleContextHolder'中,并在请求完成时将其清除。注册一个RequestContextListener来正确注册区域设置可能就足够了。 –

+0

@ M.Deinum我试图通过LocaleContextHolder更改Spring语言环境,但它不起作用,并且验证消息仍以默认语言环境显示。不过谢谢。 – xmartinez

+0

确保您在正确的时刻更改它,并且在渲染过程中保持原样。 –

回答

1

前提是你必须通过某种ThreadLocal(不知道LocalContextHolder是否起作用,因为我不是那么熟悉Spring API)访问Locale,你可以仅仅指刚提供自定义MessageInterpolator,并通过validation.xml配置。另请参阅http://docs.jboss.org/hibernate/validator/5.1/reference/en-US/html_single/#section-validator-factory-message-interpolator

在实现中,您需要检索当前用户的Locale,然后调用适当的插值方法。

+0

感谢m8,我会在本周尝试,我会给你反馈,希望我得到的问题修复:) – xmartinez

+1

解决了,我编辑了问题,并添加了我的解决方案。感谢你们的帮助,你们给了我一些小技巧,以便最终解决问题:) – xmartinez