Ниже представлен полный код класса Exceptional
. Он имеет довольно большой API, который является чистым расширением API Optional
, поэтому он может быть заменой для него в любом существующем коде, кроме того, что он не является подтипом конечного класса Optional
. Класс можно рассматривать как находящийся в том же соотношении с монадой Try
, поскольку Optional
находится с монадой Maybe
: он черпает вдохновение от него, но адаптирован к идиоме Java ( такие как фактические выбросы исключений даже из нетерминальных операций).
Это некоторые ключевые рекомендации, за которыми следует класс:
Класс пытается охватить все типичные способы обработки исключения:
recover
с некоторым кодом обработки, который обеспечивает заменяющее значение; flatRecover
, которое, аналогично flatMap
, позволяет вернуть новый экземпляр Exceptional
, который будет развернут, и состояние текущего экземпляра соответствующим образом обновлено; propagate
исключение, выкидывая его из выражения Exceptional
и делая вызов propagate
объявляющим этот тип исключения; propagate
после переноса в другое исключение ( translate it); handle
он, в результате чего пустым Exceptional
; swallow
он содержит пустой блок обработчика. Подход propagate
позволяет выборочно выбирать, какой че которые он хочет выставить из своего кода. Исключения, которые остаются необработанными во время вызова терминальной операции (например, get
), будут скрытно брошены без объявления. Это часто рассматривается как продвинутый и опасный подход, но тем не менее часто используется как способ немного облегчить неприятность проверенных исключений в сочетании с формами лямбды, которые не объявляют их. Класс Exceptional
надеется предложить более чистую и более избирательную альтернативу скрытому броску.
/*
* Copyright (c) 2015, Marko Topolnik. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public final class Exceptional
{
private final T value;
private final Throwable exception;
private Exceptional(T value, Throwable exc) {
this.value = value;
this.exception = exc;
}
public static Exceptional empty() {
return new Exceptional<>(null, null);
}
public static Exceptional ofNullable(T value) {
return value != null ? of(value) : empty();
}
public static Exceptional of(T value) {
return new Exceptional<>(Objects.requireNonNull(value), null);
}
public static Exceptional ofNullableException(Throwable exception) {
return exception != null? new Exceptional<>(null, exception) : empty();
}
public static Exceptional ofException(Throwable exception) {
return new Exceptional<>(null, Objects.requireNonNull(exception));
}
public static Exceptional from(TrySupplier supplier) {
try {
return ofNullable(supplier.tryGet());
} catch (Throwable t) {
return new Exceptional<>(null, t);
}
}
public static Exceptional fromVoid(TryRunnable task) {
try {
task.run();
return new Exceptional<>(null, null);
} catch (Throwable t) {
return new Exceptional<>(null, t);
}
}
public static Consumer super E> swallow() {
return e -> {};
}
public T get() {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
throw new NoSuchElementException("No value present");
}
public T orElse(T other) {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
return other;
}
public T orElseGet(Supplier extends T> other) {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
return other.get();
}
public Stream stream() {
return value == null ? Stream.empty() : Stream.of(value);
}
public Exceptional map(Function super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (value == null) return new Exceptional<>(null, exception);
final U u;
try {
u = mapper.apply(value);
} catch (Throwable exc) {
return new Exceptional<>(null, exc);
}
return ofNullable(u);
}
public Exceptional flatMap(Function super T, Exceptional> mapper) {
Objects.requireNonNull(mapper);
return value != null ? Objects.requireNonNull(mapper.apply(value)) : empty();
}
public Exceptional filter(Predicate super T> predicate) {
Objects.requireNonNull(predicate);
if (value == null) return this;
final boolean b;
try {
b = predicate.test(value);
} catch (Throwable t) {
return ofException(t);
}
return b ? this : empty();
}
public Exceptional recover(
Class extends X> excType, Function super X, T> mapper)
{
Objects.requireNonNull(mapper);
return excType.isInstance(exception) ? ofNullable(mapper.apply(excType.cast(exception))) : this;
}
public Exceptional recover(
Iterable> excTypes, Function super X, T> mapper)
{
Objects.requireNonNull(mapper);
for (Class extends X> excType : excTypes)
if (excType.isInstance(exception))
return ofNullable(mapper.apply(excType.cast(exception)));
return this;
}
public Exceptional flatRecover(
Class extends X> excType, Function super X, Exceptional> mapper)
{
Objects.requireNonNull(mapper);
return excType.isInstance(exception) ? Objects.requireNonNull(mapper.apply(excType.cast(exception))) : this;
}
public Exceptional flatRecover(
Iterable> excTypes, Function super X, Exceptional> mapper)
{
Objects.requireNonNull(mapper);
for (Class extends X> c : excTypes)
if (c.isInstance(exception))
return Objects.requireNonNull(mapper.apply(c.cast(exception)));
return this;
}
public Exceptional propagate(Class excType) throws E {
if (excType.isInstance(exception))
throw excType.cast(exception);
return this;
}
public Exceptional propagate(Iterable> excTypes) throws E {
for (Class extends E> excType : excTypes)
if (excType.isInstance(exception))
throw excType.cast(exception);
return this;
}
public Exceptional propagate(
Class excType, Function super E, ? extends F> translator)
throws F
{
if (excType.isInstance(exception))
throw translator.apply(excType.cast(exception));
return this;
}
public Exceptional propagate(
Iterable> excTypes, Function super E, ? extends F> translator)
throws F
{
for (Class extends E> excType : excTypes)
if (excType.isInstance(exception))
throw translator.apply(excType.cast(exception));
return this;
}
public Exceptional handle(Class excType, Consumer super E> action) {
if (excType.isInstance(exception)) {
action.accept(excType.cast(exception));
return empty();
}
return this;
}
public Exceptional handle(Iterable> excTypes, Consumer super E> action) {
for (Class extends E> excType : excTypes)
if (excType.isInstance(exception)) {
action.accept(excType.cast(exception));
return empty();
}
return this;
}
public T orElseThrow(Supplier extends X> exceptionSupplier) throws X {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
throw exceptionSupplier.get();
}
public boolean isPresent() {
return value != null;
}
public void ifPresent(Consumer super T> consumer) {
if (value != null)
consumer.accept(value);
if (exception != null) sneakyThrow(exception);
}
public boolean isException() {
return exception != null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
return obj instanceof Exceptional && Objects.equals(value, ((Exceptional)obj).value);
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@SuppressWarnings("unchecked")
private static void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}
@FunctionalInterface
public interface TrySupplier {
T tryGet() throws Throwable;
}
@FunctionalInterface
public interface TryRunnable {
void run() throws Throwable;
}
Я смог использовать это, больше не используя параметр includeAll
в файле db.changelog-master.yaml
. Опция includeAll
- это полезный способ быстро начать работу (и обработать все файлы в определенном каталоге), но, похоже, нецелесообразно для регулярного использования. Как упоминалось здесь .
Это то, что я ранее имел в db.changelog-master.yaml
, не использую его таким образом.
databaseChangeLog:
- includeAll:
path: db/changelog/changes/
Это то, что Я обновил его до:
databaseChangeLog:
- include:
file: db/changelog/changes/v0001_users.sql
- include:
file: db/changelog/changes/v0002_accounts.sql
. Важно отметить, что я перечисляю каждый отдельный файл, который я хочу включить, в том порядке, в котором я хочу его запустить.
В исходной версии столбец databasechangelog.filename
будет отличаться в зависимости от того, как было выполнено приложение:
db/changelog/changes/v0001_users.sql
- как будет выглядеть столбец при запуске из IntelliJ BOOT-INF/classes/db/changelog/changes/v0001_users.sql
, как будет выглядеть столбец при запуске из исполняемого банку. После внесения изменений оба варианта выше одинаковы и больше не включают BOOT-INF/classes/
в качестве префикса.
Благодаря другим ответам, которые помогли мне указать в правильном направлении!
Атрибут logicalFilePath
- это именно то, что вы хотите. Я столкнулся с той же проблемой с моими проектами, где я выполнял некоторые части с maven и некоторыми частями с пружинной загрузкой. этот вопрос также может помочь вам.
../changes
, вы можете пойти с этой настройкой. Но предложите вам изменить логику и не использовать includeAll. У этого есть много недостатков. Прочитайте этот и часть предупреждения
– bilak
14 July 2018 в 11:18
Установите logicalFilePath
для каждого набора изменений. Это гарантирует, что столбец DATABASECHANGELOG.FILENAME
согласован и не зависит от вашего физического каталога проверки файла набора изменений, , как описано в этом сообщении .