三. 后端服务器自定义异常
三.一 提示信息和内容自定义
SpringBoot 提供的页面和属性信息,有时候不符合业务场景,需要后端开发人员进行自定义(自带的 message 是英文的,不符合国人习惯)
我们可以自定义修改
package top.yueshushu.learn.error; import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.stereotype.Component; import org.springframework.web.context.request.WebRequest; import java.util.Map; /** * @ClassName:MyErrorAttributes * @Description 后端自定义的提示信息 * @Author zk_yjl * @Date 2021/11/24 17:34 * @Version 1.0 * @Since 1.0 **/ @Component public class MyErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace); //也可以放置其他的属性信息,或者替换属性,如 message,或者 timestamp if ((Integer)map.get("status") == 500) { map.put("message", "服务器内部错误!"); } if ((Integer)map.get("status") == 404) { map.put("message", "页面找不到!"); } if ((Integer)map.get("status") == 403) { map.put("message", "未授权!"); } return map; } }
提示信息发生了改变,变成了开发人员自定义的提示信息.
三.二 自定义视图解析和返回内容
将 MyErrorAttributes 去掉 @Component 组件注解
继承DefaultErrorViewResolver 解析视图类
@Component public class MyErrorViewResolver extends DefaultErrorViewResolver { /** 构造方法 */ public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) { super(applicationContext, resourceProperties); } @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { // 可以根据状态 status, 自定义视图页面和 model //不能直接修改 model Map<String, Object> newMap = new HashMap<>(); for(Map.Entry<String,Object> entry:model.entrySet()){ newMap.put(entry.getKey(),entry.getValue()); } newMap.put("findUser","两个蝴蝶飞"); // NOT_FOUND(404, "Not Found"), if(HttpStatus.NOT_FOUND.equals(status)){ return new ModelAndView("/self/404.html",newMap); } // 500错误 // INTERNAL_SERVER_ERROR(500, "Internal Server Error"), if(HttpStatus.INTERNAL_SERVER_ERROR.equals(status)){ return new ModelAndView("/self/500.html",newMap); } //走一个默认的页面 return new ModelAndView("/static/error/500.html",newMap); } }
在 template 目录下, 创建 self , 后续创建 500.html, 404.html
500.html , 404.html 添加一个自定义的属性, 就是 findUser
四. 前后端处理自定义异常信息
现在的项目,都是前后端分离的项目,希望在出现异常时,返回的是一个 json格式的数据,并不是跳转到页面。
前端开发人员,拿到错误的信息之后,个性化进行处理.
去掉 MyErrorViewResolver 上面的 @Component 注解
同时,去掉 自定义的 静态异常和动态异常信息, 将 error 文件夹重命名为 error2
四.一 定义异常信息
四.一.一 统一返回结果 OutputResult
@Data public class OutputResult implements Serializable { /** * @param code 响应代码 * @param message 响应信息 * @param data 响应的数据 */ private Integer code; private String message; private Map<String,Object> data=new HashMap<String,Object>(); /** * 构造方法 私有。 避免外部构造 */ private OutputResult(){ } /** * 成功 * @return */ public static OutputResult fail(){ OutputResult outputResult=new OutputResult(); outputResult.code=500; outputResult.message="失败"; return outputResult; } /** * 成功 * @return */ public static OutputResult fail(String message){ OutputResult outputResult=new OutputResult(); outputResult.code=500; outputResult.message=message; return outputResult; } /** * 成功 * @return */ public static OutputResult success(){ OutputResult outputResult=new OutputResult(); outputResult.code=200; outputResult.message="成功"; return outputResult; } /** * 成功 * @param data 要响应的数据 * @return */ public static OutputResult success(Object data){ OutputResult outputResult=new OutputResult(); outputResult.code=200; outputResult.message="成功"; outputResult.data.put("result",data); return outputResult; } }
四.一.二 自定义的异常类 BusinessException
public class BusinessException extends Exception { String message=""; public BusinessException(String message){ super(message); this.message=message; } public void setMessage(String message) { this.message = message; } @Override public String getMessage() { return message; } }
四.一.三 Controller 层异常方法 ExceptionController
@Controller public class ExceptionController { @RequestMapping("/") public String index(){ return "index"; } /** * 会出现除 0异常 * @date 2021/11/9 20:54 * @author zk_yjl * @param * @return java.lang.String */ @RequestMapping("/div") @ResponseBody public OutputResult div(){ int result=10/0; return OutputResult.success(result); } /** * 会出现空指针异常 * @date 2021/11/9 20:54 * @author zk_yjl * @param * @return java.lang.String */ @RequestMapping("/npe") @ResponseBody public OutputResult npe(){ String str=null; return OutputResult.success(str.length()); } /** * 会出现下标越界异常 * @date 2021/11/9 20:54 * @author zk_yjl * @param * @return java.lang.String */ @RequestMapping("/array") @ResponseBody public OutputResult array(){ String[] arr=new String[]{"岳泽霖","两个蝴蝶飞"}; return OutputResult.success(arr[arr.length]); } /** * 会出现下业务型异常 * @date 2021/11/9 20:54 * @author zk_yjl * @param * @return java.lang.String */ @RequestMapping("/bus") @ResponseBody public OutputResult bus() throws BusinessException { try{ int aa=10/0; }catch (Exception e){ //去查询数据库 throw new BusinessException("查询数据库失败了"); } return OutputResult.success("查询数据库成功"); } /** * 会出现下业务型异常 * @date 2021/11/9 20:54 * @author zk_yjl * @param * @return java.lang.String */ @RequestMapping("/other") @ResponseBody public OutputResult other() throws Exception { //去查询数据库 try{ int aa=10/0; }catch (Exception e){ //去查询数据库 throw new Exception("其他的异常信息"); } return OutputResult.success("查询数据库成功"); } }
进行调用时,
这样很不好看,也不方便管理.