SpringBoot之@ControllerAdvice,@ModelAttribute,@InitBinder详解
@ControllerAdvice
在 SpringBoot 中,@ControllerAdvice 通常结合 @ExceptionHandler 注解处理全局异常,全局异常处理详见第 13 章;通过@ControllerAdvice,我们可以将控制器的全局配置放置在同一个位置,注解了@Controller 的类的方法可使用 @ExceptionHandler、@InitBinder、@ModelAttribute 注解到方法上,这对所有注解了@RequestMapping 的控制器内的方法有效
@ModelAttribute
该注解应用位置包括下面几种:
(1) 应用在方法上
(2) 应用在方法的参数上
(3) 应用在方法上,并且方法也使用了@RequestMapping
2.1 应用在方法上
被 @ModelAttribute 注解的方法会在 Controller 每个方法执行之前都执行,因此对于一个 Controller中包含多个URL的时候,要谨慎使用
@Controller
@RequestMapping("/modelattributeTest")
public class ModelAttributeTestController1 {// 下面的代码也可以放在添加了 @ControllerAdvice 的类中, 那样就会作用于所有的 Controller@ModelAttributepublic void myModel(@RequestParam(required = false) String abc, Model model) {model.addAttribute("attributeName", abc);}@RequestMapping(value = "/test1")public String test1() {return "modelattributetest/test1";}
}
在请求 /modelattributeTest/test1?abc=aaa 后,会先执行 myModel 方法,然后接着执行 test1 方法,参数 abc 的值被放入 Model 中后,接着被带到 test1 方法中;当返回视图 modelattributetest/test1 时,Model 会被带到页面上,当然在使用 @RequestParam 的时候可以使用 required 来指定参数是否是必须的;如果把 myModel 和 test1 合二为一后的方法也可以,这是我们最常用的方法
@RequestMapping(value = "/test2")
public String test1(@RequestParam(required = false) String abc, Model model) {model.addAttribute("attributeName", abc);return "modelattributetest/test1";
}
此外,使用 @ModelAttribute 注解带有返回值的方法如下
// 方法一
@ModelAttribute
public String myModel(@RequestParam(required = false) String abc) {return abc;
}
// 方法二
@ModelAttribute
public Student myModel(@RequestParam(required = false) String abc) {Student stu = new Student(abc);return stu;
}
// 方法三
@ModelAttribute
public int myModel(@RequestParam(required = false) int number) {return number;
}
这种情况,返回值对象会被默认放到隐含的 Model 中,在 Model 中的 key 为返回值类型(首字母小写),value 为返回的值;那么对应上面三个方法和下面这三个写法等价
model.addAttribute("string", abc);
model.addAttribute("student", stu);
model.addAttribute("int", number);
自定义 key,只需要给 @ModelAttribute 添加 value 属性即可,如下所示;相当于 model.addAttribute(“num”, number);
@ModelAttribute(value = "num")
public int myModel(@RequestParam(required = false) int number) { return number;
}
2.2 使用 @ModelAttribute 注解方法的参数
@ModelAttribute(value = "num")
public int myModel(@RequestParam(required = false) int number) {return number;
}
相当于:model.addAttribute(“attributeName”, abc);
补充,顺便提及一下 @SessionAttributes 的使用:
(1) 如果在类上面使用了 @SessionAttributes(“attributeName”) 注解,而本类中恰巧存在attributeName,则会将 attributeName 放入到 session 作用域
(2) 如果在类上面使用了 @SessionAttributes(“attributeName”) 注解,SpringMVC 会在执行方法之前,自动从 session 中读取 key 为 attributeName 的值,并注入到 Model 中
所以我们在方法的参数中使用 @ModelAttribute(“attributeName”) 就会正常的从 Model 读取这个值,也就相当于获取了 session中的值
(3) 使用了 @SessionAttributes 之后,Spring 无法知道什么时候要清掉 @SessionAttributes 存进去的数据,如果要明确告知,也就是在方法中传入 SessionStatus 对象参数,并调 status.setComplete() 就可以了
注意:@SessionAttributes 需要清除时,使用 SessionStatus.setComplete(); 来清除;注意,它只清除 @SessionAttributes 的 session,不会清除 HttpSession 的数据;可参考:https://blog.csdn.net/hayre/article/details/54666275
2.3 应用在方法上,并且方法也使用了 @RequestMapping 注解
@Controller
@RequestMapping("/modelattributeTest4")
public class ModelAttributeTestController4 {@RequestMapping(value = "/test1")@ModelAttribute("name")public String test1(@RequestParam(required = false) String name) {return name;}
}
这种情况下,返回值 String(或者其他对象),就不再是视图了;将是我们上面将到的放入 Model 中的值,此时对应的页面就是 @RequestMapping 的 value 值 test1;等价于
model.addAttribute("name", name);
return "test1";
2.4 全局设置 @ModelAttribute,需要结合 @ControllerAdvice 使用,新建一个类,添加如下代码测试
@ControllerAdvice
public class GlobalExceptionHandler {// 全局添加属性值@ModelAttributepublic void newUser(Model model) {System.out.println("... @ModelAttribute 应用到所有@RequestMapping注解方法, 在其执行之前把返回值放入Model..."); model.addAttribute("temp", new User("dufu", "666", new Date()));}// 或者如下这样,这样就相当于 mode.addAttribue("temp", new User("dufu", "666", new Date()))@ModelAttribute("temp")public User newUser() {System.out.println("... @ModelAttribute 应用到所有@RequestMapping注解方法,在其执行之前把返回值放入Model..."); return new User("dufu", "666", new Date()));}
}
所有使用了 @RequestMapping 或者类似的注解(如:@GetMapping)的方法都会被作用到;我们就可以在页面上获取到设置的值
注意:如果要在 Controller 里获取 @ModelAttribute 设置的值,可参考如下代码
@GetMapping("/user")
public User getUser(@ModelAttribue("temp")User user) {return user;
}
@InitBinder
多用作转换器,主要用于对添加了@Controller 的类,@RequestMapping 注解的方法,在方法执行之前执行;主要作用于 GET 请求,常用来校验接收的值,设置不返回的值,或者初始化传递来的值(常用来对前端传递来的日期的转化处理)
示例,结合 @ControllerAdvice 注解将前端传递的 http://xxx?user=ramos:123 这样的字符串转化为 user 对象
@ControllerAdvice
public class GlobalExceptionHandler {// 全局初始化值@InitBinderpublic void initBinder(WebDataBinder binder) {binder.registerCustomEditor(User.class, new UserEditor());System.out.println("... @InitBinder 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器..."); }
}
上面的代码,我们添加了一个转化器,用于把前端传递过来的字符串转化成对应的 User 对象;那么需要添加一个转化器:UserEditor,注意自定义的转化器需要继承 PropertyEditorSupport
public class UserEditor extends PropertyEditorSupport {@Overridepublic String getAsText() {return super.getAsText();}@Overridepublic void setAsText(String text) throws IllegalArgumentException {if (!StringUtils.isEmpty(text)) {User user = new User();String[] items = text.split(":");user.setUsername(items[0]);user.setPassword(items[1]);user.setCreateDate(new Date());setValue(user);} else {throw new CommonException("传递的字符串为空");}}
}
Contorller 层调用,注意这里是 Get 请求,接收的值却是 User 对象;@RequestParam 注解不可少
@GetMapping(value="/name}")
@ResponseBody
public User getUserByName(@RequestParam("user") User user) {System.out.println(user);return user;
}
前端传递格式:http://localhost:8080/user/name/andy?user=ramos:123,这样就能把字符串转化成 user 对象;相当于一个转换器
除了使用 @ControllerAdvice 来配置全局的 WebDataBinder,还可以使用 RequestMappingHandlerAdapter;如下是一个格式化时间的 dataBinder 的实现
@Bean
public RequestMappingHandlerAdapter webBindingInitializer() {RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();adapter.setWebBindingInitializer(new WebBindingInitializer() {@Overridepublic void initBinder(WebDataBinder binder, WebRequest request) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");binder.registerCustomEditor(Date.class, new CustomDateEditor(format, false));}});return adapter;
}
SpringBoot之@ControllerAdvice,@ModelAttribute,@InitBinder详解相关推荐
- SpringBoot - 获取Get请求参数详解(附样例:非空、默认值、数组、对象)
利用 Spring Boot 来制作 Web 应用,就必定会涉及到前端与后台之间互相传递参数.下面演示 Controller 如何接收以 GET 方式传递过来的参数. 一.参数直接在路径中 (1)假设 ...
- SpringBoot 获取 Get 请求参数详解
叙述 利用 Spring Boot 来制作 Web 应用,就必定会涉及到前端与后台之间互相传递参数. 下面演示 Controller 如何接收以 GET 方式传递过来的参数. 解决方案 参数直接在路径 ...
- spring学习之@ModelAttribute运用详解
@ModelAttribute使用详解 1.@ModelAttribute注释方法 例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方 ...
- SpringBoot整合Log4j2以及配置详解
文章目录 标题SpringBoot整合Log4j2以及配置详解 1.加入依赖 2.在src.java.main.resources目录下创建log4j2.xml文件 log4j2.xml文件内容如下: ...
- SpringBoot - 获取Get请求参数详解
利用 Spring Boot 来制作 Web 应用,就必定会涉及到前端与后台之间互相传递参数.下面演示 Controller 如何接收以 GET 方式传递过来的参数. 一.直接在请求路径中 (1).假 ...
- springboot aop的execution 表达式详解
Aspectj切入点语法定义 在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义切入点表达式 execu ...
- Springboot使用Log4j2的配置详解
Springboot使用Log4j2的配置 日志框架的对比和选择 一.依赖配置(pom文件) 二.log4j2.xml文件的配置 三.Log4j2.xml配置文件核心概念解析 1.全局Property ...
- @ModelAttribute运用详解
2019独角兽企业重金招聘Python工程师标准>>> 被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射 ...
- springboot 集成redis_一文详解Spring Boot 集成 Redis
redis设置: 修改redis服务器的配置文件 vim /usr/local/redis/bin/redis.confbind 0.0.0.0 protected-mode no 重新启动redis ...
最新文章
- android studio 库项目管理,在Android Studio中将现有项目转换为库项目
- iPhone开发:类似iChat的聊天泡泡示例
- 自律到极致-人生才精致:第13期
- export data by MS-SQL
- leetcode 897. 递增顺序搜索树(中序遍历)
- Servlet之过滤器详解
- 网络连接数4000多正常吗_怀孕36周时胎儿发育情况是怎样的?胎儿体重有4斤多正常吗?...
- matlab训练cifar10,认识CIFAR-10数据集
- 全国大学生英语竞赛【常考词汇】
- 区块链与程序员:赚钱还是创业
- 有电流平衡能力的6组白光LED驱动器MAX8790
- C# socket 局域网聊天程序的一点心得
- nyoj-234-吃土豆(动态规划)
- win8计算机可用内存不足,win8电脑运行提示物理内存不足的解决方法
- 【智哪儿评测】轻松玩转智能家居,萤石B1智家护卫传感套装评测
- 第九章:MATLAB:程序设计(一)M文件
- 小程序突然报module is not defined_蔬菜“英文”小故事(九)
- GameFramework篇:前言
- 电磁波是如何产生的以及分类
- 矩阵的初等变换的应用
热门文章
- python爬虫实战三:爬取知乎评论
- 敏捷开发般若敏捷系列之三:什么是敏捷(下)(无住,不住于空,破空执,非法,非非法)
- 【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类
- Flutter 季度调研结果分享 | 开发者的选择
- 自带谷歌“血缘”,越超Oracle,“蟑螂”成为分布式数据库新标杆?
- 吃PHP小孩智力好,吃鱼对孩子智力有好处?不一定,这几类鱼娃吃了可能会生病...
- 小鹏汽车为什么取名为小鹏?何小鹏亲自会答:最初叫“橙子” 原因非常凑巧
- 开发环境搭建---交叉工具链、makefile编写、连接器脚本、Eclipse调试
- 【Python 实战基础】如何绘制柱状图分析两个学生成绩数据
- 练习正则表达式之惰性匹配和贪婪匹配