先讲下什么是全局异常处理器? html
全局异常处理器就是把整个系统的异常统一自动处理,程序员能够作到不用写try... catch。SpringBoot内置有默认全局异常处理器。前端
Spring Boot对异常的处理有一套默认的机制,BasicErrorController处理默认异常转发的或这error请求 :当应用中产生异常时,当从浏览器地址栏中访问应用接口时,SpringBoot会获取请求头中数据,若是请求头中的accept
包含text/html
信息,产生异常时,Spring Boot会经过ModelAndView模型
对象来装载异常信息,并以HTML的格式返回;反之,请求头中的accept
不包含text/html时
,Spring Boot则以JSON的格式返回异常信息。git
例如:访问一个未知接口资源(或后台接口定义10/0的错误,响应的HTML结果以下)程序员
例如:利用Postman测试工具,访问未知资源测试:(能够尝试使用其余插件工具:使用Chrome插件Restlet Client)github
BasicErrorController源码截取以下:后端
@RequestMapping("${server.error.path:${error.path:/error}}")请求的异常页面地址为/error/下面的资源
当没有自定义异常页面时,默认按下方源码执行构建HTML或JSON响应给前台。浏览器
1 @Controller 2 @RequestMapping("${server.error.path:${error.path:/error}}") 3 public class BasicErrorController extends AbstractErrorController { 4 /** 5 * 错误信息处理器方法errorHtml,设置了请求头Accpet值类型,若是包含text/html,即执行该方法 6 * @param request 请求对象 7 * @param response 响应对象 8 * @return 9 * MediaType.TEXT_HTML_VALUE的实际值就是一个字符串“text/html” 10 */ 11 @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) 12 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { 13 // 获取状态码 14 HttpStatus status = getStatus(request); 15 Map<String, Object> model = Collections 16 .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); 17 // 响应状态码描述 18 response.setStatus(status.value()); 19 // 建立视图模型对象 20 ModelAndView modelAndView = resolveErrorView(request, response, status, model); 21 return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); 22 } 23 24 /** 25 * 错误信息处理器方法error方法,设置了请求头Accpet值类型,即没有包含text/html执行该方法 26 * @param request 请求对象 27 * @param response 响应对象 28 */ 29 @RequestMapping 30 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { 31 HttpStatus status = getStatus(request); 32 if (status == HttpStatus.NO_CONTENT) { 33 return new ResponseEntity<>(status); 34 } 35 Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); 36 return new ResponseEntity<>(body, status); 37 } 38 39 }
咱们能够自定义友好的异常页面。但必须是放在资源/error/目录下,资源目录存放默认地址可选
src/main/resources/static/,src/main/resources/resources/,src/main/resources/public/,src/main/templates/安全
说明:前三者是静态资源目录,页面咱们使用模板引擎,所以若是须要自定义错误页面,那么须要放在src/main/templates/error目录下(固然全部的前提是,没有更改默认配置,SpringBoot默认加载其中的错误页面),且错误页面命名必须以状态码方式。SpringBoot默认错误视图解析器DefaultErrorViewResolver源码解析以下:服务器
1 public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered { 2 3 private static final Map<Series, String> SERIES_VIEWS; 4 5 // 静态初始化错误状态类型:4xx 或 5xx 6 static { 7 Map<Series, String> views = new EnumMap<>(Series.class); 8 views.put(Series.CLIENT_ERROR, "4xx"); 9 views.put(Series.SERVER_ERROR, "5xx"); 10 SERIES_VIEWS = Collections.unmodifiableMap(views); 11 } 12 13 14 // 解析错误视图 15 @Override 16 public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { 17 // 获取错误状态码例如:404,转为字符串调用方法resolve(解析方法) 18 ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); 19 if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { 20 modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); 21 } 22 return modelAndView; 23 } 24 25 // 解析处理方法 26 private ModelAndView resolve(String viewName, Map<String, Object> model) { 27 // 拼接错误视图访问前缀:error/500 28 String errorViewName = "error/" + viewName; 29 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, 30 this.applicationContext); 31 if (provider != null) { 32 return new ModelAndView(errorViewName, model); 33 } 34 // 调用解析资源:传入error/500 35 return resolveResource(errorViewName, model); 36 } 37 38 // 解析资源 39 private ModelAndView resolveResource(String viewName, Map<String, Object> model) { 40 for (String location : this.resourceProperties.getStaticLocations()) { 41 try { 42 // 获取资解析 43 Resource resource = this.applicationContext.getResource(location); 44 // 建立解析文件为:error/500.html 45 resource = resource.createRelative(viewName + ".html"); 46 if (resource.exists()) { 47 return new ModelAndView(new HtmlResourceView(resource), model); 48 } 49 } 50 catch (Exception ex) { 51 } 52 } 53 return null; 54 } 55 }
关于模板引擎的整合,参考第九集:整合JSP和模板引擎app
1.在src/main/templates/error目录下新建错误页面:例如:404.html
2.测试访问。
1 <!DOCTYPE html> 2 <html xmlns:th="http://www.thymeleaf.org"> <!-- Thymeleaf模板约束 --> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Insert title here</title> 6 </head> 7 <body> 8 自定义404友好错误页面!<br> 9 对不起,你访问的数据被外星人盗窃了…… 10 </body> 11 </html>
除了能够能够自定义友好异常页面(HTML)外,咱们也能够自定义异常处理信息,改变默认的客户端访问接口产生的异常信息。
因为工做中都是先后端分离开发模式,因此几乎没有直接返回资源页的需求,通常上都是返回固定的响应格式JSON,如respCode
、respMsg
、data等
,前端经过判断respCode
的值进行业务判断,是弹窗仍是跳转页面。
1 @Data 2 @NoArgsConstructor 3 @AllArgsConstructor 4 public class ExceptionResponseResult{ 5 @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss") // 日期格式化 6 private Date timestamp;// 时间 7 private int respCode;// 状态码 8 private String respMsg;// 给用户看的描述信息 9 private String message;// 实际错误异常信息 10 private String exceptionName;// 实际错误异常名字 11 private String path;// URI 12 private Object data;// 数据 13 }
1 // @ControllerAdvice 2 @RestControllerAdvice // 控制器类加强:能够对Controller中全部使用@RequestMapping注解的方法加强 3 public class GlobalExceptionHandler { 4 5 // 该注解是异常处理器注解,能够对指定异常类型处理,执行注解标注的方法(只要发生指定异常都会被拦截) 6 @ExceptionHandler(Throwable.class) 7 // 该注解用于指定异常处理方法执行后响应页面的HTTP状态码,HttpStatus是Spring内置的一个状态码枚举类,内定了详细的状态码及描述,当前获取的是500 8 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)// 响应500 9 public Object exceptonResponse(Exception ex,HttpServletRequest request) { 10 ExceptionResponseResult resultError = new ExceptionResponseResult(); 11 resultError.setTimestamp(new Date());// 设置异常发生时间 12 resultError.setRespCode(0);// 能够选择自定义枚举类,定义状态码 13 resultError.setRespMsg("服务器刷新异常,请稍后。。。");// 用户看到的异常信息 14 resultError.setMessage(ex.getMessage());// 实际发生的异常信息 15 resultError.setExceptionName(ex.getClass().getName());// 实际异常的名字 16 resultError.setPath(request.getRequestURI());// 异常RUI 17 return resultError; 18 } 19 20 }
1 @Controller 2 public class HtmlController { 3 4 @RequestMapping("/indexHtml") 5 public String indexHtml(Model model) { 6 model.addAttribute("url","XSGE我的网站:http://www.xsge123.com"); 7 System.out.println("测试"+(10/0)); 8 return "indexHtml"; 9 } 10 }
页面访问测试结果:正常响应,但状态码是500
1 // 该注解是异常处理器注解,能够对指定异常类型处理,执行注解标注的方法(只要发生指定异常都会被拦截) 2 @ExceptionHandler(Throwable.class) 3 // 该注解用于指定异常处理方法执行后响应页面的HTTP状态码,HttpStatus是Spring内置的一个状态码枚举类,内定了详细的状态码及描述,当前获取的是500 4 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)// 响应500 5 public Object exceptonResponse(Exception ex,HttpServletRequest request) { 6 ExceptionResponseResult resultError = new ExceptionResponseResult(); 7 if (ex instanceof NullPointerException) {// 若是捕获的异常为控空指针异常 8 // ****设置异常信息***** 9 } else if (ex instanceof ArithmeticException) { 10 // ****设置异常信息***** 11 }// ***** 12 return resultError; 13 }
在任什么时候候,当你要处理一个应用程序的业务逻辑,数据校验是你必需要考虑和面对的事情。而后仅仅前端页面的校验就能保证安全了吗?小朋友仍是年轻,基础的前端攻击技术网上不少,因此,仅仅页面数据校验是不够的。JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。
JSR-303 是JAVA EE 6 中的一项子规范,叫作Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 。 Hibernate Validator 提供了 JSR 303 规范中全部内置 constraint(约束) 的实现,除此以外还有一些附加的 constraint(约束)。(注意:此实现与 Hibernate ORM 没有任何关系)。
校验规则及使用方法:关注博主SSM整合之数据校验!!!(目前资料已备没时间写,敬请期待!)等不及的能够查阅Githup官网,查看说明文档。