为实体创build主 – 细节页面,如何链接它们以及select哪个bean范围

我已经开始学习JSF,但不幸的是,大多数教程只提供login或注册部分。

你能指出我更深入的例子吗? 我感兴趣的一件事是提供一个产品列表的页面。 我在页面上,并按页面产品,以便我可以看到添加的最新产品 。 每次访问该页面时,都会根据数据库中的最新条目创build产品列表。 我该如何处理?

解决这个问题的一个方法是创build一个会话范围的托pipebean,其中我将通过其他托pipe的bean更新不同的实体。 我在一些教程中发现了这种方法,但是看起来相当困难和笨拙。

哪一种解决这样的事情最好? 双页主/从用户界面中会话范围的正确用法是什么?

会话范围的正确用法是什么?

仅用于会话作用域的数据,没有别的。 例如,login用户,其设置,所选语言等等。

也可以看看:

  • 如何select合适的bean范围?

每次访问该页面时,都会根据数据库中的最新条目创build产品列表。 我该如何处理?

通常,您使用请求或查看范围。 加载列表应该发生在@PostConstruct方法中。 如果页面不包含任何<h:form> ,那么请求范围就可以了。 无论如何,视图范围的bean的行为就像一个请求范围。

所有只是检索信息的 “查看产品”和“编辑产品”链接/button(即幂等)应该只是简单的GET <h:link> / <h:button>其中您将实体标识符作为请求parameter passing给<f:param>

所有“删除产品”和“保存产品”的链接/button将操纵信息 (即非幂等)应通过<h:commandLink> / <h:commandButton>执行POST(您不希望它们是可collections的/ searchbot -indexable!)。 这反过来需要一个<h:form> 。 为了保存validation和ajax请求的数据(所以你不需要在每个请求上重新加载/初始化实体),这个bean最好是视图范围。

请注意,基本上每个视图都应该有一个单独的bean,并且注意这些bean不一定需要相互引用。

所以,鉴于这个“产品”实体:

 @Entity public class Product { @Id private Long id; private String name; private String description; // ... } 

而这个“产品服务”EJB:

 @Stateless public class ProductService { @PersistenceContext private EntityManager em; public Product find(Long id) { return em.find(Product.class, id); } public List<Product> list() { return em.createQuery("SELECT p FROM Product p", Product.class).getResultList(); } public void create(Product product) { em.persist(product); } public void update(Product product) { em.merge(product); } public void delete(Product product) { em.remove(em.contains(product) ? product : em.merge(product)); } // ... } 

您可以在/products.xhtml上查看“查看产品”:

 <h:dataTable value="#{viewProducts.products}" var="product"> <h:column>#{product.id}</h:column> <h:column>#{product.name}</h:column> <h:column>#{product.description}</h:column> <h:column> <h:link value="Edit" outcome="/products/edit"> <f:param name="id" value="#{product.id}" /> </h:link> </h:column> </h:dataTable> 
 @Named @RequestScoped public class ViewProducts { private List<Product> products; // +getter @EJB private ProductService productService; @PostConstruct public void init() { products = productService.list(); } // ... } 

你可以在/products/edit.xhtml上有这个“编辑产品”:

 <f:metadata> <f:viewParam name="id" value="#{editProduct.product}" converter="#{productConverter}" converterMessage="Unknown product, please use a link from within the system." required="true" requiredMessage="Bad request, please use a link from within the system." /> </f:metadata> <h:messages /> <h:form rendered="#{not empty editProduct.product}> <h:inputText value="#{editProduct.product.name}" /> <h:inputTextarea value="#{editProduct.product.description}" /> ... <h:commandButton value="save" action="#{editProduct.save}" /> </h:form> 
 @Named @ViewScoped public class EditProduct { private Product product; // +getter +setter @EJB private ProductService productService; public String save() { productService.save(product); return "/products?faces-redirect=true"; } // ... } 

而这个转换器为“编辑产品”的<f:viewParam>

 @Named @RequestScoped public class ProductConverter implements Converter { @EJB private ProductService productService; @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value == null || value.isEmpty()) { return null; } try { Long id = Long.valueOf(value); return productService.find(id); } catch (NumberFormatException e) { throw new ConverterException("The value is not a valid Product ID: " + value, e); } } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { if (value == null) { return ""; } if (value instanceof Product) { Long id = ((Product) value).getId(); return (id != null) ? String.valueOf(id) : null; } else { throw new ConverterException("The value is not a valid Product instance: " + value); } } } 

也可以看看:

  • 如何在JSF中导航? 如何使URL反映当前页面(而不是以前的页面)
  • JSF控制器,服务和DAO
  • JSF服务层
  • 如何在@FacesConverter中注入@EJB,@PersistenceContext,@Inject,@Autowired等?
  • JSF 2.0中的通信 – 包含几个示例/提示

作为BalusC推荐的一个小改进,有时候你可以从你的“详细信息”屏幕的f:viewParam中删除required / requiredMessage部分,而是使用带有相反条件的编辑forms(如BalusC做的) “list / master”屏幕的特定链接,甚至使用viewAction来testingparam并强制redirect到该列表。