@RestControllerAdvice或者@ControllerAdvice实现全局异常统一处理

位置:首页>文章>详情   分类: 教程分享 > Java教程   阅读(1165)   2023-03-28 11:29:14
           Spring boot/mvc项目中通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理。

       在spring web项目开发中,我们经常会遇到各种exception,这些exception根据业务或者场景不同抛出不同的信息和返回类型,有的exception需要返回json数据格式的错误,有的exception又需要跳转到某个错误页面。这里将会讲解常见的几个exception统一处理。


通过注解@RestControllerAdvice统一处理rest接口的异常信息。

注意@RestControllerAdvice注解一般在spring boot接口项目中使用。spring普通项目也支持不过需要高版本的spring才有@RestControllerAdvice注解标签。

Java代码:
import com.leftso.business.response.Result;
import com.leftso.system.exception.BusinessException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class RestExceptionHandler {

    @ExceptionHandler(value = { BusinessException.class })
    public Result business(BusinessException ex) {
        return Result.fail("业务异常:"+ex.getMessage());
    }

    @ExceptionHandler(value = { MethodArgumentNotValidException.class })
    public Result methodArgumentNotValidException(MethodArgumentNotValidException ex) {
        String field=ex.getBindingResult().getFieldError().getField().replace("parameter.","");
        String message=ex.getBindingResult().getFieldError().getDefaultMessage();
        return Result.fail("验证失败:字段["+field+"]"+message);
    }

    @ExceptionHandler(value = { Exception.class })
    public Result exception(Exception ex) {
        return Result.fail("系统异常:"+ex.getMessage());
    }
}

通过注解@ControllerAdvice统一处理异常

import com.leftso.common.http.result.ResultJson;
import org.springframework.http.HttpStatus;
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.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = {BusinessException.class})
    @ResponseBody
    public ResultJson business(BusinessException ex) {
        return ResultJson.fail("业务异常:" + ex.getMessage());
    }


    @ExceptionHandler(value = {Exception.class})
    public ModelAndView exception(Exception ex, HttpServletRequest request, HttpServletResponse response) {
        String uri = request.getRequestURI();
        ModelAndView modelAndView = new ModelAndView();
        if (uri.contains("enterprise")) {
            MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
            modelAndView.setView(jsonView);
            modelAndView.addObject(ResultJson.fail("系统异常:" + ex.getMessage()));
            return modelAndView;
        } else {
            RedirectView redirectView = new RedirectView("/static/error/500.jsp");
            redirectView.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            modelAndView.setView(redirectView);
            return modelAndView;
        }
    }
}

某些情况我们需要根据请求类型返回不同得view,比如ajax请求返回JSON数据,普通请求返回页面数据,
 
import com.alibaba.fastjson.JSON;
import net.ifok.common.utils.MapUtil;
import net.ifok.ocms.system.exception.BusinessException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
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.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.AccessDeniedException;
import java.util.List;

@ControllerAdvice
public class ControllerExceptionHandler {

	/**
	 * 业务异常
	 * 
	 * @param
	 * @param e
	 * @return
	 * @throws IntrospectionException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 */
	@ResponseBody
	@ExceptionHandler(value = { BusinessException.class ,RuntimeException.class})
	public ModelAndView businessExceptionHandler(HttpServletRequest request, BusinessException e)
			throws IllegalAccessException, InvocationTargetException, IntrospectionException {
		Log.error("业务异常:" + e.getMessage(),e, getClass());
		String uri = request.getRequestURI();
		boolean isJsonRequest =isAjaxRequest(request);
		if (isJsonRequest) {
			ModelAndView view = new ModelAndView();
			MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
			jsonView.setAttributesMap(MapUtil.toMap(Result.fail(e.getMessage())));
			view.setView(jsonView);
			return view;
		} else {
			ModelAndView view = new ModelAndView();
			view.setViewName("redirect:/503.html");
			return view;
		}
	}

	@ExceptionHandler(value = { MethodArgumentNotValidException.class})
	public ModelAndView methodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e){
		String message=e.getBindingResult().getFieldError().getDefaultMessage();
		Log.error("验证失败:" +message,e, getClass());
		boolean isJsonRequest =isAjaxRequest(request);
		if (isJsonRequest) {
			ModelAndView view = new ModelAndView();
			MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
			jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail(message))));
			view.setView(jsonView);
			return view;
		} else {
			ModelAndView view = new ModelAndView();
			view.setViewName("redirect:/503.html");
			return view;
		}
	}


	@ExceptionHandler(value = { HttpRequestMethodNotSupportedException.class })
	public ModelAndView methodNotSupportedException(HttpServletRequest request, HttpRequestMethodNotSupportedException e){
		Log.error("HttpRequestMethodNotSupportedException:请求方法不支持:"+e.getMethod()+"\n请求地址:"
				+request.getRequestURI()+"\n UA:\n" + request.getHeader("User-Agent"),getClass());
		boolean isJsonRequest =isAjaxRequest(request);
		if (isJsonRequest) {
			ModelAndView view = new ModelAndView();
			MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
			jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail("请求方式["+e.getMethod()+"]不支持"))));
			view.setView(jsonView);
			return view;
		} else {
			ModelAndView view = new ModelAndView();
			view.setViewName("redirect:/404.html");
			return view;
		}
	}




	@ExceptionHandler(value = { AccessDeniedException.class })
	public ModelAndView accessDeniedException(HttpServletRequest request, AccessDeniedException e) {
		Log.error("权限不足->\n资源地址:" + request.getRequestURI() + "\n UA:\n" + request.getHeader("User-Agent"),
				this.getClass());
		boolean isJsonRequest=isAjaxRequest(request);
		if (isJsonRequest) {
			ModelAndView view = new ModelAndView();
			MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
			jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail(e.getMessage()))));
			view.setView(jsonView);
			return view;
		} else {
			ModelAndView view = new ModelAndView();
			view.setViewName("redirect:/403.html");
			return view;
		}
	}

	@ExceptionHandler(value = { Exception.class })
	public ModelAndView exceptionHandler(HttpServletRequest reqeust, Exception e) {
		Log.error(e.getMessage(), e, getClass());
		boolean isJsonRequest =isAjaxRequest(reqeust);
		if (isJsonRequest) {
			ModelAndView view = new ModelAndView();
			MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
			jsonView.setAttributesMap(JSON.parseObject(JSON.toJSONString(Result.fail(e.getMessage()))));
			view.setView(jsonView);
			return view;
		} else {
			ModelAndView view = new ModelAndView();
			view.setViewName("redirect:/503.html");
			return view;
		}
	}
	public static boolean isAjaxRequest(HttpServletRequest request) {
		String requestedWith = request.getHeader("x-requested-with");
		if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
			return true;
		} else {
			return false;
		}
	}
}
 
地址:https://www.leftso.com/article/428.html

相关阅读

           Spring boot/mvc项目中通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理
@RestControllerAdvice/@ControllerAdvice不生效、没起作用解决
Spring Boot 2.0 Redis整合,通过spring boot 2.0整合Redis作为spring缓存框架的实现。
Spring boot 全局异常捕捉,spring boot,java
Java编程之Spring Boot 文件上传 REST风格API ajax方式
从Spring 6和Spring Boot 3开始,Spring框架支持“HTTP API的问题详细信息”规范RFC 7807。本Spring Boot 教程将详细指导您完成这一新增强。1.问题...
spring boot webflux client实战,webclient是spring webflux的一个小组件。对于Java的http通讯来说,webclient是非常简单易用的。
引言    通过之前spring boot mybatis 整合的讲解: spring boot mybaties整合  (spring boot mybaties 整合 基于Java注解方式写...
1.概要在本Spring boot教程中,我们将学习如何验证发送到PUT/POST API请求的数据BODY
Spring Boot 2.0,Spring框架的Spring Boot 中的Spring Boot Actuator变化讲解。并且了解如何在Spring Boot 2.0中使用Actuator...