2014-06-14 25 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