如何在Spring MVC架构中实现站点范围的异常处理?

时间:2013-05-29 22:10:17

标签: java spring spring-mvc exception-handling spring-security

注意:跳到底部的两个更新以找到答案。

我有一个在Tomcat上运行的Spring(3)MVC Web应用程序。此Web应用程序充当远程WSDL服务层的UI。我编写了一个自定义AuthenticationProvider来对此远程服务进行身份验证。这很好。我的问题是:

每个控制器方法或多或少都会导致远程调用此远程WSDL。我的计划是没有Tomcat或Spring过期会话,但要等到远程服务器告诉我会话已经到期,然后将用户重新路由到登录页面,告诉他们他们的会话已经过期。

所有其他控制器扩展的BaseController都有这个方法:

protected void addBindingErrors(HttpSession session, MTAResponse response, BindingResult binding, boolean allowDefault) {
switch (response.getResponseCode()) {
case SESSION_EXPIRED:
     UserInfo nfo = (UserInfo)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
     SecurityContext context = SecurityContextHolder.getContext();
     System.out.println("token in handle session expired: " + nfo.getMtaCoreSessionId());
     if(session != null){
          System.out.println("invalidating session");
          session.invalidate();
          //1.  throw new SessionAuthenticationException("session expiredd");
          ModelAndView mav = new ModelAndView("error");
          throw new ModelAndViewDefiningException(mav);
          //3.  something else?
     }
     context.setAuthentication(null);
  break;      
case INVALID_PARAMETER_VALUE:
  binding.addError(...);
  break;
case ACCESS_DENIED:
  binding.addError(...);
  break;          
default:
  if(allowDefault){
    binding.addError(...);
    break;
  }
}

}

我找到了一些解决方案,但我是Spring的新手,所以我不知道他们是不是“正确的”,或者是否存在潜伏的问题。

  1. (有点作弊)在BaseController.addBindingError()方法中,如果收到远程会话过期代码,则抛出SessionAuthenticationException
    • 优点:这可行,自动将用户重新路由到登录页面(我想因为我设置了authentication-failure-url?)
    • 缺点:我必须更改addBindingError的签名才能抛出这种异常。
    • Con:我还必须更改每个控制器方法的签名以抛出此类异常,因为它们都会对WSDL进行远程服务调用。
    • Con:用户不知道为什么他们回到了登录页面,我不确定是否有办法让他们知道
  2. 在BaseController.addBindingError()方法中,如果收到远程会话过期代码,则抛出ModelAndViewDefiningException

    • 优点:这样可以自动将用户重新路由到相应的错误页面,该页面可以包含指向登录页面的链接
    • 亲:我们可以在此页面向用户解释他们是如何到达这里的。
    • 缺点:我必须更改addBindingError的签名才能抛出这种异常。
    • Con:我还必须更改每个控制器方法的签名以抛出此类异常,因为它们都对远程WSDL进行远程服务调用
  3. 在BaseController.addBindingError()方法中,如果收到远程会话过期代码,则抛出MyCustomRemoteSessionExpiredException,然后在SimpleMappingExceptionResolver中捕获它

    • 优点:这样可以自动将用户重新路由到相应的错误页面,该页面可以包含指向登录页面的链接
    • 亲:我们可以在此页面向用户解释他们是如何到达这里的。
    • 缺点:我必须更改addBindingError的签名才能抛出这种异常。
    • Con:我还必须更改每个控制器方法的签名以抛出此类异常,因为它们都对远程WSDL进行远程服务调用
  4. 数字2和#3具有相同的优点/缺点。 #3似乎可能是一个更“正确”的解决方案。有没有人有任何反馈,建议或替代方案?

    2013年5月30日更新:

    我想我可能找到了我正在寻找的东西,我认为它需要我升级到最新的3.2版本。 @ControllerAdvice这里有一篇文章: http://www.javacodegeeks.com/2013/03/exception-handling-with-the-spring-3-2-controlleradvice-annotation.html 从BaseController.addBindingError,我将抛出MyCustomException(它扩展RuntimeException,以便方法签名不需要声明throws语句)并在新的@ControllerAdvice类(将包含@ExceptionHandler方法)中处理它。
    任何人都可以确认或否认这种方法吗? 还有更好的建议吗?

    谢谢!

    2013年12月3日更新**

    这个问题的标题会更好:“如何在Spring MVC架构中实现站点范围的异常处理?”。所以,我正在更改标题(前标题是基于我的误解,即与远程SOAP服务器的交互与我的真实问题有关)。我实施了5月份讨论的解决方案,并且一直运行良好。我甚至扩展了@ControllerAdvice类来处理其他RuntimeExceptions。

0 个答案:

没有答案