springBoot系列之七-----@ControllerAdvice注解用法

@ControllerAdvice  这个注解呢不能说时springBoot的,它是springMVC的一个注解,只不过功能用途是一模一样的。

@ControllerAdvice 的三种用途:

  1. 处理全局异常
  2. 预设全局数据
  3. 请求参数预处理

一、处理全局异常:

下面是代码实例:文件上传,文件过大的异常

 /**
     * 单文件上传
     *
     * @param file
     * @param request
     * @return
     */

    @PostMapping("/oneUpload")
    @ResponseBody
    public String oneUploadFile(MultipartFile file, HttpServletRequest request) {

        String path = "F://图片/img/";
        String data = sft.format(new Date());
        String fileName = file.getOriginalFilename();
        String lastStr = fileName.substring(fileName.lastIndexOf("."));
        if (".txt".equals(lastStr)) {

            return "文件格式不正确";
        }
        ;
        File file1 = new File(path + data);
        if (!file1.exists()) {
            file1.mkdirs();
        }

        String newName = UUID.randomUUID().toString().replace("-", "") + fileName;
        try {
            file.transferTo(new File(file1, newName));
            String url = path + data + "/" + newName;
            return url;
        } catch (IOException e) {
            e.printStackTrace();
        }
        //文件存储路径

        return "error";
    }

前端页面:

<form action="/upload/oneUpload" method="post" enctype="multipart/form-data">
<input type="file"  id="upload" name="file">
    <input type="submit" value="提交">
</form>

并且我把配置文件application.properties 文件大小改为了1kb

#=========================文件上传大小控制  ===================
spring.servlet.multipart.max-file-size=1kb

启动项目上传文件后出现的异常,可读性很不友好的来定制异常信息。

这下你就可以自定义一个来处理异常的类并且用@ControllerAdvice  

/**
 * 异常处理
 *
 * @author
 */

@ControllerAdvice
public class MyException {

   
    //在这个注解里面 可以指定异常还可以指定父级异常所有异常都捕获。
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public void myException(HttpServletResponse  response) throws IOException {

        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write("上传文件过大");
        writer.flush();
        writer.close();
    }
}

测试结果如下:

你还可以返回一个ModelAndView  返回一个异常页面。

  @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ModelAndView myException() throws IOException {

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("myError");
        modelAndView.addObject("error", "文件上传失败");

        return modelAndView;
    }

下面的异常页面我使用thymeleaf 模板引擎来做的。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 th:text="${error}"> </h1>
</body>
</html>

结果如下:

二、预设全局数据

通过这个注解@ControllerAdvice 设置的数据 在任何一个Controller中都可以获取的到。

直接上代码了

/**
 * 预设全局数据
 *
 * @author
 */
@ControllerAdvice
public class GlobalData {


    /**
     * 这个里的 info  可以随意设置 就相当于一个变量的名字 取数据的时候
     * 可以根据这变量来获取 设置的值
     *
     * @return
     */
    @ModelAttribute(value = "info")
    public Map<String, Object> info() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "邢小白");
        return map;
    }
}

在项目任意Controller 中取出info 步骤:

/**
 * 取出预设全局数据
 *
 * @author
 */
@Controller
public class GlobalDataController {


    @RequestMapping("/info")
    @ResponseBody
    public Object getGlobalData(Model model) {

        Map<String, Object> map = model.asMap();
        for (String key : map.keySet()) {

            System.out.println(key + ":" + map.get(key));
        }

        return map.get("info");
    }
}

结果如下:也是一个map 对象

info:{name=邢小白}

三、请求参数预处理

如果两个类有一个属性名称相同,那springMvc 时怎样映射封装呢 

代码如下:

实体类:用的lombak插件    解决了写get \set 和toString() 方法

@Data
public class Book {

    private  String name;

    private  double price;

}
@Data
public class Author {

    private String name;
    private  Integer  age;
}

Controller

@Controller
public class BookController{


    @PostMapping("/book")
    @ResponseBody
    public String  book(Book book, Author  author ){

        System.out.println(book);
        System.out.println(author);
        return "22";
    }
}

Postman工具调用接口:

结果如下:springMvc 也分不清那个是哪个, 会把两个相同属性的字段,映射封装到一个字段中。

Book(name=西游记,吴承恩, price=100.0)
Author(name=西游记,吴承恩, age=19)

解决方案:@ControllerAdvice

@ControllerAdvice
public class GlobalData {


    @InitBinder("a")
    public void initA(WebDataBinder dataBinder) {
        //设置默认的前缀
        dataBinder.setFieldDefaultPrefix("a.");
    }

    @InitBinder("b")
    public void initAB(WebDataBinder dataBinder) {
        //设置默认的前缀
        dataBinder.setFieldDefaultPrefix("b.");
    }

}

Controller

  @PostMapping("/book")
    @ResponseBody
    public String  book(@ModelAttribute("b") Book book, @ModelAttribute("a") Author  author ){

        System.out.println(book);
        System.out.println(author);
        return "22";
    }

Postman调用请求也会相应的改变:

感言致辞:

也还是那句话写这些东西呢 也算是一个总结记录以后遇到相对应的问题,也好解决,也希望学习一门技术有可能不能实践,两个星期就还回去了,觉得自己总结描述太差,想锻炼以下自己的书写能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值