Spring - 从现有的BindingResult和Model构造新的modelAndView

Mar*_*tin 9 java model-view-controller spring controller exception

我正在尝试改进我的Spring MVC应用程序,以使用全局异常处理程序来捕获所有控制器中的各种持久性异常.这是用户尝试保存新的StrengthUnit对象时运行的控制器代码.所有验证都可以正常工作,并且在抛出PersistenceException时正确返回表单,并在名称字段下面显示错误消息.结果页面还正确包含strengthUnit属性,并且能够将字段(此实体只有一个名称字段)绑定到表单:

@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";
}
Run Code Online (Sandbox Code Playgroud)

我试图使用它作为一个起点来合并我构建的全局异常处理程序,我不明白如何调用该处理程序并返回具有相同模型和绑定结果的同一页面.我尝试了一些非常丑陋的自定义异常只是为了尝试理解机制并让处理程序返回我以前的同一页面,我无法让它工作.

这是我构建的自定义异常:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在控制器的saveStrengthUnit方法中修改的catch块:

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);
    }
Run Code Online (Sandbox Code Playgroud)

最后是全局异常处理程序捕获它的方法:

@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;
}
Run Code Online (Sandbox Code Playgroud)

对于经验丰富的Spring开发人员来说,这非常难看,可能非常愚蠢,但我还不是一个.这可以工作但是绑定结果丢失并且不会出现验证错误.如何在仍使用全局异常处理程序处理所有错误的同时修改此代码以使其像以前一样运行?

谢谢!

Ash*_*ari 0

如果您试图捕获在使用 @Valid 时抛出的有效异常。并且您希望相同的处理程序处理该异常,则在 @ExceptionHandler 注释中再添加一个异常类

医生怎么说

@ExceptionHandler 值可以设置为异常类型的数组。如果抛出的异常与列表中的类型之一匹配,则将调用使用匹配的 @ExceptionHandler 注解的方法。如果未设置注释值,则使用作为方法参数列出的异常类型。

@Valid 注解抛出的异常是 MethodArgumentNotValidException ,因此您可以在同一个处理程序方法上添加此异常

我希望这可以帮助你