Если вы используете Java 8 с Java EE 7, то при попытке использовать некоторые из новых функций Java 8 могут возникать некоторые причуды. Одна из таких странностей заключается в том, что новый API Date-Time по умолчанию не работает со многими API Java EE 7, поскольку они созданы для работы с java.util.Date и / или более старыми API Date. Однако это не препятствие, так как есть много способов обойти такие проблемы. В этой статье я покажу, как можно настроить приложение JSF, чтобы разрешить использование API-интерфейсов даты и времени Java 8 вместе с JPA и преобразователями даты.
Прежде всего, если вы хотите сохранить даты, используя новый класс LocalDate (или другие, которые являются частью Java 8 Date-Time API), вам необходимо разработать конвертер, который будет автоматически конвертировать из java.time.LocalDate в java.util.Date и наоборот для работы с JPA 2.1. Это достаточно легко сделать, тем более что нет необходимости настраивать какой-либо XML для установки конвертера. Следующий код является конвертером, который используется для обеспечения поддержки даты и времени Java 8 для JPA:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import java.time.Instant;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;import java.time.Month;import java.time.ZoneId;import java.util.Date;import javax.persistence.AttributeConverter;import javax.persistence.Converter;/** * Converter to provide Java 8 Date/Time API Support to JPA * * @author Juneau */@Converter(autoApply = true)public class LocalDatePersistenceConverter implements AttributeConverter<LocalDate, Date> { @Override public Date convertToDatabaseColumn(LocalDate entityValue) { LocalTime time = LocalTime.now(); Instant instant = time.atDate(entityValue).atZone(ZoneId.systemDefault()).toInstant(); return Date.from(instant); } @Override public LocalDate convertToEntityAttribute(Date databaseValue) { Instant instant = Instant.ofEpochMilli(databaseValue.getTime()); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalDate(); }} |
Глядя на код, метод convertToDatabaseColumn() принимает
LocalDate из объекта, класса, а затем использует некоторые из утилит Java 8 Date-Time API для преобразования его в java.util.Date чтобы он мог быть сохранен в базе данных. Второй метод convertToEntityAttribute() берет java.util.Date из JPA и преобразует его в обратном направлении в объект LocalDate для использования с приложением на основе Java 8. Аннотация @Converter регистрирует класс как преобразователь, а реализация AttributeConverter применяет преобразователь к классу сущностей, чтобы преобразовать состояние в столбец базы данных и обратно.
Затем, если вы попытаетесь применить JSF-конвертер к Java 8 LocalDate в вашем приложении, скажем, в представлении, у вас возникнут проблемы, если вы не напишите специальную реализацию FacesConverter для применения к компоненту, который вы хотите преобразовать в LocalDate . Написание FacesConverter так же просто, как преобразователя атрибутов класса сущности, а регистрация так же проста, как применение аннотации к преобразователю. Следующий класс является примером FacesConverter , который преобразует java.time.LocalDate в java.util.Date для использования в компоненте JSF.
Примечание. Это также работает с популярными библиотеками компонентов JSF, такими как PrimeFaces.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import java.time.LocalDate;import java.time.format.DateTimeFormatter;import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import javax.faces.convert.FacesConverter;/** * Faces converter for support of LocalDate * @author Juneau */@FacesConverter(value="localDateTimeConverter")public class LocalDateTimeConverter implements javax.faces.convert.Converter { @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { return LocalDate.parse(value); } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { LocalDate dateValue = (LocalDate) value; return dateValue.format(DateTimeFormatter.ofPattern("MM/dd/yyyy")); } } |
Теперь давайте посмотрим на код немного. Этот класс FacesConverter зарегистрирован через аннотацию @FacesConverter , и класс может просто реализовать интерфейс javax.faces.convert.Converter . Далее взгляните на реализацию. Метод getAsObject() используется для анализа строки в компоненте и ее возврата в виде java.time.LocalDate , тогда как метод getAsString() принимает объект LocalDate и возвращает его в виде строки в указанном формате даты. Это демонстрирует еще одну приятную особенность Java 8 …
Класс DateTimeFormatter, который облегчает форматирование объекта java.time.* .
Вот и все … не так уж сложно использовать красивый API Date-Time Java 8 в приложении Java EE 7. Теперь давайте применим конвертер к компоненту даты. Следующая разметка демонстрирует, как применить конвертер к календарному компоненту PrimeFaces.
|
1
2
3
4
5
|
<p:calendar id="enterDate" converter="localDateTimeConverter" style="width: 100%;" readonly="true" value="#{myExcellentJsfController.current.enterDate}"> </p:calendar> |
| Ссылка: | Использование Java 8 Date-Time API с JSF и Java EE 7 от нашего партнера по JCG Джоша Джуно из блога Josh’s Dev Blog — Java, Java EE, Jython, Oracle и другие… блог. |