系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。主要总结一下SpringMVC中如何统一处理异常。
1.封装统一返回格式:
package cn.com.comit.dataAnalysis.common.utils;
/**
*
* @desciption 返回统一数据格式
* @author ChenXiHua
*
*/
public class ReturnData {
//状态码
private Integer statusCode;
//提示消息
private String message;
//业务数据
private Object data;
public ReturnData(Integer statusCode, String message, Object data) {
super();
this.statusCode = statusCode;
this.message = message;
this.data = data;
}
@Override
public String toString() {
return "ReturnData [statusCode=" + statusCode + ", message=" + message + ", data=" + data + "]";
}
public Integer getStatusCode() {
return statusCode;
}
public void setStatusCode(Integer statusCode) {
this.statusCode = statusCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
2.格式化返回信息:
package cn.com.comit.dataAnalysis.common.utils;
import java.util.HashMap;
import java.util.Map;
/**
*
* @desciption 格式化统一返回数据
* @author ChenXiHua
*
*/
public class ReturnDataFormat {
private static Map<Integer,String>map=new HashMap<Integer,String>(8);
static{
map.put(200,"操作成功!");
map.put(201, "返回数据库数据!");
map.put(202, "返回缓存数据!");
map.put(400, "数据参数绑定错误!");
map.put(401, "无权限!");
map.put(405, "方法请求方式不正确!");
map.put(406, "不接受处理!");
map.put(500, "[服务器]异常!");
map.put(501, "[服务器]运行时异常!");
map.put(502, "[服务器]空指针异常!");
map.put(503, "[服务器]数据类型转换异常!");
map.put(504, "[服务器]IO异常!");
map.put(505, "[服务器]未知方法异常!");
map.put(506, "[服务器]数组越界异常!");
map.put(507, "[服务器]网络异常!");
map.put(508, "[服务器]操作数据库异常!");
map.put(600, "自定义异常!");
}
public static ReturnData returnData(Integer status,Object data){
ReturnData rtData=new ReturnData(status,map.get(status),data);
return rtData;
}
}
3.建立全局异常类:
package cn.com.comit.dataAnalysis.common.exception;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.annotation.HandlesTypes;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.com.comit.dataAnalysis.common.utils.ReturnData;
import cn.com.comit.dataAnalysis.common.utils.ReturnDataFormat;
import cn.com.comit.dataAnalysis.modules.test.utils.ReturnFormat;
import cn.com.comit.dataAnalysis.modules.test.utils.ex3.SysException;
/**
*
* @desciption 全局异常处理类
* @author ChenXiHua
*
*/
@ControllerAdvice
public class GlobalExceptionHandler {
//运行时异常
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public ReturnData runtimeExceptionHandler(RuntimeException ex){
return ReturnDataFormat.returnData(501, null);
}
//空指针异常
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public ReturnData nullPointerExceptionHandler(NullPointerException ex){
return ReturnDataFormat.returnData(502, null);
}
//类型转换异常
@ExceptionHandler(ClassCastException.class)
@ResponseBody
public ReturnData classCastExceptionHandler(ClassCastException ex){
return ReturnDataFormat.returnData(503,null);
}
//IO异常
@ExceptionHandler(IOException.class)
@ResponseBody
public ReturnData ioExceptionHandler(IOException ex){
return ReturnDataFormat.returnData(504, null);
}
//未知方法异常
@ExceptionHandler(NoSuchMethodException.class)
@ResponseBody
public ReturnData noSuchMethodExceptionHandler(NoSuchMethodException ex){
return ReturnDataFormat.returnData(505, null);
}
//数组越界异常
@ExceptionHandler(IndexOutOfBoundsException.class)
@ResponseBody
public ReturnData indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex){
return ReturnDataFormat.returnData(506, null);
}
//数组越界异常
@ExceptionHandler(SQLException.class)
@ResponseBody
public ReturnData sqlExceptionHandler(SQLException ex){
return ReturnDataFormat.returnData(508, null);
}
//400错误
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public ReturnData httpMessageNotReadableExceptionHandler(HttpMessageNotReadableException ex){
return ReturnDataFormat.returnData(400,null);
}
//400错误
@ExceptionHandler(TypeMismatchException.class)
@ResponseBody
public ReturnData typeMismatchExceptionHandler(TypeMismatchException ex){
return ReturnDataFormat.returnData(400,null);
}
//400错误
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public ReturnData missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex){
return ReturnDataFormat.returnData(400,null);
}
//405错误
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseBody
public ReturnData httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex){
return ReturnDataFormat.returnData(405, null);
}
//406c错误
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
@ResponseBody
public ReturnData httpMediaTypeNotAcceptableExceptionHandler(HttpMediaTypeNotAcceptableException ex){
return ReturnDataFormat.returnData(406,null);
}
//500错误
@ExceptionHandler({ConversionNotSupportedException.class,HttpMessageNotWritableException.class})
@ResponseBody
public ReturnData server500(RuntimeException runtimeException){
return ReturnDataFormat.returnData(500,null);
}
//自定义异常
@ExceptionHandler(SysException.class)
@ResponseBody
public ReturnData sysExceptionHandler(SysException ex){
return ReturnDataFormat.returnData(600, null);
}
}
4.在spring-mvc.xml配置文件中加入:
<context:component-scan base-package="cn.com.comit.dataAnalysis.modules.**.controller.impl">
<!-- base-package 如果多个,用“,”分隔 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<!--控制器增强,使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常-->
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>
spring-mvc.xml整体代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<context:component-scan base-package="cn.com.comit.dataAnalysis.modules.**.controller.impl">
<!-- base-package 如果多个,用“,”分隔 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<!--控制器增强,使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常-->
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>
<mvc:default-servlet-handler/>
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters register-defaults="true">
<!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
<property name="writeAcceptCharset" value="false" />
</bean>
<!-- 将Jackson2HttpMessageConverter的默认格式化输出为false -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list><value>application/json;charset=UTF-8</value></list>
</property>
<property name="prettyPrint" value="false"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- REST中根据URL后缀自动判定Content-Type及相应的View -->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="mediaTypes" >
<map>
<entry key="xml" value="application/xml"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="ignoreAcceptHeader" value="true"/>
<property name="favorPathExtension" value="true"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默认编码 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 文件大小最大值 -->
<property name="maxUploadSize" value="10485760000"/>
<!-- 内存中的最大值 -->
<property name="maxInMemorySize" value="40960"/>
</bean>
</beans>
5.测试:
springmvc中控制器controller层请求代码:
method:为get
@GetMapping("/getConfigure")
@ResponseBody
public ReturnData getConfigure(){
return configureService.getConfigure();
}
请求为post时会抛出异常:
使用postman进行测试:
改为get时获取数据正常:
我的座右铭:不会,我可以学;落后,我可以追赶;跌倒,我可以站起来;我一定行。