1. 问题提出的根源:
处理 404 noound 错误。
2. 一般做法:
在 web.xml 里配置 error-page.
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/error/404.jsp</location>
</error-page>
3. 特殊场景
项目当中使用 shiro 安全框架,配置了非 ServletContainer 的 session 管理器。
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
如果想同时使用< error-page>来处理 404 错误,就会造成 session 的重新建立,表现
为已登录用户,访问一个不存在的 url,得到一个返回 404 页面,然后再访问正确的
url 地址又需要重新登录。
4. 原因分析
shiro 的 DefaultWebSessionManager 把 session 自己管理起来了,不放到 web 容器
里,那么当发生 404 时,web 容器在处理过程里发现容器里没有 session,那么就会建立
一个新的 sessionid,然后把 sessionid 绑定到请求上。于是 shiro 框架就认为是一
个新的 session 来了,但是没有登录,所以自动跳转到 login 页面。
5. 失败的解决方案
不用 web 容器的 error-page 处理。改用 spring mvc 框架自身处理。配置异常处理器:
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop
key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
<prop key="NoSuchRequestHandlingMethodException">error/404</prop>
<prop key="java.lang.Throwable">error/500</prop>
</props>
</property>
</bean>
如上面标黄色的设置项,实际是不起作用的。因为正常的 404 找不到地址错误是不会
抛出任何异常的。
6. 成功的方案
不用 web 容器的 error-page 处理。在 spring mvc 里配置一个能匹配所有请求的处理