JSF - 一些初学者问题(来自PHP开发人员)

Ond*_*tes 5 php jsf ejb jpa java-ee

我正在研究Java Server Faces的学校项目,因为我是PHP的开发人员,所以我无法掌握JSF的整体概念.

在通常的PHP MVC框架中,请求的URL通过路由系统与调用的类方法(控制器生命周期)和呈现的模板绑定,因此我可以在将任何输出发送到浏览器之前触发一些逻辑,例如执行重定向.

如果我错了,请纠正我 - 我无法在JSF中识别出这种模式.URL被绑定到渲染模板(在我的源代码中是faces/index.xhtml - > index.xhtml),如果我想在支持bean中调用一些方法(JSF相当于控制器),我可以在模板中调用任何getter( #{bean.property}),但是例如我不知道在请求URL时如何执行重定向.单击<h:commandLink>或后,我能够在我的支持bean中执行一些自定义方法<h:commandButton>,但在查看生成的HTML(总是看起来像提交表单)之后,我认为这不是唯一的方法.

我还查看了faces-config.xml,它看起来像配置多步表单向导的好方法,但我不知道如何使用这种机制来定义整个Web的结构.它主要用于哪个?定义网址?

另外,我想了解一下依赖注入系统.当我用@EJB注释它时,我不知道是什么将我的外观注入到支持的bean类属性中.如果我使用PersistenceContext注释"em"属性,我不知道什么机制将EntityManager注入到我的外观中.如何在没有这个DI容器(Glassfish?)的单元测试中改变这些机制.

请问,任何人都可以为我澄清这些东西如何以友好的PHP方式工作?谢谢!:)

fdr*_*ger 20

两年以来,我一直计划写一篇关于"JSF for PHP程序员"主题的博客文章,并且从来没有去做过......但是随着时间的推移收集了一些想法:(据我所知,你知道大部分内容):

  1. PHP和JSF之间的切换很痛苦 - 两种方式.准备苦涩和沮丧 - 我是认真的.问题是你不需要问"如何使用JSF做X",但"在JSF中做X或者我应该做Y"是否有意义.

  2. 大多数PHP框架(Cake,CI,ZF)中使用的模式不是普通的MVC - 它是前端控制器(和朋友):您处理请求,路由它们,将它们分配给操作,操作读取请求参数,与之交谈模型,将数据传递给视图,视图被呈现为响应,并使用某种助手来呈现被重用的片段,响应被序列化,完成.典型的MVC PHP应用程序中的表单可能会导致与呈现它的行为不同的操作.控制器调用视图并有机会在呈现视图之前执行操作.路由很重要,因为操作与URL相关联.

    在JSF中没有这样的东西.路由和重定向(至少是在处理视图之前发生的那个)不是JSF的一部分,它们是JSF下面的一个抽象级别.您可以使用其他库或自定义代码添加路由和重定向,这很容易.faces-config.xml中的机制并不是真正的路由,是的,你是对的,只有类似向导的scenarius才是particall.您不使用它来构建Web应用程序(仅因为它仅适用于POST请求).

    JSF中的操作不是由集中式路由器/调度程序选择,而是由组件选择.在大多数情况下,您甚至不需要操作,因为视图和模型就足够了.您可能会想象JSF将页面的每个组件视为自己的一个小MVC堆栈.组件本身(例如文本输入,下拉列表)负责从请求中检索数据,转换和验证数据,呈现HTML,并将数据传递到控制器(和其他组件),方法是将它们放在控制器(和其他组件)的正确位置.模型.

    多亏了这一点,需要动作控制器的东西,比如Zend Framework,比如分页数据,搜索,编辑多页面形式和自定义视图逻辑等,通常不需要JSF中的视图和模型(可能是验证器或转换器).组件仅在将数据持久保存到数据库或数据处理变得更复杂时才调用操作.即使这样,在视图从请求中读取所有数据之后也会触发操作,因此调度操作与路由无关.每个commandlinkcommandbutton必须返回到呈现原始表单的精确页面,因为只有此页面上的组件能够理解请求并更新模型.因为路由与触发操作无关,所以它被排除在框架之外(你可以使用像PrettyFaces这样的库做漂亮的URL和漂亮的路由,但它不是JSF的一部分).

    JSF重定向作为操作的结果执行(基于操作返回的字符串),因此虽然可以在其之前执行重定向和某些逻辑,但必须在重定向之前处理模板.

    在PHP中,通常将从数据库中读取数据视为"在显示视图之前要执行的操作".在JSF中,它不是一个动作,而是初始化模型的一部分; 因此它属于模型托管bean内部的方法 - 这样的方法应该注释,@PostConstruct并且在获得对bean的引用之后并且在注入了所有依赖项之后,它将由JSF DI容器执行.

    如果你真的认为你需要在页面显示之前触发一些动作,请使用事件监听器 - 但要注意:可能你做错了.

    Cake/Zend框架背后隐藏的假设是"每个HTML页面都有一个主要的事情要做,显示主要关注这一点".JSF背后隐藏的假设是"据我们所知,整个应用程序只是这一页充满了有状态控件"

  3. 根据定义,注入由容器完成 - 因为您的托管bean不是由您生成的,而是由某些EL解析器提供给JSF组件.JSF包含一个简单的独立容器,在Java EE 5中,您还获得了一个EJB容器.Java EE 6通过引入CDI(上下文和依赖注入,JSR 299)并将EJB重新定义为一种特殊的CDI bean来开始统一DI.同样在Java EE 6中,您可以选择跳过JSF DI容器并使用CDI bean.Glassfish中使用的CDI实现是Weld.

    虽然可以使用嵌入式Glassfish来运行测试,但是依赖注入是单元测试友好的整个想法来自于在容器外测试类的能力(这就是为什么它们是UNIT测试,而不是INTEGRATION测试).应该手动模拟和插入依赖项.

  4. 如果你没有在JSF上投入太多时间,你可能首先尝试切换到JSR-311.它是Java EE的一个新的替代表示层,专注于休息方法:宁静的URL,路由,资源等.它具有可插入的模板,其RI具有漂亮的MVC层.如果你喜欢Zend Framework,你一定会喜欢它.您可以使用JSR-311来练习EJB,JPA和其他Java EE,然后在您已经熟悉依赖注入,事务管理等方面回到JSF,并且可以专注于有状态的Web表示.Jersey中的一个示例代码(jsr-311 RI,你将它与你的glassfish/netbeans捆绑在一起)可能如下所示:

    
    @EJB
    UsersDao usersDao;
    
    @Path("/users/detail/{userId}")
    public void userDetail(@PathParam("userId") int userId){
       return new Viewable("users/template.jsp", usersDao.getById(userId));
    }
    
    Run Code Online (Sandbox Code Playgroud)

    警告:jsr-311是以服务为中心的(json,xml)而不是以Web应用程序为中心的,并且模板引擎是可插入的,因此没有jsr-311视图助手(当重建URL时,你几乎可以自己动手).

  • 伙计......谢谢你!:) (2认同)