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

标签 java spring exception model-view-controller controller

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

@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";
}

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

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

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;
    }
}

这是我在 Controller 的 saveStrengthUnit 方法中修改的 catch block :

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 开发人员来说,这非常丑陋,而且可能非常愚蠢,但我(还)不完全是这样。这有效但绑定(bind)结果丢失并且不会出现验证错误。我如何才能修改此代码以像以前一样运行,同时仍然使用全局异常处理程序来处理所有错误?

谢谢!

最佳答案

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

医生说的

The @ExceptionHandler value can be set to an array of Exception types. If an exception is thrown matches one of the types in the list, then the method annotated with the matching @ExceptionHandler will be invoked. If the annotation value is not set then the exception types listed as method arguments are used.

@Valid 注解抛出的异常是 MethodArgumentNotValidException ,所以你可以在同一个处理方法上添加这个异常

希望对你有帮助

关于java - Spring - 从现有的 BindingResult 和 Model 构建新的 modelAndView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51209754/

相关文章:

spring - 在 NamedParameterJDBCTemplate 中绑定(bind) ORDER BY 的参数

java - 将 MongoTemplate 传递给自定义存储库实现

java - 如何使用 JAVA 从 Internet 下载 zip 文件并将其保存在特定文件夹中?

JSP 2.0 自定义标签 : Unable to find setter method?

java - 即使我停止按键后,keyPressed() 事件仍会继续触发

java - 为什么linkedlist.java不导出Node类

java - FileReader 在 Java 中不工作

java - Spring Boot + JMustache 404 未从/resources/templates 文件夹中找到 .html 页面错误

java - 日期比 json 响应中的实际日期少一位

Python异常处理: Check return value of function