使用@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. 搭建集群版Eureka Server

    注册中心作为微服务架构中的核心功能,其重要性不言而喻.所以单机版的Eureka Server在可靠性上并不符合现在的互联网开发环境.集群版的Eureka Server才是商业开发中的选择. Eurek ...

  2. CSP/NOIP 2019 游记

    Day0 打牌 Day1 \(T1\) 没开\(ull\), 不知道有几分 \(T2\) \(N^2\)暴力+链, 没搞出树上做法, \(70\)分 \(T3\) 标准\(10\)分( 感觉今年省一稳 ...

  3. Adam作者大革新, 联合Hinton等人推出全新优化方法Lookahead

    Adam作者大革新, 联合Hinton等人推出全新优化方法Lookahead   参与:思源.路.泽南 快来试试 Lookahead 最优化方法啊,调参少.收敛好.速度还快,大牛用了都说好. 最优化方 ...

  4. Nginx负载均衡调度算法

    Nginx支持的负载均衡调度算法方式如下: 1. weight轮询(默认) 接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,nginx会自动将该服务器剔除出队列 ...

  5. JS基础_数据类型-Null类型和Undefined类型

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. less 经典范例 bootstrap 的 less 版本 常用 less 代码

    1. bootstrap 的 less 版本 2.less 文件分布 /*! * Bootstrap v3.3.7 (http://getbootstrap.com) * Copyright 2011 ...

  7. php不重新编译,添加模块

    本文已安装mysqli模块为例 一:检查 1:首先保证php-fpm能正常启动 2:查看当前已安装的php模块是否有mysqli [root@oldboyedu ~]# /application/ph ...

  8. matplotlib:python数据处理三剑客之一

    1.基本使用 import numpy as np import matplotlib.pyplot as plt import pandas as pd # 生成一系列x x = np.linspa ...

  9. zencart模板列表下载地址

    下载index.html文件后用浏览器打开,里面有一百多个zencart模板示例 下载地址:zencart模板示例下载地址 或者复制下面网址,用浏览器打开即可下载: http://bcs.duapp. ...

  10. 【HDU6635】Nonsense Time

    题目大意:给定一个长度为 N 的序列,开始时所有的位置都不可用,每经过一个时间单位,都会有一个位置被激活.现给定激活顺序的序列,求每次激活之后全局的最长上升子序列的长度,保证数据随机. 题解: 引理: ...