使用@ControllerAdvice 定义 全局异常处理

package com.app;

import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException; /**
* ContorllerAdvice 最常见的使用场景是全局异常处理
* 一般搭配 @ExceptionHandler @ModelAttribute 以及 @InitBinder 使用
* 如下是, 当单个文件超出最大size时 对应的自定义处理方法
*
* <p>By default the methods in an {@code @ControllerAdvice} apply globally to
* all Controllers.
*
* spring:
servlet:
multipart:
max-file-size: 50KB
*
*/
@ControllerAdvice
public class CustomExceptionHandler { @ExceptionHandler(MaxUploadSizeExceededException.class)
public void uploadException(MaxUploadSizeExceededException e, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("文件大小超出限制!");
out.flush();
out.close();
}
}

当需要将自定义结果写入Response时,有更好的选择:ResponseEntityExceptionHandler( 作为 @ControllerAdvice的基类)

Open Declaration org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler

A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods. 

This base class provides an @ExceptionHandler method for handling internal Spring MVC exceptions. This method returns a ResponseEntity for writing to the response with a message converter, in contrast to DefaultHandlerExceptionResolver which returns a ModelAndView. 

If there is no need to write error content to the response body, or when using view resolution (e.g., via ContentNegotiatingViewResolver), then DefaultHandlerExceptionResolver is good enough. 

如下,在Service中抛出 Exception

package com.app.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.app.dao.CityRepository;
import com.app.exceptions.CityNotFoundException;
import com.app.exceptions.NoDataFoundException;
import com.app.model.City; import java.util.List; @Service
public class CityService implements ICityService { @Autowired
private CityRepository cityRepository; @Override
public City findById(Long id) { return cityRepository.findById(id)
.orElseThrow(() -> new CityNotFoundException(id));
} @Override
public City save(City city) { return cityRepository.save(city);
} @Override
public List<City> findAll() { List<City> cities = (List<City>) cityRepository.findAll(); if (cities.isEmpty()) { throw new NoDataFoundException();
} return cities;
} }

并使用ControllerAdvice 标注的类做全局处理:(使用ResponseEntity 返回定制信息以及HttpStatus Code)

package com.app.exceptions;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; @ControllerAdvice
public class ControllerAdvisor extends ResponseEntityExceptionHandler { @ExceptionHandler(CityNotFoundException.class)
public ResponseEntity<Object> handleCityNotFoundException(
CityNotFoundException ex, WebRequest request) { Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("message", "City not found"); return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
} @ExceptionHandler(NoDataFoundException.class)
public ResponseEntity<Object> handleNodataFoundException(
NoDataFoundException ex, WebRequest request) { Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("message", "No cities data found"); return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
} @Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) { Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDate.now());
body.put("status", status.value()); List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(x -> x.getField() + x.getDefaultMessage())
.collect(Collectors.toList()); body.put("errors", errors); return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}
}

准备测试数据方法1:

使用MyRunner

package com.app;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component; import com.app.dao.CityRepository;
import com.app.model.City; @Component
public class MyRunner implements CommandLineRunner { private static final Logger logger = LoggerFactory.getLogger(MyRunner.class); @Autowired
private CityRepository cityRepository; @Override
public void run(String... args) throws Exception { logger.info("Saving cities"); cityRepository.save(new City("Bratislava", 432000));
cityRepository.save(new City("Budapest", 1759000));
cityRepository.save(new City("Prague", 1280000));
cityRepository.save(new City("Warsaw", 1748000));
cityRepository.save(new City("Los Angeles", 3971000));
cityRepository.save(new City("New York", 8550000));
cityRepository.save(new City("Edinburgh", 464000));
cityRepository.save(new City("Suzhou", 4327066));
cityRepository.save(new City("Zhengzhou", 4122087));
cityRepository.save(new City("Berlin", 3671000));
}
}

MyRunner 类会在项目启动之后执行:

准备测试数据方法2:

在src/main/resource 下 create 一个 data.sql ,如下:

INSERT INTO cities(name, population) values('Hello',100);
INSERT INTO cities(name, population) values('World',200);

发生异常时的返回值:

Reference:http://zetcode.com/springboot/controlleradvice/

Code: https://github.com/XLuffyStory/SpringBootStudy/tree/master/springboot-controlleradvice

@ControllerAdvice 全局异常处理的更多相关文章

  1. @ControllerAdvice全局异常处理不起作用原因及解决办法

    这段时间使用springboot搭建基础框架,作为springboot新手,各种问题都有. 当把前端框架搭建进来时,针对所有controller层的请求,所发生的异常,需要有一个统一的异常处理,然后返 ...

  2. 014-Spring Boot web【三】拦截器HandlerInterceptor、异常处理页面,全局异常处理ControllerAdvice

    一.拦截器HandlerInterceptor 1.1.HandlerInterceptor接口说明 preHandle,congtroller执行前,如果返回false请求终端 postHandle ...

  3. Spring中通过java的@Valid注解和@ControllerAdvice实现全局异常处理。

    通过java原生的@Valid注解和spring的@ControllerAdvice和@ExceptionHandler实现全局异常处理的方法: controller中加入@Valid注解: @Req ...

  4. springmvc全局异常处理ControllerAdvice区分返回响应类型是页面还是JSON

    思路: 加一个拦截器,在preHandler中取得HandlerMethod,判断其方法的返回类型,以及方法的注解和类的注解. 如果返回是json,收到异常则返回默认的异常包装类型. 如果返回是页面, ...

  5. 《Spring全局异常处理》从零掌握@ControllerAdvice注解

    一.开门见山 在前后端分离框架的大趋势下,前后端基本的职责已经确定. 前端主要负责界面的处理以及基本的判空检验.数据来源则通过vue调用后端发布的接口. 后端的原型还是mvc的模式: controll ...

  6. Spring Boot 全局异常处理

    Spring Boot版本 1.5 @ControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExcept ...

  7. SpringBoot整合全局异常处理&SpringBoot整合定时任务Task&SpringBoot整合异步任务

    ============整合全局异常=========== 1.整合web访问的全局异常 如果不做全局异常处理直接访问如果报错,页面会报错500错误,对于界面的显示非常不友好,因此需要做处理. 全局异 ...

  8. Spring 全局异常处理

    [参考文章]:Spring全局异常处理的三种方式 [参考文章]:Spring Boot 系列(八)@ControllerAdvice 拦截异常并统一处理 [参考文章]:@ControllerAdvic ...

  9. springBoot注解大全JPA注解springMVC相关注解全局异常处理

    https://www.cnblogs.com/tanwei81/p/6814022.html 一.注解(annotations)列表 @SpringBootApplication:包含了@Compo ...

随机推荐

  1. Codeforces 1221B. Knights

    传送门 看到棋盘上跳马,发现如果把棋盘黑白染色,那么每次移动都是从白点到黑点,从黑点到白点 所以直接根据黑白染色判断每个位置的马的颜色即可 #include<iostream> #incl ...

  2. VMware Ubuntu18.04 安装及配置笔记

    安装Ubuntu 下载虚拟机VMware 下载镜像Ubuntu 过程略, 参考 https://zhuanlan.zhihu.com/p/38797088 Ubuntu配置 特别提示: 在Ubuntu ...

  3. Python应用RabbitMQ教程

    介绍 RabbitMQ是一个消息代理.它的工作就是接收和转发消息.你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处.在这个比喻中,RabbitMQ就扮演着邮箱.邮局以及邮 ...

  4. Intellij idea启动项目提示"ClassNotFoundException"

    引用至Intellij IDEA 启动项目ClassNotFoundException 使用Intellij IDEA的过程中,新创建的项目启动时报 严重: Error configuring app ...

  5. BASH的保护性编程技巧

    BASH的保护性编程技巧   shell常用逻辑判断 -b file 若文件存在且是一个块特殊文件,则为真 -c file 若文件存在且是一个字符特殊文件,则为真 -d file 若文件存在且是一个目 ...

  6. PHP 下载mysql数据到PHPExcel表格

    第一步:先到官网(https://github.com/PHPOffice/PHPExcel)下载PHPExcel 第二步:放到第三方库 第三步: /** * 封装:信息导出 * @param $da ...

  7. CF407D Largest Submatrix 3

    cf luogu 被自己菜到自闭了/kk 既然是子矩阵,那么惯用套路为枚举矩阵上下边界,然后\(O(n)\)扫描求解.这题里要从左往右枚举右端点,然后看左端点最多能放到哪,那就对于每个数求出在上下边界 ...

  8. LeetCode——等差数列划分

    题目: 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如,以下数列为等差数列: 1, 3, 5, 7, 97, 7, 7, 73, -1, -5, -9 以下数列 ...

  9. Android系统分析之Audio音频流, 音频策略, 输出设备之间的关系

    音频流, 音频策略, 输出设备之间的关系 只针对 AudioManager.STREAM_VOICE_CALL 音频流类型进行分析 涉及到的类: hardware/libhardware_legacy ...

  10. IT技术网站博客推荐

    CSDN 全球最大中文IT社区,为IT专业技术人员提供最全面的信息传播和服务平台. 51CTO 技术成就梦想 - 中国领先的IT技术网站 itEye Java编程 Spring框架 Ajax技术 ag ...