【Spring Boot】027-@ControllerAdvice 与 @RestControllerAdvice

【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、运行测试

上传正常大小的图片

image-20210817092855131

上传较大的图片

image-20210817092952514

三、添加全局数据

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、运行结果

image-20210817094736527

四、请求参数预处理

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 页面;

鉴于提供的引用内容,@RestControllerAdvice(basePackages = "要拦截的异常的包路径")是一个注解,用于定义一个控制器增强类,并拦截指定包路径下的异常。[1] @RestControllerAdvice是一个组合注解,由@ControllerAdvice和@ResponseBody组成。它用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。 在Spring Boot中,@RestControllerAdvice相当于@ControllerAdvice和@ResponseBody的结合,可直接返回JSON数据。 通过指定basePackages属性,可以限定拦截异常的包路径。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [spring框架:注解@ControllerAdvice的三个使用场景](https://blog.csdn.net/l751475472/article/details/106615363)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [SpringBoot常用注解@RestControllerAdvicel](https://blog.csdn.net/zalan01408980/article/details/126729553)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值