通常,SpringBoot 默认的异常页面是这样的,用户根本看不懂,系统遇到 Bug 的话,也不知道跟管理员怎么反馈。
而自定义的异常页面是这样的,意思明朗很多。
通过配置全局异常管理,我们不仅可以美化页面的显示,自定义错误的信息。还可以捕获很多我们遇到的错误,并将它们写入日志中。虽然很多提交表单的异常可以通过前台 js 避免,但是万一用户禁用 js 呢?为了数据安全,我们在后台还是要加一层安全保护。
现在就开始吧!
1、这是一个统一异常处理类
GlobalExceptionHandler.java
注意修改 37 行的错误页面地址
不知道为什么 404 页面无法捕获
2、这是一个我们自定义的异常,通常我们可以主动抛它,当然,也可以直接抛 Exception
CustomException.java
3、在 template 或者资源根目录下新建 error 文件夹
error.html
因为 404 页面好像无法捕获,那么我们可以再新建一个 404.html ,内容和上面差不多,改一下错误码为 404 即可。
4、为了演示使用,这里是 UserServiceImpl.java 里的一个添加新用户的方法
先看几个系统自动抛出的异常
1、页面不存在,400错误
2、编辑用户的时候,修改票数(一个 Integer 类型的字段),当我们填成字符串 421swsw 的时候,400错误
3、某个字段只允许一个字符如用户状态是否禁用Y或N,党输入abcd的时候,无法执行,数据库报异常
然后再看几个我们主动抛出的异常
2、添加用户的时候,设置了用户名字段为唯一性,500错误
3、密码小于 6 位
而自定义的异常页面是这样的,意思明朗很多。
通过配置全局异常管理,我们不仅可以美化页面的显示,自定义错误的信息。还可以捕获很多我们遇到的错误,并将它们写入日志中。虽然很多提交表单的异常可以通过前台 js 避免,但是万一用户禁用 js 呢?为了数据安全,我们在后台还是要加一层安全保护。
现在就开始吧!
代码如下
1、这是一个统一异常处理类
GlobalExceptionHandler.java
- package com.liuyanzhao.forum.exception;
- import org.hibernate.service.spi.ServiceException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.converter.HttpMessageNotReadableException;
- import org.springframework.ui.Model;
- import org.springframework.validation.BindException;
- import org.springframework.validation.BindingResult;
- import org.springframework.validation.FieldError;
- import org.springframework.web.HttpMediaTypeNotSupportedException;
- import org.springframework.web.HttpRequestMethodNotSupportedException;
- import org.springframework.web.bind.MethodArgumentNotValidException;
- import org.springframework.web.bind.MissingServletRequestParameterException;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.ResponseStatus;
- import org.springframework.web.servlet.NoHandlerFoundException;
- import javax.validation.ConstraintViolation;
- import javax.validation.ConstraintViolationException;
- import javax.validation.ValidationException;
- import java.util.Set;
- /**
- * @author 言曌
- * @date 2018/3/20 下午12:57
- */
- @ControllerAdvice
- public class GlobalExceptionHandler {
- // 日志记录工具
- private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
- //错误显示页面,即 /public/error/error.html 文件
- public static final String viewName = "/error/error";
- /**
- * 400 - Bad Request
- */
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MissingServletRequestParameterException.class)
- public String handleMissingServletRequestParameterException(MissingServletRequestParameterException e, Model model) {
- logger.error("缺少请求参数", e);
- String message = "【缺少请求参数】" + e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 400);
- return viewName;
- }
- /**
- * 400 - Bad Request
- */
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(HttpMessageNotReadableException.class)
- public String handleHttpMessageNotReadableException(HttpMessageNotReadableException e, Model model) {
- logger.error("参数解析失败", e);
- String message = "【参数解析失败】" + e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 400);
- return viewName;
- }
- /**
- * 400 - Bad Request
- */
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e, Model model) {
- logger.error("参数验证失败", e);
- BindingResult result = e.getBindingResult();
- FieldError error = result.getFieldError();
- String field = error.getField();
- String code = error.getDefaultMessage();
- String message = "【参数验证失败】" + String.format("%s:%s", field, code);
- model.addAttribute("message", message);
- model.addAttribute("code", 400);
- return viewName;
- }
- /**
- * 400 - Bad Request
- */
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(BindException.class)
- public String handleBindException(BindException e, Model model) {
- logger.error("参数绑定失败", e);
- BindingResult result = e.getBindingResult();
- FieldError error = result.getFieldError();
- String field = error.getField();
- String code = error.getDefaultMessage();
- String message = "【参数绑定失败】" + String.format("%s:%s", field, code);
- model.addAttribute("message", message);
- model.addAttribute("code", 400);
- return viewName;
- }
- /**
- * 400 - Bad Request
- */
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(ConstraintViolationException.class)
- public String handleServiceException(ConstraintViolationException e, Model model) {
- logger.error("参数验证失败", e);
- Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
- ConstraintViolation<?> violation = violations.iterator().next();
- String message = "【参数验证失败】" + violation.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 400);
- return viewName;
- }
- /**
- * 400 - Bad Request
- */
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(ValidationException.class)
- public String handleValidationException(ValidationException e, Model model) {
- logger.error("参数验证失败", e);
- String message = "【参数验证失败】" + e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 400);
- return viewName;
- }
- /**
- * 404 - Not Found
- */
- @ResponseStatus(HttpStatus.NOT_FOUND)
- @ExceptionHandler(NoHandlerFoundException.class)
- public String noHandlerFoundException(NoHandlerFoundException e, Model model) {
- logger.error("Not Found", e);
- String message = "【页面不存在】" + e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 404);
- System.out.println("404404错误");
- return viewName;
- }
- /**
- * 405 - Method Not Allowed
- */
- @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
- @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
- public String handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, Model model) {
- logger.error("不支持当前请求方法", e);
- String message = "【不支持当前请求方法】" + e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 405);
- return viewName;
- }
- /**
- * 415 - Unsupported Media Type
- */
- @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
- @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
- public String handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e, Model model) {
- logger.error("不支持当前媒体类型", e);
- String message = "【不支持当前媒体类型】" + e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 415);
- return viewName;
- }
- /**
- * 业务层需要自己声明异常的情况
- */
- @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
- @ExceptionHandler(ServiceException.class)
- public String handleServiceException(ServiceException e, Model model) {
- logger.error("业务逻辑异常", e);
- String message = "【业务逻辑异常】" + e.getMessage();
- model.addAttribute("message", message);
- return viewName;
- }
- /**
- * 获取其它异常。包括500
- *
- * @param e
- * @return
- * @throws Exception
- */
- @ExceptionHandler(value = Exception.class)
- public String defaultErrorHandler(Exception e, Model model) {
- logger.error("Exception", e);
- String message = e.getMessage();
- model.addAttribute("message", message);
- model.addAttribute("code", 500);
- return viewName;
- }
- }
注意修改 37 行的错误页面地址
不知道为什么 404 页面无法捕获
2、这是一个我们自定义的异常,通常我们可以主动抛它,当然,也可以直接抛 Exception
CustomException.java
- package com.liuyanzhao.forum.exception;
- /**
- * 自定义异常
- * @author 言曌
- * @date 2018/3/20 下午12:50
- */
- public class CustomException extends RuntimeException {
- /** serialVersionUID */
- private static final long serialVersionUID = 6417641452178955756L;
- public CustomException() {
- super();
- }
- public CustomException(String message) {
- super(message);
- }
- public CustomException(Throwable cause) {
- super(cause);
- }
- public CustomException(String message, Throwable cause) {
- super(message, cause);
- }
- }
3、在 template 或者资源根目录下新建 error 文件夹
error.html
- <div class="error-page">
- ${code=} <span th:text="${code}"></span>
- <h2 class="headline text-red" th:text="${code}"></h2>
- <div class="error-content" style="margin-top: 120px;">
- <h3><i class="fa fa-warning text-red"></i> 天哪! 好像遇到了错误.</h3>
- <p style="font-size: 1.2em;">
- 错误信息: <span th:text="${message}" class="text text-danger"></span>
- </p>
- <p><a href="javascript:history.go(-1)">返回上一页</a></p>
- <form class="search-form">
- <div class="input-group">
- <input type="text" name="search" class="form-control" placeholder="Search">
- <div class="input-group-btn">
- <button type="submit" name="submit" class="btn btn-danger btn-flat"><i class="fa fa-search"></i>
- </button>
- </div>
- </div>
- <!-- /.input-group -->
- </form>
- </div>
- </div>
- <!-- /.error-page -->
因为 404 页面好像无法捕获,那么我们可以再新建一个 404.html ,内容和上面差不多,改一下错误码为 404 即可。
4、为了演示使用,这里是 UserServiceImpl.java 里的一个添加新用户的方法
- @Transactional(rollbackFor = Exception.class)
- @Override
- public void saveUser(User user) {
- String username = user.getUsername();
- String nickname = user.getNickname();
- String password = user.getPassword();
- String email = user.getEmail();
- //1、非空判断
- if (username == null || nickname == null || password == null || email == null) {
- throw new CustomException("存在必填字段为空");
- } else {
- if (username.trim() == "" || password.trim() == "") {
- throw new CustomException("存在必填字段为空字符串");
- } else if(password.trim().length() < 6) {
- throw new CustomException("密码长度小于6位");
- }
- }
- //2、判断用户名是否合法
- if (username != null && username != "") {
- User user2 = userRepository.findByUsername(username);
- //2.1用户名已存在,不可以注册
- if (user2 != null) {
- throw new CustomException("用户名 " + username + " 已被使用");
- }
- }
- //3、判断Email是否合法
- if (email != null && email != "") {
- User user3 = userRepository.findByEmail(email);
- //1.1用户名已存在,不可以注册
- if (user3 != null) {
- throw new CustomException("Email " + email + "已被使用");
- }
- }
- //4、处理其他字段
- user.setCreateTime(System.currentTimeMillis());
- user.setEncodePassword(user.getPassword()); // 加密密码
- user.setIsBanned("N");//正常状态
- user.setNumberVoteUp(0);//票数
- user.setAvatar(AvatarUtil.getGravatar(email));//头像
- if (user.getNickname() == null) {
- user.setNickname(username);//默认昵称是用户名
- }
- userRepository.save(user);
- }
最终效果图
先看几个系统自动抛出的异常
1、页面不存在,400错误
2、编辑用户的时候,修改票数(一个 Integer 类型的字段),当我们填成字符串 421swsw 的时候,400错误
3、某个字段只允许一个字符如用户状态是否禁用Y或N,党输入abcd的时候,无法执行,数据库报异常
然后再看几个我们主动抛出的异常
2、添加用户的时候,设置了用户名字段为唯一性,500错误
3、密码小于 6 位
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏