其实@ControllerAdvice有3个作用:
3.7.1 全局异常处理
就是自定义一个全局异常类,然后通过@ControllerAdvice捕获处理
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
@ControllerAdvice
public class GlobalExceptionHandler {
private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
public static final String SYSTEM_ERROR = "服务器正忙,请稍后再试...";
@ResponseBody
@ExceptionHandler(CustomUnCheckedException.class)
public ResultData handleryException(HttpServletRequest request, CustomUnCheckedException ex){
logger.error("自定义异常:{}",ex);
ResultData
resultData.setResultCode(ex.getCode());
System.out.println(ex.getCode());
resultData.setResultMsg(ex.getMessage());
return resultData;
}
@ResponseBody
@ExceptionHandler(Exception.class)
public ResultData
logger.error("异常:{}",ex);
ResultData
resultData.setResultCode(ResultStateEnum.FAIL.getCode());
resultData.setResultMsg(SYSTEM_ERROR);
return resultData;
}
}
自定义全局异常:
public class CustomUnCheckedException extends RuntimeException implements Serializable {
private static final long serialVersionUID = 2516912856988538515L;
private static final Integer DEFAULT_CODE = 0;// 默认结果码0代表成功
private static final String DEFAULT_OUT_MSG = "成功";
private Integer code;//结果码,省略getter方法
public String getOutMsg() {
if (code.equals(DEFAULT_CODE)) { return getMessage();}
CustomExceptionCodeEnum customExceptionCodeEnum = CustomExceptionCodeEnum.getByCode(code);
if (customExceptionCodeEnum != null) {
return customExceptionCodeEnum.getDesout();
}
return getMessage();
}
public String getInMsg() {
CustomExceptionCodeEnum customExceptionCodeEnum =
CustomExceptionCodeEnum.getByCode(code);
if (customExceptionCodeEnum != null) { return customExceptionCodeEnum.getDesin();}
return getMessage();
}
// 构造器 多种支持
public CustomUnCheckedException() { super();}
public CustomUnCheckedException(Throwable e) { super(e); }
public CustomUnCheckedException(Integer errorCode) { this.code = errorCode; }
public CustomUnCheckedException(CustomExceptionCodeEnum mcode, Throwable e) {
super(mcode.getDesin(), e);
this.code = mcode.getCode();
}
public CustomUnCheckedException(Integer code, Throwable e) {
super(CustomExceptionCodeEnum.getInMsg(code), e);
this.code = code;
}
public CustomUnCheckedException(Integer code, String message) {
super(message); this.code = code;
}
public CustomUnCheckedException(Integer code, String message, Throwable e) {
super(message, e);
this.code = code;
}
}
//错误码
public enum CustomExceptionCodeEnum {
DB_OPERATOR__ERROR_001(1, "数据库操作发生异常", "数据库操作发生异常"),
SYS_NO_REPEAT_OPERATION(2, "SYS_NO_REPEAT_OPERATION", "请勿重复操作!");
private Integer code; /**错误码*/ //省略getter
private String desin; /** 内部描述 */
private String desout; /** 外部描述 */
CustomExceptionCodeEnum(Integer code, String desin, String desout) {
this.code = code; this.desin = desin; this.desout = desout;
}
//通过错误码获取CustomExceptionCodeEnum实例
public static CustomExceptionCodeEnum getByCode(Integer code) {
if (null != code) {
for (CustomExceptionCodeEnum mnum : values()) {
if (mnum.getCode().equals(code)) { return mnum; }
}
}
return null;
}//根据错误码获取内部描述
public static String getInMsg(Integer code) {
if ( null != code ) {
for (CustomExceptionCodeEnum mnum : values()) {
if (mnum.getCode().equals(code)) { return mnum.getDesin();}
}
}
return null;
}//根据错误码获取外部描述
public static String getOutMsg(String code) {
if (code != null && !"".equals(code.trim())) {
for (CustomExceptionCodeEnum mnum : values()) {
if (mnum.getCode().equals(code)) { return mnum.getDesout();}
}
}
return null;
}
}
3.7.2 全局数据绑定
定义需要绑定的数据
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class MyGlobalDataBindHandler {
@ModelAttribute(name="allen") //对应Map的Key
public Map
Map
map.put("age",99);//对应Map的value
map.put("gender","男");//对应Map的value
return map;
}
}
测试类:
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class TestController2 {
@RequestMapping("/test2")
public String test2(Model model){
Map
System.out.println(map);//{allen={gender=男, age=99}}
return "test2";
}
}
3.7.3 全局数据预处理
利用@ControllerAdvice、@InitBinder(“b”)、WebDataBinder、@ModelAttribute("b") 实现拦截并实现数据的预处理
@ControllerAdvice
public class MyGlobalDataPrecessingHandler {
@InitBinder("b")
public void b(WebDataBinder binder){ binder.setFieldDefaultPrefix("b."); }
@InitBinder("a")
public void a(WebDataBinder binder){ binder.setFieldDefaultPrefix("a."); }
}
public class Author {//省略setter&getter&toString方法
private String name; private Integer age;
}
public class Book {//省略setter&getter&toString方法
private String name; private Double price;
}
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
测试类
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController3 {
//http://localhost:18080/add/book?name=allen基于springboot的书&price=100&name=allen&age=28
@RequestMapping("/add/book")
public void addBook(Book book,Author author){
System.out.println(book);//Book{name='allen基于springboot的书,allen', price=100.0}
System.out.println(author);//Author{name='allen基于springboot的书,allen', age=28}
}
//http://localhost:18080/add/book2?b.name=allen基于springboot的书&b.price=100&a.name=allen&a.age=28
@RequestMapping("/add/book2")
public void addBook2(@ModelAttribute("b") Book book, @ModelAttribute("a")Author author){
System.out.println(book);//Book{name='allen基于springboot的书', price=100.0}
System.out.println(author);//Author{name='allen', age=28}
}
}