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

编程教程 > Java (2048) 2025-01-27 10:07:57

           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.xqlee.business.response.Result;
import com.xqlee.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.xqlee.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;
		}
	}
}

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
Spring boot/mvc项目中通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler
Spring Boot中的拦截器和过滤器都是用于在请求到达控制器之前或之后对请求进行处理的。区别如下:拦截器是基于Java的反射机制,而过滤器是基于函数回调。拦截器只能对Spring MVC的请...
@RestControllerAdvice/@ControllerAdvice不生效、没起作用解决正常情况下,通过@RestControllerAdvice/@
Spring boot 全局异常捕捉,spring boot,java
Java编程中spring boot项目动态添加拦截器Interceptor
参考文章 ThreadLocal在线程池中被串用_threadlocal串数据-CSDN博客流程示意参考文章是过滤器Filter,我这里的情况差不多,拦截器,也
前言引用之前的例子《Vert.x 4 Web REST CRUD接口应用》项目作为基础进行修改,创建一个自定义异常和异常拦截处理器。以实现对指定异常返回特殊数据
Spring Boot 入门 AOP 日志处理,这里主要讲解spring boot 中采用AOP方式进行日志的统一处理。spring 框架的处理也是一样。综合来讲,本文主要讲解了spring b...
前言在使用SpringBoot做项目时,需要使用拦截器判断用户是否登陆,来决定用户是否能访问某些页面。起初,通过继承来WebMvcConfigurerAdapt
Spring Boot 1.x升级到Spring Boot 2.0迁移指南
项目源码下载:(访问密码:9987)Spring-Cloud-Circuit-Breaker.zip学习在调用底层微服务的同时利用调用的Spring Cloud Netflix堆栈组件之一Hys...
Java编程之Spring Boot 文件上传 REST风格API ajax方式
使用Spring Batch decorators对数据进行分类以写入多个目的地。当您在企业架构中工作以将数据传递/共享到多个系统时,这是非常方便的。Spring批处理中的装饰器是什么2.1。什...
mybatis Interceptor拦截器实现自定义扩展查询兼容mybatis plus @Intercepts({ @Signature(type = Executor.c...