全局异常处理
全局异常配置中一个重要注解
| @ControllerAdvice | org.springframework.web.bind.annotation.ControllerAdvice |
|---|
@ControllerAdvice
public class ClobalExceptionAdvice {
/**
* 全局异常处理
*
* @param e the e
* @return the object
* @author 路西法98
* @since 2022年9月28日
*/
//可以写自定义的业务异常
@ExceptionHandler(Exception.class) //可以捕获的异常类型
@ResponseBody //本次的处理是基于rest风格完成的
public Object exceptionHandler(Exception e) { //实现所有的异常处理
Map<String,Object> map = new HashMap<>(); //保存响应信息
map.put("message",e.getMessage()); //直接获取异常信息
map.put("status", HttpServletResponse.SC_INTERNAL_SERVER_ERROR); //设置一个HTTP状态码
map.put("exception",e.getClass().getName()); //设置异常类型
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
map.put("path",request.getRequestURI()); //异常发生的路径
return map;
}
@RestController //基于Rest架构进行处理,省略了@ResponseBody
@RequestMapping("/test/*") //父路径
public class TestExceptionAction extends AbstractBaseAction { //控制层的实现类
@RequestMapping("testException")
public Object action() {
return 9 / 0;
}
}
程序执行路径:localhost/test/testException
程序执行结果:
{
"exception": "java.lang.ArithmeticException",
"path": "/test/testException",
"message:" "/by zero",
"status": 500
}
此时出现异常之后已经可以实现正确的信息展示,同时在展示的时候直接告诉用户具体产生异常的路径(私用),以及具体的异常类型,这个时候可以称为是一个完整的异常处理操作。
全局数据绑定
采用前后端分离技术时,需要考虑数据最终返回结构,因为除了所需要真正响应的数据之外,有可能还会附加又一些其他的辅助性数据,例如,每次都要返回一个HTTP状态码,或者是一些SessionID、认证数据等,在这样的情况下,如果每一次进行响应的时候都重复的编写,则会非常繁琐
MessageConfig .java
@Configuration
public class MessageConfig {
@Bean
public Message getMessege() {
Message message = new Message();
message.setTitle("路西法的结局");
message.setContent("与克洛伊幸福度过余生");
return Message;
}
}
GlobalDataBindAdvice .java
@ControllerAdvice
public class GlobalDataBindAdvice { //全局数据绑定
@Autowired
private Message message; //注入Message对象实例
@ModelAttribute(name = "bindModel")
public Object dataBind() {
Map<String,Object> map = new HashMap<>(); //绑定一个Map集合
map.put("title","test " + this.message.getTitle);
map.put("content","test " + this.message.getContent());
}
}
GlobalDataAction.java
@RestController //基于Rest架构进行处理,省略了@ResponseBody注解
@RequestMapping("/data/*") //父路径
public class GlobalDataAction extends AbstractBaseAction {
@RequestMapping("testMethod1")
public Object testMethod1(String message, Model model) {
Map<String, Object> map = (Map<String, Object>) model.asMap().get("bindModel"); //获取绑定的Map集合
map.put("data",message);
return map; //通过Map返回数据
}
@RequestMapping("testMethod2")
public Object testMethod2(int x, int y, Model model) {
Map<String, Object> map = (Map<String, Object>) model.asMap().get("bindModel"); 获取绑定的Map集合
map.put("data", x/y);
return map;
}
}
访问GlobalDataAction.testMethod1()方法
localhost/data/testMethod1?message=今天星期四
程序执行结果:
{
"data": "今天星期四",
"title": "路西法的结局",
"content": "与克洛伊幸福度过余生"
}
访问GlobalDataAction.testMethod2()方法
localhost/data/testMethod2?x=10&y=5
程序执行结果:
{
"data": 2,
"title": "路西法的结局",
"content": "与克洛伊幸福度过余生"
}
全局数据预处理
使用SpringMVC开发时,可以自动的将接收的参数转为VO对象的属性内容,如果有两个不同的类,类中有两个相同的属性,并且,这两个类的对象还需要接收
eg
Company.java
@Data
public class Company {
private Long cid;
private String name;
}
Dept.java
@Data
public class Dept {
private Long deptno;
private String name;
}
DeptAction.java
@RestController
@RequestMapping("/dept/*")
public class DeptAction {
@RequestMapping("add"
public Object add(Company company, Dept dept) {
Map<String, Object> map = new HashMap<>();
map.put("dept", dept);
map.put("company", company);
return map;
}
}
通过浏览器访问当前的执行路径:
localhost/dept/add?cid=10&name=路西法&deptno=999&name=地狱管理部
程序执行结果:
{
"company": {
"cid": 10,
"name": "路西法,地狱管理部"
},
"dept": {
"deptno": 999,
"name": "路西法,地狱管理部"
}
}
最终执行结果的name跟预期的有差别
如果想要解决请求参数准确设置的问题,必须采用一种全局预处理的方式进行代码的配置,这种方式相当于设置一些前缀
GlobalDataPreparementAdvice .java
@ControllerAdvice
public class GlobalDataPreparementAdvice { //全局数据预处理
@InitBinder("company")
public void company(WebDataBinder binder) {
binder.setFieldDefaultPrefix("company."); //参数前缀
}
@InitBinder("dept")
public void dept(WebDataBinder binder) {
binder.setFieldDefaultPrefix("dept."); //参数前缀
}
}
DeptAction.java
@RestController
@RequestMapping("/dept/*")
public class DeptAction {
@RequestMapping("add")
public Object add(@ModelAttribute("company") Company company,
@ModelAttribute("dept") Dept dept) {
Map<String, Object> map = new HashMap<>();
map.put("dept", dept);
map.put("company", company);
return map;
}
}
准备完成之后进行请求路径的设置,路径对于同名的参数要加入前缀
localhost/dept/add?cid=10&company.name=路西法&deptno=999&dept.name=地狱管理部
程序执行结果:
{
"company": {
"cid": 10,
"name": "路西法"
},
"dept": {
"deptno": 999,
"name": "地狱管理部"
}
}