前言
在实际项目中,程序往往会出现各种各样的异常。而针对这些异常,如果我们不做处理,直接抛出到页面的话,不仅不友好,而且会给一些别有用心的人制造空当。所以,处理这些异常信息显然是十分必要的。
异常处理
在笔者以往的开发经验中,程序中针对异常的处理,往往采取这种方式
public Map test(){
Map<String,String> result = new HashMap<>();
try {
//业务代码
result.put("code","200");
result.put("msg","请求成功");
} catch (Exception e){
logger.error("请求失败",e.getLocalizedMessage(),e);
result.put("code","500");
result.put("msg","请求失败");
}
return result;
}
这样写,虽然没问题,也是处理异常的一种方式,但看上去一点也不优雅。这里捕获的是Exception,并没有针对其子异常去做特殊处理。假如我们需要处理更多异常的返回信息的话,这里就需要写更多的catch
块,显然一点也不优雅。
那么,在Spring Boot中如何处理这诸多的异常呢?下面笔者将带着大家一起来了解Spring Boot中的异常处理方式。
@ControllerAdvice 和 @RestControllerAdvice
在Spring 3.2以后,新增了一个注解**@ControllerAdvice**。在该注解标识的类下,我们不仅对请求数据做处理,同时,也可以通过在方法上标识**@ExceptionHandler**的注解,来针对某个或某几个异常进行处理。
而在Spring 4.2以后,新增的**@RestControllerAdvice注解,则在原来@ControllerAdvice**的基础上做了进一步的加强。
编码
讲到这,相信读者朋友对我接下来的处理异常方式,心中已经有了大概的答案了吧。没错,笔者采用的就是**@ControllerAdvice加上@ExceptionHandler**的方式来处理异常。
-
新建GlobalExceptionHandler.java,用来处理控制层抛出的异常
package com.boot.demo.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.request.WebRequest; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 处理异常 * @param ex * @return */ @ExceptionHandler(Exception.class) public Map exceptionHandler(Exception ex){ logger.error("请求失败",ex.getLocalizedMessage(),ex); Map<String,Object> result = new HashMap<>(); result.put("code",500); result.put("msg","请求失败"); return result; } }
-
为了进一步处理Spring中抛出的异常,我们需要对GlobalExceptionHandler.java作出一点改变
package com.boot.demo.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 处理异常 * @param ex * @return */ @ExceptionHandler(Exception.class) public Map exceptionHandler(Exception ex){ logger.error("请求失败",ex.getLocalizedMessage(),ex); Map<String,Object> result = new HashMap<>(); result.put("code",500); result.put("msg","请求失败"); return result; } /** * 处理Spring内部异常 * @param ex * @param body * @param headers * @param status * @param request * @return */ protected ResponseEntity<Object> handleExceptionInternal( Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { logger.info("服务器端响应失败,status : {},ex : {}",status.getReasonPhrase(),ex); Map<String,Object> result = new HashMap<>(); result.put("code",status.value()); result.put("msg",ex.getLocalizedMessage()); return new ResponseEntity<>(result,HttpStatus.OK); } }
到这里,处理异常的逻辑就写完了,下面我们新建一个Controller,用于测试吧。
TestController.java
package com.boot.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class TestController {
private static final Logger logger = LoggerFactory.getLogger(TestController.class);
@RequestMapping("test")
public Map test(){
Map<String,String> result = new HashMap<>();
try {
//业务代码
result.put("code","200");
result.put("msg","请求成功");
} catch (Exception e){
logger.error("请求失败",e.getLocalizedMessage(),e);
result.put("code","500");
result.put("msg","请求失败");
}
return result;
}
@RequestMapping("test2")
public Map test2(){
Map<String,String> result = new HashMap<>();
int i = 10 / 0;
result.put("code","200");
result.put("msg","请求成功");
return result;
}
}
测试
启动项目,访问http://localhost:8080/test2,返回内容如下