@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详解相关推荐

  1. SpringBoot - 获取Get请求参数详解(附样例:非空、默认值、数组、对象)

    利用 Spring Boot 来制作 Web 应用,就必定会涉及到前端与后台之间互相传递参数.下面演示 Controller 如何接收以 GET 方式传递过来的参数. 一.参数直接在路径中 (1)假设 ...

  2. SpringBoot 获取 Get 请求参数详解

    叙述 利用 Spring Boot 来制作 Web 应用,就必定会涉及到前端与后台之间互相传递参数. 下面演示 Controller 如何接收以 GET 方式传递过来的参数. 解决方案 参数直接在路径 ...

  3. spring学习之@ModelAttribute运用详解

    @ModelAttribute使用详解 1.@ModelAttribute注释方法      例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方 ...

  4. SpringBoot整合Log4j2以及配置详解

    文章目录 标题SpringBoot整合Log4j2以及配置详解 1.加入依赖 2.在src.java.main.resources目录下创建log4j2.xml文件 log4j2.xml文件内容如下: ...

  5. SpringBoot - 获取Get请求参数详解

    利用 Spring Boot 来制作 Web 应用,就必定会涉及到前端与后台之间互相传递参数.下面演示 Controller 如何接收以 GET 方式传递过来的参数. 一.直接在请求路径中 (1).假 ...

  6. springboot aop的execution 表达式详解

    Aspectj切入点语法定义 在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义切入点表达式  execu ...

  7. Springboot使用Log4j2的配置详解

    Springboot使用Log4j2的配置 日志框架的对比和选择 一.依赖配置(pom文件) 二.log4j2.xml文件的配置 三.Log4j2.xml配置文件核心概念解析 1.全局Property ...

  8. @ModelAttribute运用详解

    2019独角兽企业重金招聘Python工程师标准>>> 被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射 ...

  9. springboot 集成redis_一文详解Spring Boot 集成 Redis

    redis设置: 修改redis服务器的配置文件 vim /usr/local/redis/bin/redis.confbind 0.0.0.0 protected-mode no 重新启动redis ...

最新文章

  1. android studio 库项目管理,在Android Studio中将现有项目转换为库项目
  2. iPhone开发:类似iChat的聊天泡泡示例
  3. 自律到极致-人生才精致:第13期
  4. export data by MS-SQL
  5. leetcode 897. 递增顺序搜索树(中序遍历)
  6. Servlet之过滤器详解
  7. 网络连接数4000多正常吗_怀孕36周时胎儿发育情况是怎样的?胎儿体重有4斤多正常吗?...
  8. matlab训练cifar10,认识CIFAR-10数据集
  9. 全国大学生英语竞赛【常考词汇】
  10. 区块链与程序员:赚钱还是创业
  11. 有电流平衡能力的6组白光LED驱动器MAX8790
  12. C# socket 局域网聊天程序的一点心得
  13. nyoj-234-吃土豆(动态规划)
  14. win8计算机可用内存不足,win8电脑运行提示物理内存不足的解决方法
  15. 【智哪儿评测】轻松玩转智能家居,萤石B1智家护卫传感套装评测
  16. 第九章:MATLAB:程序设计(一)M文件
  17. 小程序突然报module is not defined_蔬菜“英文”小故事(九)
  18. GameFramework篇:前言
  19. 电磁波是如何产生的以及分类
  20. 矩阵的初等变换的应用

热门文章

  1. python爬虫实战三:爬取知乎评论
  2. 敏捷开发般若敏捷系列之三:什么是敏捷(下)(无住,不住于空,破空执,非法,非非法)
  3. 【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类
  4. Flutter 季度调研结果分享 | 开发者的选择
  5. 自带谷歌“血缘”,越超Oracle,“蟑螂”成为分布式数据库新标杆?
  6. 吃PHP小孩智力好,吃鱼对孩子智力有好处?不一定,这几类鱼娃吃了可能会生病...
  7. 小鹏汽车为什么取名为小鹏?何小鹏亲自会答:最初叫“橙子” 原因非常凑巧
  8. 开发环境搭建---交叉工具链、makefile编写、连接器脚本、Eclipse调试
  9. 【Python 实战基础】如何绘制柱状图分析两个学生成绩数据
  10. 练习正则表达式之惰性匹配和贪婪匹配