SpringBoot默认已经存在了错误页的显示处理,例如访问一个不存在的路径:
如果考虑到前后端分离的设计,那么应该使用JSON进行数据交互,返回页面的形式就不能满足要求了。
新建返回数据包装类,规定任何交互数据都以此为规范:
public class ResultMessage<T> {
private Integer code; // 返回编码
private String message; // 信息
private T result; // 返回结果
private boolean success;
public ResultMessage() {
}
public ResultMessage(Integer code, String message, T result, boolean success) {
this.code = code;
this.message = message;
this.result = result;
this.success = success;
}
// setter、getter略
}
新建ErrorAction专门返回错误信息:
@RestController
@RequestMapping("/errors")
public class ErrorAction {
@RequestMapping(value = "/error_404")
public ResultMessage<?> error404(HttpServletRequest request,HttpServletResponse response){
response.setContentType("text/json");
response.setStatus(HttpServletResponse.SC_NOT_FOUND); // 设置响应编码
Map<String, String> map = new LinkedHashMap<>();
map.put("referer", request.getHeader("Referer")); // 之前的来源
map.put("path", request.getRequestURI()); // 访问路径
return new ResultMessage<>(404, "无法找到用户访问信息", map, false);
}
}
新建配置类,使用/error/404
代替真正的错误页显示:
@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
/** * 注册错误页 * @param registry ErrorPageRegistry */
public void registerErrorPages(ErrorPageRegistry registry) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/errors/error_404");
registry.addErrorPages(errorPage404);
}
}
启动项目,访问一个不存在的路径:
其他类型的错误信息也可以采用同样的处理。
以500为例,在ErrorAction
新增一个error500
方法:
@RequestMapping(value = "/error_500")
public ResultMessage<?> error500(HttpServletRequest request,HttpServletResponse response){
Map<String, String> map = new LinkedHashMap<>();
map.put("referer", request.getHeader("Referer")); // 之前的来源
map.put("path", request.getRequestURI()); // 访问路径
return new ResultMessage<>(500, "无法找到用户访问信息", map, false);
}
修改ErrorPageConfig
类的registerErrorPages
方法,注册500错误页:
@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
/** * 注册错误页 * @param registry ErrorPageRegistry */
public void registerErrorPages(ErrorPageRegistry registry) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/errors/error_404");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/errors/error_500");
registry.addErrorPages(errorPage404, errorPage500);
}
}
新建TestController
类,制造一个服务器错误:
@RestController
@RequestMapping("/fail/*")
public class TestController {
@RequestMapping("/zero")
public Integer zeroError(Integer x) {
return 0 / x;
}
}
启动项目,访问http://localhost:8080/fail/zero
:
SpringBoot中可以使用@ControllerAdvice
或RestControllerAdvice
注解开启全局异常的捕获,使用@ExceptionHandler
注解声明要捕获异常的类型。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResultMessage<?> exceptionHandler(HttpServletRequest request, Exception e) {
Map<String, String> resultMap = new LinkedHashMap<>();
resultMap.put("uri",request.getRequestURI());
resultMap.put("type",e.getClass().getName());
return new ResultMessage(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), resultMap, false);
}
}
创建一个产生异常的Action测试类:
@RestController
@RequestMapping("/fail/*")
public class TestController {
@RequestMapping("/zero")
public Integer zeroError(Integer x) {
return 0 / x;
}
}
启动项目,访问http://localhost:8080/fail/zero
:
访问:http://localhost:8080/fail/zero?x=0
全局数据绑定用在一些返回相同数据的场景,修改了全局绑定的数据,那么所有的返回结果都会被更改。
新建Message类:
@Data
@AllArgsConstructor
public class Message {
private Integer id;
private String content;
private Date pubDate;
}
新建MessageConfig类,将Message实例对象注入Spring容器:
@Configuration
public class MessageConfig {
@Bean
public Message getMessage() {
return new Message(1,"SpringBoot全局数据绑定",new Date());
}
}
新建GlobalDataBindAdvice配置全局数据:
@ControllerAdvice
public class GlobalDataBindAdvice { // 全局数据绑定
private final Message message;
@Autowired
public GlobalDataBindAdvice(Message message) {
this.message = message;
}
@ModelAttribute(value = "bindModel")
public Object bindData() {
Map<String, String> resultMap = new LinkedHashMap();
resultMap.put("content", message.getContent());
resultMap.put("pubDate", message.getPubDate().toString());
return resultMap;
}
}
新建GlobalDataAction测试数据绑定结果:
@RestController
public class GlobalDataAction {
@RequestMapping("/message/echo")
public ResultMessage<?> echo(Model model, String message) {
Map<String, String> bindMap = (Map<String, String>) model.asMap().get("bindModel"); // 取得全局绑定数据
bindMap.put("url", "/message/echo");
return new ResultMessage(200, message, bindMap, false);
}
}
启动项目,访问http://localhost:8080/message/echo?message=hello
:
SpringMVC可以将接收的参数自动转换为VO对象,然而如果一次性接受两个对象且两个对象中含有相同名称的属性,那么转换就会出现问题。
新建Company类和Dept类,这两个类中含有相同名字的属性name
。
@Data
public class Company {
private Integer cid;
private String name;
}
@Data
public class Dept {
private Integer deptId;
private String name;
}
新建DeptAction同时接收这两个类的对象:
@RestController
@RequestMapping("/dept/*")
public class DeptAction {
@RequestMapping("/get")
public Object get(Company company, Dept dept) {
Map<String,Object> resultMap = new LinkedHashMap<>();
resultMap.put("company",company);
resultMap.put("dept",dept);
return resultMap;
}
}
访问:http://localhost:8080/dept/get?cid=1&name=XX公司&deptId=22&name=财务部
发现重复的参数内容使用了,
进行分割,并不是预期中的结果。实际上传递给Action的参数都会通过HttpServletRequest
中的getParameterValues
方法进行接收,接收到的内容全部都是数组,而Spring将数组的内容自动调用了toString()方法。
如果想要得到预期的结果,可以通过全局预处理来实现,新建GlobalDataPreAdvice
设置参数前缀:
@ControllerAdvice
public class GlobalDataPreAdvice { // 全局数据预处理
@InitBinder("company")
public void company(WebDataBinder binder) { // 参数前缀
binder.setFieldDefaultPrefix("company.");
}
@InitBinder("dept")
public void dept(WebDataBinder binder) {
binder.setFieldDefaultPrefix("dept.");
}
}
修改DeptAction
指定参数前缀:
@RestController
@RequestMapping("/dept/*")
public class DeptAction {
@RequestMapping("/get")
public Object get(@ModelAttribute("company") Company company,
@ModelAttribute("dept") Dept dept) {
Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("company", company);
resultMap.put("dept", dept);
return resultMap;
}
}
访问:http://localhost:8080/dept/get?company.cid=1&company.name=XX公司&dept.deptId=22&dept.name=财务部
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/Nicholas_GUB/article/details/121273139
内容来源于网络,如有侵权,请联系作者删除!