10

我的问题是我想创建一个 @ExceptionHandler 方法来捕获所有未处理的异常。一旦被捕获,我想重定向到当前页面,而不是指定一个单独的页面来显示错误。

基本上我如何获取somemethod返回的someview的值并在下面的方法unhandledExceptionHandler中动态设置它。

@ExceptionHandler(Exception.class)
protected ModelAndView unhandledExceptionHandler(Exception ex){
    System.out.println("unhandle exception here!!!");
    ModelAndView mv = new ModelAndView();
    mv.setViewName("currentview");
    mv.addObject("UNHANDLED_ERROR", "UNHANDLED ERROR. PLEASE CONTACT SUPPORT. "+ex.getMessage());
    return mv;
}



@RequestMapping(value = "/somepage", method = RequestMethod.GET)
public String somemethod(HttpSession session) throws Exception {
    String abc = null;
    abc.length();
    return "someview";
}

所以在 JSP 中,我可以将这个错误消息重新呈现到当前页面中。

<c:if test="${not empty UNHANDLED_ERROR}">
    <div class="messageError"> ${UNHANDLED_ERROR}</div>
</c:if>
4

5 回答 5

6

我不认为有办法做你所要求的,因为在异常处理程序方法unhandledExceptionHandler中,没有办法找出处理程序方法somemethod将返回的视图的名称。

唯一的方法是您引入某种元数据方案,以便当您最终进入异常处理程序时,您可以确定将其映射到哪个视图。但我认为这个元数据方案会相当复杂。您可以通过找出抛出异常时访问的原始 url 来实现这样的方案,这可以通过下面的代码片段来完成。

(ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()

一旦您知道原始请求 URL 可以重定向到它,也许使用 flash 属性来存储存在异常的事实以及错误是什么。

当您有一个在不同视图之间进行选择的处理程序方法时,将出现元数据的主要问题。

@RequestMapping(value = "/somepage", method = RequestMethod.GET)
public String somemethod(HttpSession session) throws Exception {
    String abc = null;
    if(someCondition) {
        abc.length();
        return "someview";
    } else {
        // do some stuff here.
        return "someOtherView";
    }
}

即使知道某个方法是错误的根源,您也不知道 if 语句中的哪个分支导致了异常。

于 2013-09-16T16:49:32.547 回答
6

我不认为你可以在不修改所有处理程序方法的情况下做到这一点。但是,您可以尝试以“漂亮”的方式执行此操作:

1)您可以定义自己的注释,它将接受目标视图名称作为参数(例如@ExceptionView

2)接下来要做的是用它标记您的处理程序方法,例如:

@ExceptionView("someview")
@RequestMapping(value = "/somepage", method = RequestMethod.GET)
    public String somemethod(HttpSession session) throws Exception {
    String abc = null;
    abc.length();
    return "someview";
}

3)之后,您可以在异常处理程序中执行以下操作:

@ExceptionHandler(Exception.class)
protected ModelAndView unhandledExceptionHandler(Exception ex, HandlerMethod hm) {
    String targetView;
    if (hm != null && hm.hasMethodAnnotation(ExceptionView.class)) {
        targetView = hm.getMethodAnnotation(ExceptionView.class).getValue();
    } else {
        targetView = "someRedirectView"; // kind of a fallback
    }
    ModelAndView mv = new ModelAndView();
    mv.setViewName(targetView);
    mv.addObject("UNHANDLED_ERROR", "UNHANDLED ERROR. PLEASE CONTACT SUPPORT. "+ex.getMessage());
    return mv;
}
于 2017-06-28T11:58:59.383 回答
2

您可以将错误放在 ModelAndView 对象中,而不是在单独的页面上发送错误。在您的情况下,您可以将 try/catch 放在您的控制器方法中并返回相同的视图,如下所示:

@RequestMapping(value = "/somepage", method = RequestMethod.GET)
public String somemethod(ModelAndView mv,HttpSession session) throws Exception {
   mv.setViewName("someview");
   try{ 
      String abc = null;
      abc.length();
    } catch(Exception e) {
      mv.addObject("UNHANDLED_ERROR", "UNHANDLED ERROR. PLEASE CONTACT SUPPORT.  "+ex.getMessage());
   }
   return mv;
}

因此,将 ModelAndView 添加到您的方法中并返回它。

于 2013-09-21T11:30:33.097 回答
2

这个我没有试过,但是根据这里的文档,我们可以在异常处理程序中获取请求对象。我们可能无法获取链接到 URL 的视图。从 URL 获取视图,以及视图的状态/模型将是棘手的部分。

  @ExceptionHandler(Exception.class)
  public ModelAndView handleError(HttpServletRequest req, Exception ex) {
    logger.error("Request: " + req.getRequestURL() + " raised " + ex);

    ModelAndView mav = new ModelAndView();
    mav.addObject("exception", ex);
    mav.addObject("url", req.getRequestURL());
    mav.setViewName("error");
    return mav;
  }
于 2017-06-30T20:11:38.213 回答
0
  1. 创建一个带有注释的控制器方法@RequestMethod("/server-error")
  2. 创建一个带有注释的控制器@ExceptionHandler方法return "forward:/server-error";
于 2017-07-05T13:11:19.263 回答