• @ControllerAdvice


    • 全局异常处理
    • 全局数据绑定
    • 全局数据预处理

    全局异常处理
    全局异常配置中一个重要注解

    @ControllerAdviceorg.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": "地狱管理部"
    	}
    }
    
  • 相关阅读:
    应用计量经济学问题~
    Studio One6.5安装源码教程
    基于php的旅游小型网站
    函数9:生成器和 yield 语句
    mysql一条语句是如何被执行的——带你了解mysql语句执行内部顺序
    LabVIEW 使用VISA Close真的关闭COM口了吗
    20年ICPC澳门站L - Random Permutation
    测试开发【Mock平台】10基础:拦截器实现Mock功能(一)探索HandlerInterceptor
    落单的数字
    Linux负载CPU、内存、磁盘IO、网络IO状态分析详解
  • 原文地址:https://blog.csdn.net/weixin_42594143/article/details/127089927