根据角色控制表单输入的属性文件

问题描述:

我正在构建的应用程序的要求要求用户角色是动态的,它们将存储在数据库中,并且它们也将映射到功能(表单)的应用程序,也存储在数据库中。根据角色控制表单输入的属性文件

限制角色访问特定页面并不困难,但要求还规定表单输入必须基于角色进行自定义,这意味着输入可以是强制性的,也可以不是,可见或不可见,只读,只有或没有基于角色。

我的控制这些限制的方法是基于为每个角色创建一个属性文件,该文件将所有表单的所有输入存储为应用程序中的键,并将长字符串作为值来定义状态输入,如下所示的:

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

我认为你是正确的方式,我会继续使用你的方法,其中包括创建多个属性文件,每个用户一个,除了我们不会使用任何“巨​​量变量 管理的豆“

所以,第一个步骤是使用一个单一的资源束前缀(在<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