溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

從Richfaces 4.5遷移到Primefaces 6.2

發(fā)布時(shí)間:2020-04-03 07:28:34 來源:網(wǎng)絡(luò) 閱讀:6612 作者:川川Jason 欄目:開發(fā)技術(shù)

自2016年6月Richfaces已停止更新,最近將一項(xiàng)目遷移到了Primefaces。Primefaces提供了更豐富的組件,使用更簡單,界面更美觀,性能更高。JSF應(yīng)用現(xiàn)在越來越少,僅供有需要者參考。

Richfaces版本: 4.5.14.Final
Primefaces版本: 6.2

第一步 刪除Richfaces配置,引入Primefaces

如果您使用了maven,請從pom中刪除richfaces配置,然后加入primefaces:

<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>6.2</version>
</dependency>

然后將web.xml中的richfaces配置刪除。

批量更新

  • xmlns:rich="http://richfaces.org/rich"
    xmlns:a4j="http://richfaces.org/a4j"

    替換為:

    xmlns:p="http://primefaces.org/ui"

    注意xmlns:p="http://primefaces.org/ui" 不能重復(fù)。

  • 將 rich: 和 a4j: 替換為 p:。
  • 將屬性render替換為update,execute替換為process。
  • 刪除屬性limitRender、bypassUpdates。

同名組件

Richfaces Primefaces
<a4j:ajax> <p:ajax>
<a4j:commandButton> <p:commandButton>
<a4j:commandLink> <p:commandLink>
<a4j:log> <p:log>
<a4j:outputPanel> <p:outputPanel>
<a4j:poll> <p:poll>
<a4j:repeat> <p:repeat>
<rich:calendar> <p:calendar>
<rich:contextMenu> <p:contextMenu>
<rich:dataGrid> <p:dataGrid>
<rich:dataTable> <rich:dataScroller> <p:dataTable>
<rich:extendedDataTable> <rich:collapsibleSubTable> <p:dataTable>
<rich:editor> <p:editor>
<rich:fileUpload> <p:fileUpload>
<rich:message> <p:message>
<rich:messages> <p:messages>
<rich:panel> <p:panel>
<rich:panelMenu> <p:panelMenu>
<rich:pickList> <p:pickList>
<rich:progressBar> <p:progressBar>
<rich:toolbar> <p:toolbar>
<rich:tooltip> <p:tooltip>
<rich:tree> <p:tree>

異名組件

Richfaces Primefaces
<a4j:jsFunction> <p:remoteCommand>
<a4j:mediaOutput> <p:media>
<a4j:region> <p:fragment>
<a4j:status> <p:ajaxStatus>
<rich:validator> <p:clientValidator>
<rich:accordion> <rich:collapsiblePanel> <p:accordionPanel>
<rich:autocomplete> <p:autoComplete>
<rich:chart> Primefaces提供了十多種chart組件,自行選擇
<rich:dragSource> <p:draggable>
<rich:dropTarget> <p:droppable>
<rich:dropDownMenu> <p:menubar>
<rich:list> <p:dataList>
<rich:inplaceInput> <rich:inplaceSelect> <p:inplace>
<rich:inputNumberSlider> <p:slider>
<rich:inputNumberSpinner> <p:spinner>
<rich:notify> <p:notificationBar>
<rich:notifyMessage> <rich:notifyMessages> <p:growl>
<rich:orderingList> <p:orderList>
<rich:popupPanel> <p:dialog>
<rich:select> <p:selectOneMenu>
<rich:tabPanel> <rich:togglePanel> <p:tabView>

不存在的組件

<a4j:param>
<a4j:actionListener>
<a4j:push>
<a4j:queue>

說明:<rich:dataScroller>與<p:dataScroller>,雖然名稱相同,但功能不同,一個(gè)是分頁,一個(gè)是按需顯示數(shù)據(jù)。

子組件、屬性、事件

名稱或功能相同的組件,子組件名稱,支持的屬性、事件可能不同,使用時(shí)需要仔細(xì)核對,如:

  • <rich:panelMenu> -> <p:panelMenu>
    <p:panelMenu> 僅支持幾個(gè)常用屬性
    <rich:panelMenuGroup> -> <p:submenu>
    <rich:panelMenuItem> -> <p:menuitem>
    label -> value
  • <rich:collapsiblePanel> -> <p:accordionPanel>
    要?jiǎng)h除原定義的屬性,增加子組件<p:tab>

Function

  • #{rich:component('id')} -> PF('widgetVar')
    <a4j:commandButton value="Cancel" oncomplete="#{rich:component('popupPanel')}.hide();"/>
    <rich:popupPanel id="popupPanel">...</rich:popupPanel>
    <a4j:commandButton value="Cancel" oncomplete="PF('dialog').hide()"/>
    <p:dialog id="dialog" widgetVar="dialog">...</p:dialog>
  • #{rich:clientId('id')} -> #{p:component('id')}
  • jQuery
    在Primefaces中可以直接使用jQuery,如:
    <p:commandButton onclick="alert($('#form\\:panel\\:airport').val());return false;" value="test"/>

    上面使用了轉(zhuǎn)義字符,也可以使用PrimeFaces函數(shù),注意不要加"#",如下:

    <p:commandButton onclick="alert($(PrimeFaces.escapeClientId('form:panel:airport')).val());return false;" value="test"/>

Primefaces特有組件

Primefaces提供了很多新穎美觀的組件,也可以替代Richfaces組件,大家可查看Primefaces showcase。
有一些比較常用的功能Richfaces沒有提供,原來只能自己實(shí)現(xiàn),現(xiàn)在不需要了,比如:

  • <p:outputLabel>
    自動為required增加*,為校驗(yàn)信息增加label
    <p:outputLabel for="extended" value="Extended Label:" />
    <p:inputText id="extended" required="true" />
  • <p:panelGrid>
    支持復(fù)雜表格,使用Richfaces時(shí)只能借助<rich:dataTable>較繁瑣。
  • <p:confirmDialog>
    confirmDialog示例:
    <p:commandButton value="Destroy the World" actionListener="#{dialogView.destroyWorld}" update="message">
    <p:confirm header="Confirmation" message="Are you sure?" icon="ui-icon-alert" />
    </p:commandButton>
    <p:confirmDialog global="true" showEffect="fade" hideEffect="fade">
    <p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
    <p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
    </p:confirmDialog>

驗(yàn)證

<h:inputText value="" required="true" id="test">
    <p:ajax event="blur" update="msgTest"/>
</h:inputText>
<p:message for="test" id="msgTest" display="icon"/>

<rich:message>不支持tooltip形式顯示message,<p:message>支持。

dataTable與LazyDataModel

<p:dataTable>實(shí)現(xiàn)了<rich:dataTable>、<rich:extendedDataTable>、<rich:dataScroller>的所有功能,定義更簡單,且復(fù)雜表頭時(shí)仍支持排序,支持單選、復(fù)選框選擇,提供emptyMessage屬性,不必再使用noData facet。
LazyDataModel比ExtendedDataModel實(shí)現(xiàn)更簡單,性能更高。
下面LazyDataModel和自定義dataTable示例(org.jason是自定義的一些實(shí)現(xiàn)):
PagingDataModel

import org.jason.base.dao.Filter;
import org.jason.base.dao.IQuery;
import org.jason.base.dao.Order;
import org.jason.base.dao.Pagination;
import org.jason.base.service.PagingService;
import org.jason.entity.BaseEntity;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.primefaces.model.SortOrder.ASCENDING;
//
public class PagingDataModel<T extends BaseEntity> extends LazyDataModel<T> {
    private PagingService service;
    private IQuery query;   
    private List<T> data;
    private List<T> selectedItems = new ArrayList<>();
    private T selectedItem;

    @SuppressWarnings("rawtypes")
    public PagingDataModel(PagingService service, IQuery query) {
        this.service = service;
        this.query = query;
    }

    @Override
    public T getRowData(String rowKey) {
        for (T entity : data) {
            if (entity.getId() == Integer.parseInt(rowKey)) {
                return entity;
            }
        }
        return null;
    }

    @Override
    public Object getRowKey(T object) {
        return object.getId();
    }

    @Override
    public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
        data = service.find(query, new Pagination(first, pageSize, createFilter(filters), createOrders(sortField, sortOrder)));
        setRowCount(service.count(query, createFilter(filters)));

        return data;
    }

    public void refresh() {
        setSelectedItem(null);
        setSelectedItems(null);
        load(0, getPageSize(), null, null, null);
    }

    private List<Filter> createFilter(Map<String, Object> filters) {
        if (filters == null) {
            return Collections.emptyList();
        }

        return filters.entrySet().stream().map(filter -> new Filter(filter.getKey(), filter.getValue())).collect(Collectors.toList());
    }

    private List<Order> createOrders(String sortField, SortOrder sortOrder) {
        if (sortField == null || sortOrder == null) {
            return Collections.emptyList();
        }

        List<Order> orders = new ArrayList<>();
        orders.add(new Order(sortField, sortOrder == ASCENDING));

        return orders;
    }

    public List<T> getSelectedItems() {
        return selectedItems;
    }

    public void setSelectedItems(List<T> selectedItems) {
        this.selectedItems = selectedItems;
    }

    public T getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(T selectedItem) {
        this.selectedItem = selectedItem;
    }
}

自定義dataTable

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:composite="http://java.sun.com/jsf/composite"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
<composite:interface>
    <composite:attribute name="emptyMessage" default="#{messages['general.noData']}"/>
    <composite:attribute name="paginator" default="true"/>
    <composite:attribute name="paginatorPosition" default="bottom"/>
    <composite:attribute name="rows" default="10"/>
    <composite:attribute name="rowsPerPageTemplate" default="5,10,15"/>
    <composite:attribute name="rowStyleClass" default="even,odd"/>
    <composite:attribute name="selection"/>
    <composite:attribute name="selectionMode"/>
    <composite:attribute name="style"/>
    <composite:attribute name="styleClass" default="list-table"/>
    <composite:attribute name="value" type="org.iata.ios.web.pagination.PagingDataModel" required="true"/>
    <composite:attribute name="onRowClick"/>
    <composite:facet name="header"/>
    <composite:facet name="footer"/>
</composite:interface>
<composite:implementation>
    <p:outputPanel layout="block" styleClass="list-panel">
        <c:choose>
            <c:when test="#{not empty cc.attrs.selectionMode}">
                <p:dataTable id="dt" value="#{cc.attrs.value}" var="item" lazy="true" rows="#{cc.attrs.paginator ? cc.attrs.rows : 0}" paginator="#{cc.attrs.paginator}"
                             paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                             rowsPerPageTemplate="#{cc.attrs.rowsPerPageTemplate}" paginatorPosition="#{cc.attrs.paginatorPosition}"
                             selection="#{cc.attrs.selection}" emptyMessage="#{cc.attrs.emptyMessage}"
                              styleClass="#{cc.attrs.styleClass}" rowStyleClass="#{cc.attrs.rowClasses}" onRowClick="#{cc.attrs.onRowClick}">
                    <composite:insertFacet name="header"/>
                    <p:column rendered="#{cc.attrs.selectionMode == 'single'}" selectionMode="single" />
                    <p:column rendered="#{cc.attrs.selectionMode == 'multiple'}" selectionMode="multiple" />
                    <composite:insertChildren/>
                    <composite:insertFacet name="footer"/>
                </p:dataTable>
            </c:when>
            <c:otherwise>
                <p:dataTable id="dt" value="#{cc.attrs.value}" var="item" lazy="true" rows="#{cc.attrs.paginator ? cc.attrs.rows : 0}" paginator="#{cc.attrs.paginator}"
                             paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                             rowsPerPageTemplate="#{cc.attrs.rowsPerPageTemplate}" paginatorPosition="#{cc.attrs.paginatorPosition}" emptyMessage="#{cc.attrs.emptyMessage}"
                              styleClass="#{cc.attrs.styleClass}" rowStyleClass="#{cc.attrs.rowClasses}" onRowClick="#{cc.attrs.onRowClick}">
                    <composite:insertFacet name="header"/>
                    <composite:insertChildren/>
                    <composite:insertFacet name="footer"/>
                </p:dataTable>
            </c:otherwise>
        </c:choose>
    </p:outputPanel>
    <ui:include src="css.xhtml"/>
</composite:implementation>
</html>

參考文檔

PrimeFaces Showcase
PrimeFaces Documentation
Migrating From RichFaces 4 to PrimeFaces 3
Patching RichFaces 3.3.3 AJAX.js for IE11

附錄 Seam升級到CDI

替換Annotation

  • @Name -> @Named
    import org.jboss.seam.annotations.Name; -> import javax.inject.Named;
  • @In -> @Inject
    import org.jboss.seam.annotations.In; -> import javax.inject.Inject;
  • 刪除@Out
    import org.jboss.seam.annotations.Out;
    改為@Inject相應(yīng)Scope的組件
  • @Scope(ScopeType.APPLICATION) -> @ApplicationScoped
    @Scope(ScopeType.SESSION) -> @SessionScoped
    @Scope(ScopeType.CONVERSATION) -> @ConversationScoped
    @Scope(ScopeType.EVENT) -> @RequestScoped(或刪除)
  • @Create -> @PostConstruct
    import org.jboss.seam.annotations.Create; -> import javax.annotation.PostConstruct;
    @Destroy -> @PreDestroy
    import org.jboss.seam.annotations.Destroy; -> import javax.annotation.PreDestroy;
  • @Observer("org.jboss.seam.postInitialization")
    可以使用DeltaSpike Servlet module,替換如下:
    public void init(@Observes @Initialized ServletContext context) {
    ...
    }

    引入DeltaSpike Servlet module:

    <dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-servlet-module-api</artifactId>
    <version>1.8.1</version>
    </dependency>
    <dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-servlet-module-impl</artifactId>
    <version>1.8.1</version>
    </dependency>

    在web.xml中增加:

    <listener>
    <display-name>EventBridgeContextListener</display-name>
    <listener-class>org.apache.deltaspike.servlet.impl.event.EventBridgeContextListener</listener-class>
    </listener>
  • @Startup可使用ejb Singleton替換:
    @Singleton
    @Startup
  • @RequestParameter和頁面參數(shù)
    可以替換為這樣的組合:
    <p:button value="Edit" outcome="edit">
    <f:param name="id" value="#{...}"/>
    </p:button>
    <f:metadata>
    <f:viewParam name="id" value="#{...}"/>
    </f:metadata>
  • @Logger 建議替換為slf4j
    @Logger
    private Log log;

    替換為:
    private Logger log = LoggerFactory.getLogger(Test.class);
    日志中的{0} {1} 均替換為{}。

  • FacesMessages和StatusMessages改為使用javax.faces.application.FacesMessage

更新配置

  • 刪除components.xml
  • seam.properties替換為beans.xml,內(nèi)容如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    </beans>
  • 刪除page.xml
    navigation調(diào)整到JSF 2 faces-config.xml中(navigation-rule)。
    action可以調(diào)整到頁面中:
    <f:metadata>
    <f:event type="preRenderView" listener="#{...}"/>
    </f:metadata>

    頁面參數(shù)上面已提到過。

頁面

xmlns:s="http://jboss.com/products/seam/taglib", 可以使用JSF 2或Primefaces標(biāo)簽替換

Seam JSF 2/Primefaces
<s:div> <p:outputPanel>
<s:span> <p:outputPanel layout="inline">
<s:enumItem> <f:selectItem> label -> itemLabel enumValue -> itemValue
<s:convertDateTime> <f:convertDateTime>
<s:fragment> <ui:fragment>
<s:conversationId> <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/>

參考文檔

seam migration
Migration from Seam 2 to Java EE and Alternatives

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI