Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Exception handling spring异常处理程序不处理某些类型的异常_Exception Handling_Spring Mvc_Spring Security - Fatal编程技术网

Exception handling spring异常处理程序不处理某些类型的异常

Exception handling spring异常处理程序不处理某些类型的异常,exception-handling,spring-mvc,spring-security,Exception Handling,Spring Mvc,Spring Security,我在Spring2.5应用程序中设置了一个简单的异常处理程序。当前它捕获所有异常s并显示stacktrace页面 这很好,但是现在spring security没有正确地将未登录的用户踢到登录页面,相反,我的异常页面显示为spring security异常: org.springframework.security.AccessDeniedException 问题是这个应用程序没有自己的异常子类,它用于所有的异常,所以我必须映射Exception,但是取消映射AccessDeniedExcep

我在Spring2.5应用程序中设置了一个简单的异常处理程序。当前它捕获所有
异常
s并显示stacktrace页面

这很好,但是现在spring security没有正确地将未登录的用户踢到登录页面,相反,我的异常页面显示为spring security异常:

org.springframework.security.AccessDeniedException
问题是这个应用程序没有自己的异常子类,它用于所有的异常,所以我必须映射
Exception
,但是取消映射
AccessDeniedException

这在Spring2.5中可能吗

编辑:使用spring security 2.0.1

我的豆子看起来像这样

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.RuntimeException">common/error</prop>
        </props>
    </property>
</bean>**

常见/错误
**

它似乎有一个属性
MappedHandlerClasses
,这就是您要寻找的,因为它可以接受一组异常。

基于卡尔托奇的答案,在您的映射中,您有两个选项。您可以更具体地捕获异常,而不是RuntimeException,或者,您可以为AccessDeniedException的处理程序指定登录视图。视图名称类似于redirect:/login?err=401

请参阅此处完成的配置


他用一个bean处理了多个异常。您也可以这样做,并重定向到您的登录视图。唯一悬而未决的问题是,它是否在配置中接受重定向:/viewname,而我现在还不能对此进行测试。

处理此问题的一种方法是创建另一个实现and-接口的处理程序。在您自己的实现中,您可以执行以下操作:

public class AccessDeniedExceptionResolver implements HandlerExceptionResolver, Ordered
{
    private int order;

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
    {
        if(exception instanceof AccessDeniedException)
        {
            return new ModelAndView("redirect:/login"); //Replace with redirect to your login-page
        }

        return null; //Null-return = pass the exception to next handler in order
    }

    public void setOrder(int order)
    {
        this.order = order;
    }

    @Override
    public int getOrder()
    {
        return order;
    }   
}
现在,有序接口实现允许您告知调用异常处理程序的顺序。SimpleMappingExceptionResolver还实现了Ordered接口,因此您可以在bean定义中执行以下操作:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.RuntimeException">common/error</prop>
        </props>
    </property>
    <property name="order" value="1"/>
</bean>

<bean class="package.to.your.handler.AccessDeniedExceptionResolver">
    <property name="order" value="0"/>
</bean>

常见/错误
具有较低阶值的bean具有较高的优先级(这意味着将在具有较大值的bean之前调用它,在本例中,在SimpleMappingExceptionResolver之前调用AccessDeniedExceptionResolver)


希望这能有所帮助。

我们处理此问题的方法是使用一个自定义异常解析程序类来处理任何未被其他处理程序捕获的异常-它实现HandlerExceptionResolver,Ordered

我们声明一个单独的SimpleMappingExceptionResolver bean,用于捕获特定的异常

顺序是这样的,我们的自定义解析器在SimpleMappingExceptionResolver之后运行

其效果是指定的异常(例如AccessDeniedException)由SimpleMappingExceptionResolver处理并定向到适当的页面

任何其他运行时异常都由自定义解析器处理,该解析器将转发到一般错误页

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="org.springframework.security.AccessDeniedException">accessDenied</prop>
            <prop key="org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException">accessDenied</prop>
        </props>
    </property>
    <property name="order" value="0"/>
</bean>

<bean class="package.to.your.handler.DefaultExceptionResolver">
    <property name="order" value="1"/>
</bean>

拒绝访问
拒绝访问

这种安排允许您捕获任意数量的异常(我在这里捕获2个,AccessDenied和HibernateOptimisticLockingFailureException)使用Spring解析器和其他一切都由自定义解析器捕获。在上面接受的解决方案中,您必须编写更多Java代码来捕获除AccessDenied之外的异常。

还有另一个选项:创建一个能够排除某些异常类的
SimpleMappingExceptionResolver
子类(对于Spring Security,将它们留给默认处理)

公共类ExclutionResolver扩展SimpleMappingExceptionResolver实现InitializingBean{
私有类[]不包括类;
@凌驾
受保护的ModelAndView doResolveException(HttpServletRequest请求、HttpServletResponse响应、对象处理程序、异常ex){
for(类excludedClass:excludedClass){
if(不包括类isInstance(ex)){
返回null;
}
}
返回super.doResolveException(请求、响应、处理程序、ex);
}
公共void集合ExcludedClass(类[]ExcludedClass){
this.excludedClasses=excludedClasses;
}
@凌驾
public void afterPropertieSet()引发异常{
if(ExcludedClass==null){
ExcludedClass=新类[]{};
}
}
}

我迟到了很多年,但我遇到了这个确切的问题,并且提出的解决方案没有一个效果很好

我发现,如果我从我的catch-all处理程序中重新调用异常,那么Spring的默认处理程序将生效:

@ControllerAdvice
@顺序(value=Ordered.lower\u priority)//不幸的是,不够
公共类GeneralExceptionHandler{
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL\u SERVER\u错误)
@应答器
公共字符串processOtherExceptions(异常ex)引发异常{
if(例如AccessDeniedException){
掷骰子;
}
//其他异常的处理程序-记录它并返回一些通用消息。
日志错误(“未捕获异常”,ex);
返回“内部错误”;
}

不知道,但我也对解决方案感兴趣。您使用的是哪个版本的spring security?您确定吗,从文档中可以看出,该字段似乎包含了一个处理映射异常的
处理程序
对象列表,我无法更具体地说,因为我继承的应用程序已经在整个plac中抛出RunTimeExceptione、 我不能在一百万个地方修改它,对吧,我想了很多,这就是为什么我包括了第二个选项。谢谢,这很有效。我必须等20个小时才能给你分数。在SimpleMappingExceptionResolver for AccessDeniedException中添加一个映射到重定向:/login的SimpleMappingExceptionResolver不是比实现一个类更容易吗要这么做?@mkoryak:谢谢,不用着急。如果发生这种情况,在那之前可能会出现更好的解决方案
public class ExclusionExceptionResolver extends SimpleMappingExceptionResolver implements InitializingBean {
  private Class[] excludedClasses;

  @Override
  protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    for (Class<?> excludedClass : excludedClasses) {
      if (excludedClass.isInstance(ex)) {
        return null;
      }
    }
    return super.doResolveException(request, response, handler, ex);
  }
  public void setExcludedClasses(Class[] excludedClasses) {
    this.excludedClasses = excludedClasses;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    if (excludedClasses == null) {
      excludedClasses = new Class[]{};
    }
  }
}