Spring - Создайте новый modelAndView из существующих BindingResult и Model - PullRequest
0 голосов
/ 06 июля 2018

Я пытаюсь улучшить приложение Spring MVC, чтобы использовать глобальный обработчик исключений, чтобы перехватывать различные исключения постоянства на всех моих контроллерах.Это код контроллера, который выполняется, когда пользователь пытается сохранить новый объект StrengthUnit, например.Все проверки работают отлично, и форма правильно возвращается с сообщением об ошибке под полем имени, когда создается исключение PersistenceException.Полученная страница также правильно содержит атрибут forceUnit и может связать поле (у этого объекта просто есть поле имени) обратно в форму:

@RequestMapping(value = {"/newStrengthUnit"}, method = RequestMethod.POST)
public String saveStrengthUnit(@Valid StrengthUnit strengthUnit, BindingResult result, ModelMap model) throws Exception
{
    try
    {
        setPermissions(model);

        if (result.hasErrors())
        {
            return "strengthUnitDataAccess";
        }
        strengthUnitService.save(strengthUnit);

        session.setAttribute("successMessage", "Successfully added strength unit \"" + strengthUnit.getName() + "\"!");
    }
    catch (PersistenceException ex)
    {
        FieldError error = new FieldError("strengthUnit", "name", strengthUnit.getName(), false, null, null, 
                "Strength unit \"" + strengthUnit.getName() + "\" already exists!");
        result.addError(error);

        return "strengthUnitDataAccess";
    }

    return "redirect:/strengthUnits/list";
}

Я пытаюсь использовать это как отправную точку длявключить глобальный обработчик исключений, который я построил, и я не понимаю, как этот обработчик может быть вызван и вернуть ту же страницу с той же моделью и результатом привязки.Я попробовал что-то очень уродливое с пользовательским исключением, просто чтобы попытаться понять механику и заставить обработчик вернуть мне ту же страницу, что и раньше, и я не могу заставить ее работать.

Вот пользовательскийИсключение, которое я построил:

public class EntityAlreadyPersistedException extends Exception
{
    private final Object entity;
    private final FieldError error;
    private final String returnView;
    private final ModelMap model;
    private final BindingResult result;

    public EntityAlreadyPersistedException(String message, Object entity, FieldError error, String returnView, ModelMap model, BindingResult result) 
    {
        super(message);

        this.entity = entity;
        this.error = error;
        this.returnView = returnView;
        this.model = model;
        this.result = result;
    }

    public Object getEntity() 
    {
        return entity;
    }

    public FieldError getError() 
    {
        return error;
    }

    public String getReturnView() 
    {
        return returnView;
    }

    public ModelMap getModel()
    {
        return model;
    }

    public BindingResult getResult() 
    {
        return result;
    }
}

Вот мой модифицированный блок catch в методе saveStrengthUnit моего контроллера:

catch (PersistenceException ex)
    {
        FieldError error = new FieldError("strengthUnit", "name", strengthUnit.getName(), false, null, null, 
                "Strength unit \"" + strengthUnit.getName() + "\" already exists!");
        result.addError(error);

        throw new EntityAlreadyPersistedException("Strength unit \"" + strengthUnit.getName() + "\" already exists!", strengthUnit, error, 
                "strengthUnitDataAccess", model, result);
    }

И, наконец, метод глобального обработчика исключений для его перехвата:

@ExceptionHandler(EntityAlreadyPersistedException.class)
public ModelAndView handleDataIntegrityViolationException(HttpServletRequest request, Exception ex)
{
    EntityAlreadyPersistedException actualException;

    actualException = ((EntityAlreadyPersistedException)ex);

    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName(actualException.getReturnView());
    modelAndView.addObject(BindingResult.MODEL_KEY_PREFIX + "strengthUnitForm", actualException.getResult());

    if (actualException.getEntity() instanceof StrengthUnit)
    {
        modelAndView.addObject("strengthUnit", (StrengthUnit)actualException.getEntity());
    }
    return modelAndView;
}

Это очень уродливо и, вероятно, очень глупо для опытного разработчика Spring, но я не совсем такой (пока).Это работает, НО результат привязки теряется и ошибки проверки не появляются.Как я могу изменить этот код так, чтобы он вел себя так, как раньше, при этом все еще используя глобальный обработчик исключений для обработки всех ошибок?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 30 июля 2018

1.Вы устанавливаете сущность как сила-единица. GetName (), а не сила-единица.

    throw new EntityAlreadyPersistedException("Strength unit \"" + strengthUnit.getName() + "\" already exists!", strengthUnit, error, 
                    "strengthUnitDataAccess", model, result);

2.но вы проверяете if (actualException.getEntity() instanceof StrengthUnit

Надеюсь, это поможет, Попробуйте установить сущность в качестве forceUnit.

0 голосов
/ 27 июля 2018

Если вы пытаетесь перехватить действительное исключение, которое было выброшено при использовании @Valid. И вы хотите, чтобы тот же обработчик обрабатывал это исключение, затем добавьте еще один класс исключений в аннотацию @ExceptionHandler

Что говорит доктор

Значение @ExceptionHandler может быть установлено в массив исключений типы. Если выброшено исключение, соответствует одному из типов в списке, тогда метод, аннотированный соответствующим @ExceptionHandler, будет вызывается. Если значение аннотации не установлено, типы исключений перечислены как аргументы метода.

Исключение, создаваемое аннотацией @Valid, - это MethodArgumentNotValidException, поэтому вы можете добавить это исключение в тот же метод обработчика

Надеюсь, это поможет вам

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...