1 前言
希望定制错误,比如一般springboot的500错误展示如下(trace等可以通过配置application.yml来决定隐藏还是具有):
application.yml:
server:
port: 8088
path: /hello
error:
include-stacktrace: never
如果不希望使用springboot封装的这种接口调用异常返回,可以个人定制。
tips:springboot热启动
配置依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
快捷键热启动springboot:ctrl+F9
2 定制全局错误返回
package com.xiaoxu.Exception;
import com.google.common.collect.ImmutableMap;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @author xiaoxu
* @date 2022-01-27
* Ymybatis:com.xiaoxu.Exception.excHandler
*/
@ControllerAdvice//该注解其实就类似于一个@Component注解,所以如果自己定制的错误返回希望是一个json形式的,那么就可以加上@ResponseBody注解
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map<String,Object> handleException(HttpServletRequest h, Exception e){
System.out.println("自定义异常:");
e.printStackTrace();
System.out.println("excHandler.defaultExceptionHandler执行结束");
return ImmutableMap.<String,Object>builder().put("code",502).put("msg",e.getMessage()).put("isSuccess",false).build();
}
}
注意:上述异常捕捉类,以及方法名称,均可随便写,主要是要有 @ControllerAdvice注解修饰类 ,
以及 @ExceptionHandler(value = Exception.class)来修饰需要捕捉的异常方法 ,@ControllerAdvice本质上,也是一个@Component注解,所以如果需要捕捉异常后,返回json格式的数据,那么方法加上@ResponseBody注解即可(类似于controller层,加上@Controller修饰类,@ResponseBody修饰请求的方法,返回的就是json格式的数据,两个注解的功能等同于类上加@RestController)。然后因为@ControllerAdvice本质是@Component,所以也是个组件,所以springboot的主程序类(或者说启动类)包扫描必须包含该异常捕捉类的包路径才可:
@SpringBootApplication(scanBasePackages = {"com.xiaoxu"})
修改controller:
package com.xiaoxu.controller;
import com.google.common.collect.ImmutableMap;
import com.xiaoxu.service.YouHTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* @author xiaoxu
* @date 2022-01-24
* Ymybatis:com.xiaoxu.controller.YouHuiQuanController
*/
@RestController
public class YouHuiQuanController {
@Autowired
YouHTypeService youHTypeService;
@PostMapping(value = "/Youh2")
public Map<String,Object> getYouhuiTypesNew2(@RequestParam("type") String resourceType) throws Exception {
if(resourceType.equals("你好")){
throw new Exception("出错了");
}
return ImmutableMap.<String,Object>builder()
.put("1",youHTypeService.getResult(resourceType))
.build();
}
}
package com.xiaoxu.Exception;
/**
* @author xiaoxu
* @date 2022-01-27
* Ymybatis:com.xiaoxu.Exception.TypeIsNotPresentException
*/
public class TypeIsNotPresentException extends RuntimeException{
public TypeIsNotPresentException() {
//调用父类的含有message的构造方法
super("该类型不存在");
}
}
修改全局的异常捕捉类GlobalExceptionHandler:
package com.xiaoxu.Exception;
import com.google.common.collect.ImmutableMap;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @author xiaoxu
* @date 2022-01-27
* Ymybatis:com.xiaoxu.Exception.excHandler
*/
@ControllerAdvice//该注解其实就类似于一个@Component注解,所以如果自己定制的错误返回希望是一个json形式的,那么就可以加上@ResponseBody注解
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map<String,Object> myhandleException(HttpServletRequest h, Exception e){
System.out.println("自定义异常:");
e.printStackTrace();
System.out.println("excHandler.defaultExceptionHandler执行结束");
return ImmutableMap.<String,Object>builder().put("code",502).put("msg",e.getMessage()).put("isSuccess",false).build();
}
@ResponseBody
@ExceptionHandler(TypeIsNotPresentException.class)
public Map<String,Object> typeIsNotPre(TypeIsNotPresentException t){
return ImmutableMap.<String,Object>builder().put("code",503).put("msg",t.getMessage()).put("isSuccess",false).build();
}
}
修改controller层:
package com.xiaoxu.controller;
import com.google.common.collect.ImmutableMap;
import com.xiaoxu.Exception.TypeIsNotPresentException;
import com.xiaoxu.service.YouHTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* @author xiaoxu
* @date 2022-01-24
* Ymybatis:com.xiaoxu.controller.YouHuiQuanController
*/
@RestController
public class YouHuiQuanController {
@Autowired
YouHTypeService youHTypeService;
@PostMapping(value = "/Youh2")
public Map<String,Object> getYouhuiTypesNew2(@RequestParam("type") String resourceType) throws Exception {
if(resourceType.equals("你好")){
// throw new RuntimeException("出错了");
throw new TypeIsNotPresentException();
}
return ImmutableMap.<String,Object>builder()
.put("1",youHTypeService.getResult(resourceType))
.build();
}
}
如果修改controller层抛出RunTimeException,那么调用postman结果如下:
注意:配置依赖时,不要重复配置版本不匹配的webmvc依赖,因为spring-boot-starter-web依赖,已经添加了spring-web和spring-webmvc的依赖,否则执行全局异常捕捉的时候会抛错:
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<parent>
<artifactId>spring-boot-starter-parentartifactId>
<groupId>org.springframework.bootgroupId>
<version>2.5.4version>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
4 总结
(1)全局异常类定义,必须加上@ControllerAdvice注解修饰,相当于@Component注解,会在springboot包扫描路径下找到并注册为一个组件。
(2)全局异常捕捉中,捕捉的异常类型由@ExceptionHandler(value = Exception.class)注解决定,如果个人定义异常能匹配上,那么就优先执行个人定义的异常返回(即便全局异常捕捉中,同时还存在父类异常Exception的捕捉,也不会调它),比如@ExceptionHandler(TypeIsNotPresentException.class);如果是类似RunTimeException、或者Exception等,因为Exception异常类是所有异常类的父类,那么异常返回就会调用到@ExceptionHandler(value = Exception.class)这里。
(3)如果希望异常方法返回的是json格式,那么类似@Controller+@ResponseBody,为方法增加@ResponseBody注解,异常响应就会返回json格式数据了。