一、说明
web系统开发过程中经常遇见400/404/500类型的错误页面,对于开发人员而言见到这种页面多了可能觉得问题不大,但是实际是很重要的,需要配置一个合理的自定义错误页面。
本文只提通过springmvc controller配置自定义错误页,Tomcat设置400/404/500自定义错误页面(推荐)请参考博文:点击打开链接
二、实现
1.spring-mvc.xml(视图解析器配置)
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="suffix" value=".jsp"></property>
<property name="prefix" value="/WEB-INF/views/"></property>
</bean>
2.ErrorController.java(代码实现)
package com.mvc.pab.internet.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("error")
public class ErrorController {
private static final String BASE_DIR = "error/";
@RequestMapping("400")
public String handle1(HttpServletRequest request){
return BASE_DIR + "400";
}
@RequestMapping("404")
public String handle2(HttpServletRequest request){
return BASE_DIR + "404";
}
@RequestMapping("500")
public String handle3(HttpServletRequest request){
return BASE_DIR + "500";
}
}
3.web.xml(错误页面路径定义)
<error-page>
<error-code>400</error-code>
<location>/error/400</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500</location>
</error-page>
3.spring-mvc.xml(拦截器配置)
项目当中有设置全局拦截器的,一定要在这里添加拦截器配置,不然会被拦截,配置方法是往自己的配置中节点代码<mvc:exclude-mapping path="/error/*" />,/error/*为我的错误页的视图层,意为都不拦截/error/
<!--配置拦截器, 多个拦截器,顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/error/*" />
<mvc:exclude-mapping path="/test/*" />
<mvc:exclude-mapping path="/manager/*" />
<mvc:exclude-mapping path="/wxmanager/*" />
<bean class="com.mvc.filter.CommonInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
<mvc:mapping path="/manager/*" />
<mvc:mapping path="/wxmanage/*" />
<mvc:exclude-mapping path="/manager/login" />
<mvc:exclude-mapping path="/manager/doLogin" />
<bean class="com.mvc.filter.ManagerInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
重启服务器生效!!!!
附文章ManagerInterceptor.java示例
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.mvc.pab.model.Account;
import com.mvc.security.model.User;
public class ManagerInterceptor extends HandlerInterceptorAdapter {
private final Logger log = LoggerFactory.getLogger(ManagerInterceptor.class);
/**
* 在业务处理器处理请求之前被调用
* 如果返回false
* 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
* 如果返回true
* 执行下一个拦截器,直到所有的拦截器都执行完毕
* 再执行被拦截的Controller
* 然后进入拦截器链,
* 从最后一个拦截器往回执行所有的postHandle()
* 接着再从最后一个拦截器往回执行所有的afterCompletion()
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
log.info("==============执行顺序: 1、preHandle================");
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
String url = requestUri.substring(contextPath.length());
log.info("requestUri:"+requestUri);
log.info("contextPath:"+contextPath);
log.info("url:"+url);
//String token = (String)request.getSession().getAttribute("token");
User admin = (User)request.getSession().getAttribute("admin");
if(admin == null){
//异步请求
if(request.getHeader("x-requested-with")!=null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")){
response.getWriter().print("timeout");
return false;
}else{
log.info("Interceptor:跳转到login页面!");
response.sendRedirect("../manager/login");
return false;
}
}else if (! (admin.getType() == 1)) {//拦截高尔夫和机场的管理用户,只能查询订单和确认到场
if ( ! (url.equals("/manager/search") || url.equals("/manager/getOrder") || url.equals("/manager/confirmUser") || url.equals("/manager/golfPage") || url.equals("/manager/airPage") || url.equals("/manager/logout") || url.equals("/manager/airOrder") || url.equals("/manager/golfOrder"))) {
response.sendRedirect("../manager/login");
return false;
}
return true;
}else{
return true;
}
}
/**
* 在业务处理器处理请求执行完成后,生成视图之前执行的动作
* 可在modelAndView中加入数据,比如当前时间
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("==============执行顺序: 2、postHandle================");
if(modelAndView != null){ //加入当前时间
// modelAndView.addObject("var", "测试postHandle");
}
}
/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
*
* 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("==============执行顺序: 3、afterCompletion================");
}
}
CommonIntercetor.java示例代码
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.mvc.framework.util.DomainUtils;
import com.mvc.pab.internet.controller.AccountController;
import com.mvc.pab.model.Account;
import com.mvc.soecode.wxtools.api.IService;
import com.mvc.soecode.wxtools.api.WxConsts;
import com.mvc.soecode.wxtools.api.WxService;
import com.soecode.wxtools.bean.WxUserList.WxUser;
/**
* @author justin 2017-8-1
*/
public class CommonInterceptor extends HandlerInterceptorAdapter {
private final Logger log = Logger.getLogger(CommonInterceptor.class);
public static final String LAST_PAGE = "com.alibaba.lastPage";
/*
* 利用正则映射到需要拦截的路径
*
* private String mappingURL;
*
* public void setMappingURL(String mappingURL) { this.mappingURL =
* mappingURL; }
*/
/**
* 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
* 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链,
* 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion()
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
log.info("==============执行顺序: 1、preHandle================");
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
String url = requestUri.substring(contextPath.length());
log.info("requestUri:" + requestUri);
log.info("contextPath:" + contextPath);
log.info("url:" + url);
String token = (String) request.getSession().getAttribute("token");
WxUser wxUser = (WxUser) request.getSession().getAttribute("wxUser");
Account user = (Account) request.getSession().getAttribute("user");
if (null == wxUser) {// 需要授权登录
if (request.getHeader("x-requested-with") != null
&& request.getHeader("x-requested-with").equalsIgnoreCase(
"XMLHttpRequest")) {
response.getWriter().print("timeout");
return false;
} else {
IService wxService = new WxService();
String oauth_url = wxService.oauth2buildAuthorizationUrl(
AccountController.REDIRECT_URL,
WxConsts.OAUTH2_SCOPE_USER_INFO, "");
response.sendRedirect(oauth_url);
return false;
}
}
if (user == null) {// 未验证身份证
// 异步请求
if (request.getHeader("x-requested-with") != null
&& request.getHeader("x-requested-with").equalsIgnoreCase(
"XMLHttpRequest")) {
response.getWriter().print("timeout");
return false;
} else {
log.info("Interceptor:跳转到用户首页面!");
response.sendRedirect(DomainUtils.getDynamicDomain()
+ "/account/index");
return false;
}
} else
return true;
}
/**
* 在业务处理器处理请求执行完成后,生成视图之前执行的动作 可在modelAndView中加入数据,比如当前时间
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("==============执行顺序: 2、postHandle================");
if (modelAndView != null) { // 加入当前时间
// modelAndView.addObject("var", "测试postHandle");
}
}
/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
*
* 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("==============执行顺序: 3、afterCompletion================");
}
}