2015-02-07 69 views
1

我正在構建的應用程序的要求要求用戶角色是動態的,它們將存儲在數據庫中,並且它們也將映射到功能(表單)的應用程序,也存儲在數據庫中。根據角色控制表單輸入的屬性文件

限制角色訪問特定頁面並不困難,但要求還規定表單輸入必須基於角色進行自定義,這意味着輸入可以是強制性的,也可以不是,可見或不可見,只讀,只有或沒有基於角色。

我的控制這些限制的方法是基於爲每個角色創建一個屬性文件,該文件將所有表單的所有輸入存儲爲應用程序中的鍵,並將長字符串作爲值來定義狀態輸入,如下所示的:

user-inputs.properties

# form.input=mandatory:visibility 

searchBooks.bookName=true:true 
searchBooks.bookCategory=false:true 
searchBooks.authorName=false:false 

admin-inputs.properties

searchBooks.bookName=true:true 
searchBooks.bookCategory=false:true 
searchBooks.authorName=false:true 

然後做一些神奇的Java代碼,無論何時訪問表單,從特定用戶角色的文件中讀取其輸入屬性,並解析這些值,以便我可以爲rendered=""required=""屬性提供正確的值<h:inputText/>

這可能是一個解決方案,但應用程序的輸入不僅僅是書名和類別,這意味着我將放置大量必需的和呈現的屬性,這會使JSF頁面看起來醜陋,並帶有大量變量託管的bean。

對我的問題有更好的方法/框架/解決方案嗎?

+0

你是什麼意思形式比一本書更?也許你可以在Bean或其他地方做這種驗證? – antogerva 2015-02-08 00:11:08

+0

@antogerva對不起,我的意思是「但應用程序的輸入,,,,」意味着任何形式,有很多輸入。 – 2015-02-08 05:56:37

+0

@AliBassam我添加了關於捆綁注入的NB,請看看,因爲我認爲您需要注意它。 – Tarik 2015-02-08 15:58:04

回答

1

我認爲你是正確的方式,我會繼續使用你的方法,其中包括創建多個屬性文件,每個用戶一個,除了我們不會使用任何「巨​​量變量 管理的豆「

所以,第一個步驟是使用一個單一的資源束前綴(在<var></var><resource-bundle>)管理多個資源屬性,在第二個步驟中,我們將看到如何將這些文件之間切換,並在最後一步,我們會讀到從屬性文件使用JSTL。

管理多個屬性文件:

首先,我們在faces-config文件中定義我們的資源包:

<application> 
     <resource-bundle> 
     <base-name>UserMessages</base-name> 
     <var>msgs</var> 
     </resource-bundle> 
</application> 

UserMessagesResourceBundle,我們將實施,使我們對我們的財產文件之間切換的邏輯(假設yourpackage.user-inputs是用戶輸入的完全限定名稱。屬性):

import java.util.Enumeration; 
import java.util.MissingResourceException; 
import java.util.ResourceBundle; 

import javax.faces.context.FacesContext; 

public class UserMessages extends ResourceBundle { 

    public UserMessages() { 
     // we are loading user-inputs.properties as the default properties file 
     setParent(getBundle("yourpackage.user-inputs", FacesContext.getCurrentInstance() 
       .getViewRoot().getLocale())); 
    } 

    @Override 
    protected Object handleGetObject(String key) { 
     // we could just return parent.getObject(key) but we want to respect JSF recommandations 
     try { 
      return parent.getObject(key); 
     } catch (MissingResourceException e) { 
      return "???" + key + "???"; 
     } 
    } 

    @Override 
    public Enumeration<String> getKeys() { 

     return parent.getKeys(); 
    } 

    // this is the method that will allow us to switch between our .properties 
    public void setResourceBundle(String basename) { 
     setParent(getBundle(basename, FacesContext.getCurrentInstance() 
       .getViewRoot().getLocale())); 
    } 
} 

屬性文件之間切換:

爲了從屬性文件切換到另一個,我們將需要使用,我們只是在我們的類中聲明上述方法setResourceBundle(String basename),所以在管理豆你在哪裏聲明你的業務邏輯和你在哪裏打算切換,這取決於用戶的角色文件,你需要注入的捆綁,如:

//don't forget adding getters and setters or you end with NullPointerException 
@ManagedProperty("#{msgs}") 
private UserMessages userMesssages; 

然後切換到另一個文件(admin-inputs.properties),只是使用這樣的:

//yourpackage.admin-inputs is the fully qualified name 
userMesssages.setResourceBundle("yourpackage.admin-inputs"); 

NB:你可以注入以這種方式(以上)的包只有在請求範圍豆,在更廣泛的範圍來使用它,請參閱:Read i18n variables from properties file in a Bean

現在,我們可以輕鬆地從user-inputs切換到admin-inputs,最後一步是最簡單的一步。

解析屬性文件:

壞消息是,使用這種方法的時候,你需要rendered=""required=""屬性添加到每個輸入您願意管理(但不要忘記,好的是你不需要管理託管bean中的變量;))。

首先,您需要在您的XHTML文件的頂部添加JSTL的命名空間聲明:

xmlns:fn="http://java.sun.com/jsp/jstl/functions" 

你可以找到更多關於JSTL功能在javadocs,對於功能substringAfter

返回特定子字符串後面的字符串子集。

實施例:

P.O. Box: ${fn:substringAfter(zip, "-")} 

功能substringBefore

返回特定子串之前的字符串的一個子集。

實施例:

Zip (without P.O. Box): ${fn:substringBefore(zip, "-")} 

其次,作爲String的第一部分表示required屬性:

//Returns the substring of msgs['searchBooks.authorName'] before the first occurrence of the separator ':'  
required="${fn:substringBefore(msgs['searchBooks.authorName'], ':')}" 

和第二部分:

//Returns the substring of msgs['searchBooks.authorName'] after the first occurrence of the separator ':'. 
rendered="${fn:substringAfter(msgs['searchBooks.authorName'], ':')}" 

參見:

+0

完美!正是我需要的,謝謝你的辛勤工作。 – 2015-02-08 06:19:47

+0

歡迎您:) – Tarik 2015-02-08 13:59:07