在spring mvc开发中,当逻辑正常执行时返回客户端指定格式的数据,比如json,但是遇NullPointerException空指针异常,NoSuchMethodException调用的方法不存在异常,返回给客户端的是HTML格式error page,导致客户端不能正常解析数据;这明显不是我们想要的。
从spring3.2开始,增加了新注解@ControllerAdvice,控制器增强的注解。其原理是使用AOP对Controller控制器进行增强(前置增强、后置增强、环绕增强,AOP原理请自行查阅);这样我们就可以自行对控制器的方法进行调用前(前置增强)和调用后(后置增强)的处理。
如果要返回JSON格式,只需要创建一个ExceptionHandler的class 用@ControllerAdvice注解,里面通过@ExceptionHandler来注解了的方法处理数据,处理中将Exception转换为Json格式返回即可。
操作如下:
1.配置applicationContext.xml:
<context:component-scan base-package="com.app.ssm.controller" />
目的是能够扫描到,自定义的@ControllerAdvice注解的ExceptionHandler;
2.编写ExceptionHandler类,参考代码如下,JSONExceptionHandler ,其中@ExceptionHandler(RuntimeException.class)获取相关异常,处理方法为runtimeExceptionHandler(RuntimeException runtimeException),函数内部编写转换json格式内容,@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR),修改返回http状态;@ResponseBody 注解为返回json对象;ErrorResponse为一个POJO对象,返回转换为json数据。
package com.app.ssm.controller;
import java.io.IOException;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
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 org.springframework.web.bind.annotation.ResponseStatus;
import com.app.ssm.common.ErrorCode;
import com.app.ssm.common.ErrorResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* 异常增强,以JSON的形式返回给客服端
* 异常增强类型:NullPointerException,RunTimeException,ClassCastException,
NoSuchMethodException,IOException,IndexOutOfBoundsException
以及springmvc自定义异常等,如下:
SpringMVC自定义异常对应的status code
Exception HTTP Status Code
ConversionNotSupportedException 500 (Internal Server Error)
HttpMessageNotWritableException 500 (Internal Server Error)
HttpMediaTypeNotSupportedException 415 (Unsupported Media Type)
HttpMediaTypeNotAcceptableException 406 (Not Acceptable)
HttpRequestMethodNotSupportedException 405 (Method Not Allowed)
NoSuchRequestHandlingMethodException 404 (Not Found)
TypeMismatchException 400 (Bad Request)
HttpMessageNotReadableException 400 (Bad Request)
MissingServletRequestParameterException 400 (Bad Request)
*
* @author Y.F.Zhang
*
* @Time Feb 21, 2017
*/
@ControllerAdvice
public class JSONExceptionHandler {
/*----- INTERNAL SERVER ERROR -----*/
//运行时异常
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorResponse runtimeExceptionHandler(RuntimeException runtimeException) {
return ErrorResponse.of("SERVER: Runtime Exception", ErrorCode.RUNTIME_EXCEPTION, HttpStatus.INTERNAL_SERVER_ERROR);
}
//空指针异常
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorResponse nullPointerExceptionHandler(NullPointerException ex) {
ex.printStackTrace();
return ErrorResponse.of("SERVER: Null Pointer Exception", ErrorCode.NULL_POINT_EREXCEPTION, HttpStatus.INTERNAL_SERVER_ERROR);
}
/*----- REQUEST ERROR -----*/
//400错误
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorResponse requestNotReadable(HttpMessageNotReadableException ex){
System.out.println("400..requestNotReadable");
ex.printStackTrace();
return ErrorResponse.of("Request Not Readable", ErrorCode.BAD_REQUEST, HttpStatus.BAD_REQUEST);
}
//400错误
@ExceptionHandler({TypeMismatchException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorResponse requestTypeMismatch(TypeMismatchException ex){
System.out.println("400..TypeMismatchException");
ex.printStackTrace();
return ErrorResponse.of("Type Mismatch Exception", ErrorCode.BAD_REQUEST, HttpStatus.BAD_REQUEST);
}
//400错误
@ExceptionHandler({MissingServletRequestParameterException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorResponse requestMissingServletRequest(MissingServletRequestParameterException ex){
System.out.println("400..MissingServletRequest");
ex.printStackTrace();
//return ErrorResponse.of("Missing Servlet Request", ErrorCode.BAD_REQUEST, HttpStatus.BAD_REQUEST);
return ErrorResponse.of(ex.getMessage(), ErrorCode.BAD_REQUEST, HttpStatus.BAD_REQUEST);
}
//405错误
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ResponseBody
public ErrorResponse request405(){
System.out.println("405...");
return ErrorResponse.of("Method Not Allowed", ErrorCode.METHOD_NOT_ALLOWED, HttpStatus.METHOD_NOT_ALLOWED);
}
}