@ControllerAdvice
@ControllerAdvice注解(控制器切面)定义的类,会自动注册为一个Bean对象,将扫描指定包中带
@Controller注解的类:在客户端发起请求,映射到控制器方法时,结合其他注解或接口完成统一的功 能。
注:可以不指定扫描的包,对容器中所有@Controller生效
应用一:统一异常处理
@ControllerAdvice
public class ExceptionAdvice {
//自定义异常报错错误码和错误消息
@ExceptionHandler(AppException.class)
@ResponseBody
public Object handle1(AppException e){
JSONResponse json = new JSONResponse();
json.setCode(e.getCode());
json.setMessage(e.getMessage());
// log.debug(transfer(e));
log.debug(“自定义异常”, e);
return json;
}
}
@GetMapping("/ex")
public Object ex(Integer i){//模拟用户登录出错的问题
if(i==1){//用户名密码不通过
throw new AppException(“LOG001”, “用户名或密码错误”);
}else{//模拟登录成功,但自己写代码有bug,出现运行时异常
int x = i/0;
}
Map<String, Object> map = new HashMap<>();
map.put(“ok”, true);
return map;
}
此时在登录以后,访问 /api/exception 接口将会报错,抛出的异常属于Exception类,所以会进入 @ExceptionHandler注解的方法
应用二:响应数据格式的统一封装
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
/**
* 执行完Controller的请求映射方法,如果是有响应体内容,可以在写入http协议响应体
* 之前,重写
* body 请求映射方法返回值
* response SpringMVC封装的响应类
*返回的响应体内容:一般的做法,请求映射返回Object,可以改为其他对象
* 返回String,使用json序列化
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//如果请求映射方法返回统一响应格式,就不需要再次包裹
if(body instanceof JSONResponse)
return body;
//包裹为统一的响应格式
JSONResponse json = new JSONResponse();
json.setSuccess(true);
json.setData(body);
//如果是String,需要序列化
if(body instanceof String){
try {
return objectMapper.writeValueAsString(json);
} catch (JsonProcessingException e) {
throw new RuntimeException("json序列化出错:"+json);
}
}
return json;
}
}
关于异常:
出现异常时,代码执行顺序
如何抛出一个异常?手动抛异常(自定义异常),代码bug抛异常
如何处理异常?框架封装try catch,需要使用统一处理异常方案
如何根据异常找到出现异常的代码行,调试代码
根据堆栈信息,查找在哪一个类,哪个方法跑出的
分析try catch,分析具体的问题代码