Способ, которым мы обрабатываем это, заключается в том, чтобы иметь собственный класс распознавателя исключений, который обрабатывает любые исключения, которые не перехвачены другими обработчиками - он реализует HandlerExceptionResolver, Ordered.
Мы объявляем отдельный компонент SimpleMappingExceptionResolver, который перехватывает определенные исключения.
Порядок таков, что наш пользовательский распознаватель запускается после 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.