前因
博主在写项目的时候,自定义了一个异常类,继承自运行时异常类:
/**
* 禁止访问异常类
* @author alageek
*/
public class AccessForbiddenException extends RuntimeException {
private static final long serialVersionUID = 7526324512252691698L;
public AccessForbiddenException(){
super();
}
public AccessForbiddenException(String message, Throwable cause, Boolean enableSuppression, Boolean writableStackTrace){
super(message, cause, enableSuppression, writableStackTrace);
}
public AccessForbiddenException(String message, Throwable cause){
super(message, cause);
}
public AccessForbiddenException(Throwable cause){
super(cause);
}
public AccessForbiddenException(String message){
super(message);
}
}
而后在拦截器中,将其抛出:
/**
* 登录拦截
* @author alageek
*/
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Admin admin = (Admin) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_ADMIN);
if(admin == null){
throw new AccessForbiddenException(CrowdConstant.MESSAGE_ACCESS_FORBIDDEN);
}
return true;
}
}
同时又在SpringMVC中设置了全局异常处理:
/**
* 异常处理机制
* @author alageek
* 注解ControllerAdvice表示当前类是基于注解的异常处理器类
*/
@ControllerAdvice
public class CrowdExceptionResolver {
/**
* 禁止访问异常处理
* 注解ExceptionHandler将异常类与方法关联
* @param exception 异常对象
* @param request 请求对象
* @param response 响应对象
* @return 若请求为Ajax请求,则返回json类型的错误信息,否则返回错误页面
* @throws IOException ResultEntity对象转json异常
*/
@ExceptionHandler(value = AccessForbiddenException.class)
public ModelAndView resolveAccessForbiddenException(
AccessForbiddenException exception,
HttpServletRequest request,
HttpServletResponse response) throws IOException {
String viewName = "admin-login";
return commonResolve(exception, request, response, viewName);
}
private ModelAndView commonResolve(
Exception exception,
HttpServletRequest request,
HttpServletResponse response,
String viewName) throws IOException {
if(CrowdUtil.judgeRequestType(request)){
// Ajax请求
response.getWriter().write(new Gson().toJson(ResultEntity.failed(exception.getMessage())));
return null;
}
// 普通请求
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
modelAndView.setViewName(viewName);
return modelAndView;
}
}
最终的启动项目后,发现在拦截器抛出AccessForbiddenException异常时,全局异常处理并未捕获到异常。
BUG定位
经过百度SpringMVC全局异常处理的三种方式后,恍然大悟,按上面博主所写的这种方式捕获全局异常,只能捕获到Controller里抛出的异常,想要捕获拦截器里这个异常,需要在SpringMVC的配置文件中进行配置。
BUG修复
在SpringMVC配置文件中配置异常机制,如下:
<!-- 配置基于XML的异常机制 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="simpleMappingExceptionResolver">
<!-- 配置异常类型和具体视图页面的对应关系 -->
<property name="exceptionMappings">
<props>
<prop key="com.alageek.crowd.exception.AccessForbiddenException">admin-login</prop>
</props>
</property>
</bean>