统一的异常处理和自定义的全局异常处理器的配置使用
一、统一的异常处理
1、自定义异常处理类,继承了exception
package yycg.base.process.result; /** * 自定义系统异常类 */ public class ExceptionResultInfo extends Exception { // 系统统一使用的结果类,包括了 提示信息类型和信息内容 private ResultInfo resultInfo; public ExceptionResultInfo(ResultInfo resultInfo) { super(resultInfo.getMessage()); this.resultInfo = resultInfo; } public ResultInfo getResultInfo() { return resultInfo; } public void setResultInfo(ResultInfo resultInfo) { this.resultInfo = resultInfo; } }
2、统一的异常处理类,包括异常类型,异常信息
package yycg.base.process.result; import java.util.HashMap; import java.util.List; import java.util.Map; import yycg.util.ResourcesUtil; /** * 系统提示信息封装类 * @author mrt * */ public class ResultInfo { public static final int TYPE_RESULT_FAIL = 0;//失败 public static final int TYPE_RESULT_SUCCESS = 1;//成功 public static final int TYPE_RESULT_WARN = 2;//警告 public static final int TYPE_RESULT_INFO = 3;//提示信息 public ResultInfo(){} /** * 消息提示类型 */ private int type; /** * 提示代码 */ private int messageCode; /** * 提示信息 */ private String message; /** * 提示信息明细列表 */ private List<ResultInfo> details; public List<ResultInfo> getDetails() { return details; } public void setDetails(List<ResultInfo> details) { this.details = details; } /** * 提示消息对应操作的序号,方便用户查找问题,通常用于在批量提示信息中标识记录序号 */ private int index; /** * 提交后得到到业务数据信息从而返回给页面 */ private Map<String,Object> sysdata = new HashMap<String, Object>(); /** * 构造函数,根据提交信息代码messageCode获取提示信息 * @param MESSAGE */ public ResultInfo(final int type,int messageCode,String message){ this.type = type; this.messageCode = messageCode; this.message = message; } public int getMessageCode() { return messageCode; } public void setMessageCode(int messageCode) { this.messageCode = messageCode; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public int getType() { return type; } public void setType(int type) { this.type = type; } public boolean isSuccess(){ if(this.type == TYPE_RESULT_SUCCESS){ return true; } return false; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public Map<String, Object> getSysdata() { return sysdata; } public void setSysdata(Map<String, Object> sysdata) { this.sysdata = sysdata; } }
3、操作结果信息返回到页面进行提示的包装类
package yycg.base.process.result; /** * 系统提交结果结果类型 * @author Thinkpad * */ public class SubmitResultInfo { public SubmitResultInfo(ResultInfo resultInfo){ this.resultInfo = resultInfo; } //操作结果信息 private ResultInfo resultInfo; public ResultInfo getResultInfo() { return resultInfo; } public void setResultInfo(ResultInfo resultInfo) { this.resultInfo = resultInfo; } }
使用说明:
【1】
ExceptionResultInfo 类继承了exception,同时添加了resultInfo属性
resultInfo用来标记异常出错类型(type)和记录异常信息(message)
例子:
resultInfo.setType(resultInfo.TYPE_RESULT_FAIL);//0错误 1成功 2警告3提示
resultInfo.setMessage("账号已存在,请重新输入!");
throw new ExceptionResultInfo(resultInfo);
【2】
在将json异常信息放回到页面时使用SubmitResultInfo类
return new SubmitResultInfo(resultInfo);
二、自定义全局异常处理器,springmvc 提供接口:HandlerExceptionResolver
1、自定义的异常处理器类,实现接口:handlerExceptionResolver
package yycg.base.process.exception; import java.io.IOException; import java.lang.reflect.Method; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import yycg.base.process.result.ExceptionResultInfo; import yycg.base.process.result.ResultInfo; /** * * <p> * Title: ExceptionResolverCustom * </p> * <p> * Description:全局异常处理器 * </p> * <p> * Company: www.itcast.com * </p> * * @author * @date * @version 1.0 */ public class ExceptionResolverCustom implements HandlerExceptionResolver { // json转换器 // 将异常信息转json private HttpMessageConverter<ExceptionResultInfo> jsonMessageConverter; // 前端控制器调用此方法执行异常处理 // handler,执行的action类就包装了一个方法(对应url的方法) @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 输出 异常信息 ex.printStackTrace(); // 转成springmvc底层对象(就是对action方法的封装对象,只有一个方法) HandlerMethod handlerMethod = (HandlerMethod) handler; // 取出方法 Method method = handlerMethod.getMethod(); // 判断方法是否返回json // 只要方法上有responsebody注解表示返回json // 查询method是否有responsebody注解 ResponseBody responseBody = AnnotationUtils.findAnnotation(method, ResponseBody.class); if (responseBody != null) { // 将异常信息转json输出 return this.resolveJsonException(request, response, handlerMethod, ex); } /** *1如果上面是可预知异常,type和message都已经设置有值,return ModelandView *直接将可预知异常返回到请求页面的回调函数,不再执行以下代码end *2如果是未知异常,则执行以下代码,构建未知异常,跳转到error页面显示 */ // 这里说明action返回的是jsp页面 // 解析异常 ExceptionResultInfo exceptionResultInfo = resolveExceptionCustom(ex); // 将异常信息在异常页面显示 request.setAttribute("exceptionResultInfo", exceptionResultInfo.getResultInfo()); // 转向错误页面 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("exceptionResultInfo", exceptionResultInfo.getResultInfo()); modelAndView.setViewName("/base/error");// 逻辑视图名 return modelAndView; } //------------------------------------------------------------------------------------ // 异常信息解析方法 private ExceptionResultInfo resolveExceptionCustom(Exception ex) { ResultInfo resultInfo = null; if (ex instanceof ExceptionResultInfo) { // 抛出的是系统自定义异常 resultInfo = ((ExceptionResultInfo) ex).getResultInfo(); } else { // 重新构造“未知错误”异常 resultInfo = new ResultInfo(); resultInfo.setType(ResultInfo.TYPE_RESULT_FAIL); resultInfo.setMessage("未知错误!"); } return new ExceptionResultInfo(resultInfo); } //------------------------------------------------------------------------------------ // 将异常信息转json输出 private ModelAndView resolveJsonException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 解析异常 (解析返回异常是自定义异常还是未知异常) ExceptionResultInfo exceptionResultInfo = resolveExceptionCustom(ex); HttpOutputMessage outputMessage = new ServletServerHttpResponse(response); try { //将exceptionResultInfo对象转成json输出 jsonMessageConverter.write(exceptionResultInfo, MediaType.APPLICATION_JSON, outputMessage); } catch (HttpMessageNotWritableException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new ModelAndView(); } public HttpMessageConverter<ExceptionResultInfo> getJsonMessageConverter() { return jsonMessageConverter; } public void setJsonMessageConverter( HttpMessageConverter<ExceptionResultInfo> jsonMessageConverter) { this.jsonMessageConverter = jsonMessageConverter; } }
2、配置
①在springmvc.xml文件中配上json转换器(spring-web jar提供),并注入上面自定义的异常处理器类中,用于异常信息转换为json
<!-- json转换器 --> <bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> </bean> <!-- 统一异常处理类 --> <bean id="handlerExceptionResolver" class="yycg.base.process.exception.ExceptionResolverCustom"> <!-- 注入一个json转换器 --> <property name="jsonMessageConverter" ref="jsonMessageConverter" /> </bean>
②在web.xml中声明屏蔽默认的异常处理器,使自定义的异常处理器生效
<init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc.xml</param-value> </init-param> <!-- 屏蔽springmvc自动注册的异常处理器 --> <init-param> <param-name>detectAllHandlerExceptionResolvers</param-name> <param-value>false</param-value> </init-param>
说明:
1、自定义全局异常处理器,实现HandlerExceptionResolver接口
2、在springmvc.xml配置统一异常处理器。
<!-- json转换器 -->
<bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
</bean>
<!-- 统一异常处理类 -->
<bean id="handlerExceptionResolver"
class="yycg.base.process.exception.ExceptionResolverCustom">
<!-- 注入一个json转换器 -->
<property name="jsonMessageConverter" ref="jsonMessageConverter" />
</bean>
3、在web.xml中配置:
【前端控制器知道全局异常处理器id为handlerExceptionResolver
detectAllHandlerExceptionResolvers:
屏蔽自动注册异常处理器,固定使用bean的id为handlerExceptionResolver的异常处理器。】
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<init-param>
<param-name>detectAllHandlerExceptionResolvers</param-name>
<param-value>false</param-value>
</init-param>