处理全局异常
我们使用fileupload项目来进行测试,首先我们设置上传文件的大小限制
1 spring.servlet.multipart.max-file-size =1KB
测试一下,我们可以看到出现了FileSizeLimitExceededException ,同时还有一个提示信息This application has no explicit mapping for /error, so you are seeing this as a fallback. 那么我们如何自定义一个错误提示呢?我们创建一个MyException类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.example.fileupload;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.multipart.MaxUploadSizeExceededException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;@ControllerAdvice public class MyException { @ExceptionHandler (MaxUploadSizeExceededException.class ) public void myException (MaxUploadSizeExceededException e , HttpServletResponse response ) throws IOException { response.setContentType("text/html;charset=utf-8" ); PrintWriter writer = response.getWriter(); writer.write("上传文件大小超出限制" ); writer.flush(); writer.close(); } }
我们再来做一次文件上传,我们可以看到自定义的错误提示了
那么如果我们想自定义一个错误页面呢?首先我们添加thymeleaf依赖,然后添加一个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.example.fileupload;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.multipart.MaxUploadSizeExceededException;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;@ControllerAdvice public class MyException { @ExceptionHandler (MaxUploadSizeExceededException.class ) public ModelAndView myException (MaxUploadSizeExceededException e ) throws IOException { ModelAndView modelAndView = new ModelAndView("error" ); modelAndView.addObject("error" ,"上传文件大小超出限制" ); return modelAndView; } }
然后在template目录下创建一个error.html文件
1 2 3 4 5 6 7 8 9 10 <!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 >
上传一个超出1KB的文件后就会看到自定义的错误提示页面了
预设全局数据
我们先创建一个GlobalData类,该类定义了一个全局数据,即任意一个Controller都可以获取到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.example.controlleradvice;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 GlobalData { @ModelAttribute (value = "info" ) public Map<String,Object> myData () { Map<String, Object> map = new HashMap<>(); map.put("name" ,"WJZheng" ); map.put("address" ,"https://wellenzheng.github.io/" ); return map; } }
然后我们创建一个Controller,通过Model来获取数据并在控制台输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.example.controlleradvice;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.util.Map;import java.util.Set;@RestController public class DataController { @GetMapping ("/data" ) public String data (Model model) { Map<String, Object> map = model.asMap(); Set<String> keySet = map.keySet(); for (String key : keySet) { System.out.println(key + ":" + map.get(key)); } return "data" ; } }
请求参数预处理
我们首先创建一个Book类和一个Author类,他们都有一个同名的属性name。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package com.example.controlleradvice;public class Book { private String id; private String name; private Double price; @Override public String toString () { return "Book{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + '}' ; } public String getId () { return id; } public void setId (String id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Double getPrice () { return price; } public void setPrice (Double price) { this .price = price; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package com.example.controlleradvice;public class Author { private String name; private Integer age; @Override public String toString () { return "Author{" + "name='" + name + '\'' + ", age=" + age + '}' ; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getAge () { return age; } public void setAge (Integer age) { this .age = age; } }
然后在Controller里添加一个方法来post数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.example.controlleradvice;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class BookController { @PostMapping ("/book" ) public void addBook (@ModelAttribute("book" ) Book book, @ModelAttribute ("author" ) Author author) { System.out.println(book); System.out.println(author); } }
最后在GlobalData中为这两个参数绑定一个前缀
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.example.controlleradvice;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 GlobalData { @InitBinder ("author" ) public void initAuthor (WebDataBinder binder) { binder.setFieldDefaultPrefix("a." ); } @InitBinder ("book" ) public void initBook (WebDataBinder binder) { binder.setFieldDefaultPrefix("b." ); } }
然后在postman中进行测试,我们就可以在提交的数据中加上前缀来区别这两个类的同名属性
若未加预处理之前,springboot会把两个同名属性合并在一起