使用@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. QuickSort(快排)的JAVA实现

    QuickSort的JAVA实现 这是一篇算法课程的复习笔记 用JAVA对快排又实现了一遍. 先实现的是那个easy版的,每次选的排序轴都是数组的最后一个: package com.algorithm ...

  2. 【lucene】一个简单的招聘网站的建立

    1.建立索引库: 核心代码如下 package com.tabchanj.job.index; import java.util.ArrayList; import java.util.HashMap ...

  3. 第一篇 HTML 认识HTML

    认识HTML 学习一门语言,我们要先了解它,可以不用太资深,但要做到别人问,你能回答得出来! 注:推荐大家去网址:www.w3school.com.cn 前端学习手册(免费的) HTML(超文本标记语 ...

  4. java复制文件范例代码

    String url1 = "F:\\SuperMap-Projects\\region.udb";// 源文件路径 try { for(int i=1;i<101;i++) ...

  5. python删除数组中元素

    有数组a,要求去掉a所有为0的元素 a = [2,4,0,8,9,10,100,0,9,7] Filter a= filter(None, a) Lambada a = filter(lambda x ...

  6. WebAPI跨域问题处理

    1.按照https://dzone.com/articles/access-control-allow-origin-header-and-the-aspnet文章所述,在程序中配置允许跨域请求. 但 ...

  7. Docker架构及其三要素

    1.Docker架构 a.Docker客户端和服务端   Docker是客户-服务器(C/S)架构的程序.Docker客户端只需向Docker服务器或守护进程发出请求,服务器或守护进程将完成所有工作并 ...

  8. Delphi 指针类型

  9. 个人总结的J2EE目前知道的涵盖面,从大方向入手,多写单元测试,加强基础

    JEE Development process: java SE 普通语法,,异常处理,数据结构,循环,面向对象,泛型, 属性,反射,多线程,线程池,锁, lambada,异步编程,并发 框架spri ...

  10. python 教程(一)

    必须感慨一下,整了一周多的时间才基本理通顺.自己老是不能静心,方法也不对所以走了很多弯路. 1.建议:一定要先去看官方文档. 下面我们来看一周的成果吧: windows下如何下载并安装Python 3 ...