spring boot 尚桂谷学习笔记06 异常处理 ---Web
------错误处理机制------
默认效果
1 返回一个默认的错误页面

浏览器发送请求的请求头:优先接收 text/html 数据

客户端则默认响应json数据 : accept 没有说明返回什么数据 默认返回json

原理:参照 ErrorMvcAutoConfiguration 错误的自动配置
1 DefaultErrorAttributes
// 帮助我们共享页面信息
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> errorAttributes = new LinkedHashMap();
errorAttributes.put("timestamp", new Date());
this.addStatus(errorAttributes, webRequest);
this.addErrorDetails(errorAttributes, webRequest, includeStackTrace);
this.addPath(errorAttributes, webRequest);
return errorAttributes;
}
2 BasicErrorController
@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"}) // 都是响应 /error请求
public class BasicErrorController extends AbstractErrorController {
@RequestMapping(
produces = {"text/html"} // 产生html类型的数据
)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
// 去哪个页面作为错误页面 包含页面地址和内容
ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
return modelAndView == null ? new ModelAndView("error", model) : modelAndView;
} @RequestMapping
@ResponseBody // 产生json数据
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = this.getStatus(request);
return new ResponseEntity(body, status);
}
3 ErrorPageCustomizer
@Value("${error.path:/error}")
private String path = "/error"; 系统出现错误 到 error请求 (web.xml 注册的错误规则)
4 DefaultErrorViewResolver
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView modelAndView = this.resolve(String.valueOf(status), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
}
return modelAndView;
}
private ModelAndView resolve(String viewName, Map<String, Object> model) {
// 默认可以找到一个页面 error/404
String errorViewName = "error/" + viewName;
// 模板引擎可以解析这个页面地址就用模板引擎解析
// 模板引擎可以用的情况下返回得到errorViewName指定视图地址
// 模板引擎不可用 就在静态资源文件夹下找 errorViewName 对应的页面
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
return provider != null ? new ModelAndView(errorViewName, model) : this.resolveResource(errorViewName, model);
}
步骤:
一旦系统出现4xx或者5xx错误:ErrorPageCustomizer 生效(定制错误的响应规则) 就会来到/error 请求
就会被 BasicErrorController 处理:
1) 响应页面: 去哪个页面由 DefaultErrorViewResolver 决定
protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
Iterator var5 = this.errorViewResolvers.iterator();
// 所有的ErrorViewResolver 得到 ModelAndView
ModelAndView modelAndView;
do {
if (!var5.hasNext()) {
return null;
}
ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
modelAndView = resolver.resolveErrorView(request, status, model);
} while(modelAndView == null);
return modelAndView;
}
2 如何定制错误响应
1) 定制错误页面
1) 有模板引擎的情况下:error/ 状态码 ( error/404.html) 将错误页面命名为错误状态码.html 发生此状态码到此错误页面
也可以使用 4xx.html或者5xx.html 来匹配 4开头的或者5开头的错误 如果有精确的会优先到精确的错误提示页面
页面能获取的信息:
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303 数据校验的错误信息


2) 没有模板引擎,在静态资源文件夹下寻找 static文件夹下寻找
3) 模板引擎静态资源都没有 就是默认来到springboot 默认的错误提示页面
2) 定制json 错误数据
1) 自定义异常处理&返回json数据
//异常处理器
@ControllerAdvice
public class MyExceptionHandler {
// 浏览器客户端返回都是json数据
@ResponseBody
@ExceptionHandler(UserNotExistException.class)
public Map<String , Object> handleException(Exception e) {
Map<String , Object> map = new HashMap<String, Object>();
map.put("code", "user.notexist");
map.put("message", e.getMessage()); return map;
}
}
// 没有自适应效果...


2) 转发到/error 进行自适应响应 实现功能但是 map.put 信息无法接受
@ResponseBody
@ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e, HttpServletRequest request) {
Map<String , Object> map = new HashMap<String, Object>();
// 传入我们自己设置的状态码 4xx 5xx 否则不会进入到错误页面的解析流程
request.setAttribute("javax.servlet.error.status_code", 400);
map.put("code", "user.notexist");
map.put("message", e.getMessage()); // 转发到 /error页面
return "forward:/error";
}
3) 将我们的定制数据携带出去
出现错误以后 会来到 /error 请求 会被 ErrorBaseController 处理,响应出去的数据可以
获取的数据时由 getErrorAttributes 得到的(是 AbstractErrorController规定的方法)
---1完全来编写一个 ErrorController【或者编写AbstractErrorController类子类】 的实现类放在容器中
---2页面上能用的数据 或者json 能用的返回数据 通过 errorAttributes.getErrorAttributes得到
容器中DefaultErrorAttributes.getErrorAttributes 此方法定义返回数据可以自己写一个
// 给容器加入自己定义的ErrorAttributes
@Component
public class MyErrorAttributes extends DefaultErrorAttributes{ @Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
map.put("company", "lixuchun");
// scope
// request 0
// session 1
Map<String , Object> ext = (Map<String , Object>)webRequest.getAttribute("ext", 0);
map.put("ext", ext);
return map;
}
}
在MyExceptionHandler 中加入
@ResponseBody
@ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e, HttpServletRequest request) {
Map<String , Object> map = new HashMap<String, Object>();
// 传入我们自己设置的状态码 4xx 5xx 否则不会进入到错误页面的解析流程
request.setAttribute("javax.servlet.error.status_code", 400);
map.put("code", "user.notexist");
map.put("message", e.getMessage());
request.setAttribute("ext", map);
// 转发到 /error页面
return "forward:/error";
}
访问结果:

spring boot 尚桂谷学习笔记06 异常处理 ---Web的更多相关文章
- spring boot 尚桂谷学习笔记08 Docker ---Web
------Docker------ 简介:Docker是一个开元的应用容器引擎,性能非常高 已经安装好的软件打包成一个镜像放到服务器中运行镜像 MySQL容器,Redis容器...... Docke ...
- spring boot 尚桂谷学习笔记10 数据访问02 mybatis
数据访问 mybatis 创建一个 springboot 工程,模块选择 sql 中 mysql(数据驱动), jdbc(自动配置数据源), mybatis Web模块中选择 web pom 引入: ...
- spring boot 尚桂谷学习笔记04 ---Web开始
------web开发------ 1.创建spring boot 应用 选中我们需要的模块 2.spring boot 已经默认将这些场景配置好了 @EnableAutoConfiguration ...
- spring boot 尚桂谷学习笔记11 数据访问03 JPA
整合JPA SpringData 程序数据交互结构图 (springdata jpa 默认使用 hibernate 进行封装) 使用之后就关注于 SpringData 不用再花多经历关注具体各个交互框 ...
- spring boot 尚桂谷学习笔记09 数据访问
springboot 与数据库访问 jdbc, mybatis, spring data jpa, 1.jdbc原生访问 新建项目 使用 springboot 快速构建工具 选中 web 组件 sq ...
- spring boot 尚桂谷学习笔记07 嵌入式容器 ---Web
------配置嵌入式servlet容器------ springboot 默认使用的是嵌入的Servlet(tomcat)容器 问题? 1)如何定制修改Servlet容器的相关配置: 1.修改和se ...
- spring boot 尚桂谷学习笔记05 ---Web
------web 开发登录功能------ 修改login.html文件:注意加粗部分为 msg 字符串不为空时候 才进行显示 <!DOCTYPE html> <!-- saved ...
- springboot 尚桂谷学习笔记03
------spring boot 与日志------ 日志框架: 市面上的日志框架: jul jcl jboss-logging logback log4j log4j2 ...... 左边一个门面 ...
- 初次搭建spring boot 项目(实验楼-学习笔记)
首先说一下springboot 的优点: 使用Spring Initializr可以在几秒钟就配置好一个Spring Boot应用. 对大量的框架都可以无缝集成,基本不需要配置或者很少的配置就可以运行 ...
随机推荐
- JS事件循环,MACRO TASK,MICRO TASK
事件循环的基本概念 JS执行的过程中,由JS引擎控制的函数调用栈来控制时间循环 定时器线程,事件触发线程,异步http请求线程控制异步的任务队列 任务分为macro task,micro task 对 ...
- 洛谷 P3374 【模板】树状数组 1(单点加,区间和)
题目链接 https://www.luogu.org/problemnew/show/P3374 树状数组 树状数组最基本的就是求区间和. 维护: 空间复杂度:O(n) 时间复杂度(区间和,单点修改) ...
- 解决mxGraph放大/缩小在非IE浏览器下overlay图标位置不变化的问题
首先要创建一个工具栏.并为工具栏中的放大.缩小button定义事件. <div id="toolbar" style="float:left;margin-top: ...
- 【JMeter5.0】Mac安装JDK和JMeter5
之前讲了Windows下安装JDK和JMeter4.0的方法,其实不论操作系统是Windows.Mac OS.Linux等,JMeter所需要的基础环境配置都是类似的,本文介绍JMeter for M ...
- Vue 踩坑日志 - 有关路由传参的坑
1.有关路由传参 vue中当通过params传过去的参数刷新页面以后会消失,所以可以用query传参.但此时又会出现另一个坑,刷新后数据仍在.但这是针对单个的某个变量的. 如果传入一个对象的话,刷新页 ...
- SpringMVC表单或Json中日期字符串与JavaBean的Date类型的转换
SpringMVC表单或Json中日期字符串与JavaBean的Date类型的转换 场景一:表单中的日期字符串和JavaBean的Date类型的转换 在使用SpringMVC的时候,经常会遇到表单中的 ...
- JS 页面繁简字转换
// 本js用于客户在网站页面选择繁体中文或简体中文显示,默认是正常显示,即简繁体同时显示// 在用户第一次访问网页时,会自动检测客户端语言进行操作并提示.此功能可关闭// 本程序只在UTF8编码下测 ...
- 靶场练习--sqli(1&2)
前言 懒猪赵肥肥耍了3天3夜,每天除了练英语口语,啥子都没干.今天开始发愤图强,嘻嘻~ 计划内容有:靶场.视频.python.PHP.java.计算机英语. 首先,每天必搞靶场必看视频必学java和英 ...
- ltp-ddt nand_perf_ubifs_w_cpuload
NAND_M_PERF_UBIFS_CPU_LOAD source 'common.sh';/opt/ltp/runltp -f ddt/nand_perf_ubifs -s "NAND_S ...
- WPF 几种常用控件样式的总结
这里把wpf中几种常用样式总结一下,后期可以直接拷贝使用,呵呵 一.Button <ResourceDictionary xmlns="http://schemas.microsoft ...