文章目录

  • ​​【Spring Boot】027-@ControllerAdvice 与 @RestControllerAdvice​​
  • ​​一、@ControllerAdvice概述​​
  • ​​1、简介​​
  • ​​2、使用场景​​
  • ​​二、全局异常处理​​
  • ​​1、概述​​
  • ​​2、代码演示​​
  • ​​自定义异常处理类 CustomExceptionHandler​​
  • ​​resources/static目录下的upload.html​​
  • ​​文件上传处理接口FileUploadController​​
  • ​​3、运行测试​​
  • ​​上传正常大小的图片​​
  • ​​上传较大的图片​​
  • ​​三、添加全局数据​​
  • ​​1、概述​​
  • ​​2、代码演示​​
  • ​​全局数据配置 GlobalConfig​​
  • ​​在Controller中使用全局数据​​
  • ​​3、运行结果​​
  • ​​四、请求参数预处理​​
  • ​​1、概述​​
  • ​​2、代码示例​​
  • ​​实体类:Book​​
  • ​​实体类:Author​​
  • ​​Controller 接收实体类(错误写法)​​
  • ​​Controller 接收实体类(正确写法)​​
  • ​​GlobalConfig​​
  • ​​五、@RestControllerAdvice​​
  • ​​1、与 @ControllerAdvice 区别​​
  • ​​2、@RestController 与 @Controller 的区别​​
  • ​​使用@Controller 注解​​
  • ​​@RestController注解​​

【Spring Boot】027-@ControllerAdvice 与 @RestControllerAdvice

一、@ControllerAdvice概述

1、简介

@ControllerAdvice 是 @Controller 的增强版,其主要用来处理全局数据,一般搭配 @ExceptionHandler 、@ModelAttribute 以及 @InitBinder 使用!

2、使用场景

  • 全局异常处理;
  • 添加全局数据;
  • 请求参数预处理;

二、全局异常处理

1、概述

@ControllerAdvice 最常见的使用场景就是全局异常处理。在文件上传时,有时候文件超过最大限制,就会抛出异常,此时我们可以通过 @Controller 结合 @ExceptionHandler 定义全局异常捕捉机制!

2、代码演示

Thymeleaf几乎不用了,不再演示!

自定义异常处理类 CustomExceptionHandler

package com.zibo.api.common.handler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@ControllerAdvice
public class CustomExceptionHandler {

@ExceptionHandler(MaxUploadSizeExceededException.class)
public void uploadException(MaxUploadSizeExceededException e, HttpServletResponse resp) throws IOException{
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("上传文件大小超出限制!");
out.flush();
out.close();
}

}

resources/static目录下的upload.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile" value="请选择文件">
<input type="submit" value="上传">
</form>

</body>
</html>

文件上传处理接口FileUploadController

package com.zibo.api.controller.file;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@RestController
public class FileUploadController {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
@PostMapping("upload")
public String upload(MultipartFile uploadFile, HttpServletRequest request){
String realPath = request.getSession().getServletContext().getRealPath("/uploadFile/");
String format = sdf.format(new Date());
File folder = new File(realPath + format);
if(!folder.isDirectory()){
folder.mkdirs();
}
String oldName = uploadFile.getOriginalFilename();
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
try {
uploadFile.transferTo(new File(folder,newName));
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/uploadFile/" + format + "/" + newName;
}catch (IOException e){
e.printStackTrace();
}
return "上传失败!";
}
}

3、运行测试

上传正常大小的图片

【Spring Boot】027-@ControllerAdvice 与 @RestControllerAdvice_数据

上传较大的图片

【Spring Boot】027-@ControllerAdvice 与 @RestControllerAdvice_数据_02

三、添加全局数据

1、概述

@ControllerAdvice 是一个全局数据处理组件,因此也可以在其中配置全局数据,使用 @ModelAttribute 注解进行配置。

2、代码演示

全局数据配置 GlobalConfig

package com.zibo.api.config;

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 GlobalConfig {
// info表示的是返回数据的key
@ModelAttribute(value = "info")
public Map<String,String> userInfo(){
Map<String,String> map = new HashMap<>();
map.put("username","刘备");
map.put("gender","男");
return map;
}
}

在Controller中使用全局数据

注意 @RestController 和 @Controller 两个注解的区别!@RestController = @Controller + @ResponseBody

这里就暂时使用 @Controller 吧!因为很少用,所以用一下吧,增强记忆!

package com.zibo.api.controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@Controller
public class HelloController {

@RequestMapping("hello")
@ResponseBody
public Object hello(Model model){
Map<String, Object> map = model.asMap();
return map.get("info");
}

}

3、运行结果

【Spring Boot】027-@ControllerAdvice 与 @RestControllerAdvice_spring_03

四、请求参数预处理

1、概述

@ControllerAdvice 结合 @InitBinder 实现对请求参数预处理!

2、代码示例

仅作写法展示,未进行实际测试!

实体类:Book

package com.zibo.api.entity;

import lombok.Data;

@Data
public class Book {
private String name;
private String author;
}

实体类:Author

package com.zibo.api.entity;

import lombok.Data;

@Data
public class Author {
private String name;
private Integer age;
}

Controller 接收实体类(错误写法)

这么写的问题:book 和 author 中都有 name 属性,会导致数据混淆错误!

@RequestMapping("hi")
public String hi(Book book, Author author){
return book.toString() + "==>" + author.toString();
}

Controller 接收实体类(正确写法)

@RequestMapping("hi")
public String hi(@ModelAttribute("b") Book book, @ModelAttribute("a") Author author){
return book.toString() + "==>" + author.toString();
}

GlobalConfig

package com.zibo.api.config;

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 java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalConfig {

@InitBinder("b")
public void init(WebDataBinder binder){
binder.setFieldDefaultPrefix("b.");
}

@InitBinder("a")
public void init2(WebDataBinder binder){
binder.setFieldDefaultPrefix("a.");
}
}

五、@RestControllerAdvice

1、与 @ControllerAdvice 区别

代码演示省略!

简单地说,@RestControllerAdvice 与 @ControllerAdvice 的区别就和 @RestController 与 @Controller 的区别类似,@RestControllerAdvice 注解包含了 @ControllerAdvice 注解和 @ResponseBody 注解。

当自定义类加@ControllerAdvice注解时,方法需要返回json数据时,每个方法还需要添加@ResponseBody注解;

当自定义类加@RestControllerAdvice注解时,方法自动返回json数据,每个方法无需再添加@ResponseBody注解;

2、@RestController 与 @Controller 的区别

@RestController = @Controller + @ResponseBody

使用@Controller 注解

在对应的方法上,视图解析器可以解析 return 的 jsp,html 页面,并且跳转到相应页面

若返回 json 等内容到页面,则需要加 @ResponseBody 注解;

@RestController注解

相当于 @Controller + @ResponseBody 两个注解的结合,返回 json 数据不需要在方法前面加 @ResponseBody 注解了,但使用@RestController 这个注解,就不能返回 jsp,html 页面,视图解析器无法解析 jsp,html 页面;