Как правильно использовать область сеанса
Используйте его только для данных области сеанса, и ничего больше.Например, вошедший в систему пользователь, его настройки, выбранный язык и т. Д.
См. Также:
И каждый раз, когда я захожу на страницу, список товаров будет создаваться из последних записей в базе данных.Как я могу справиться с этим?
Обычно вы используете запрос или просматриваете область действия для него.Загрузка списка должна происходить методом @PostConstruct
.Если страница не содержит <h:form>
, тогда область запроса в порядке.Бин в области видимости будет вести себя как запрос, если в любом случае нет <h:form>
.
Все ссылки / кнопки "Просмотр продукта" и "Редактирование продукта", которые просто извлекают информацию (то есть идемпотентно), должны быть просто GET <h:link>
/ <h:button>
, где вы передаете сущностьидентификатор в качестве параметра запроса по <f:param>
.
Все ссылки / кнопки "удалить товар" и "сохранить товар", которые будут манипулировать информацией (т.е. не идемпотентно) должны выполнять POST на <h:commandLink>
/ <h:commandButton>
(вы нене хочу, чтобы они были закладками / поисковыми ботами!).Это в свою очередь требует <h:form>
.Чтобы сохранить данные для проверок и запросов ajax (чтобы вам не нужно было перезагружать / предварительно инициализировать сущность при каждом запросе), боб предпочтительно должен иметь область видимости.
Обратите внимание, что в основном вы должны иметь отдельный компонент для каждого представления, а также заметьте, что эти компоненты не обязательно должны ссылаться друг на друга.
Итак, учитывая эту сущность "product":
@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);
}
}
}
Вы можетедаже использовать универсальный конвертер, это объясняется в Реализация конвертеров для сущностей с Java Generics .
См. также: