一起来学SpringBoot(六)web开发与错误的处理

在互联网时代,我们所开发的应用大多是直面用户的,程序中的任何一点小疏忽都可能导致用户的流失,而程序出现异常往往又是不可避免的,那该如何减少程序异常对用户体验的影响呢?其实方法很简单,对异常进行捕获,然后给予相应的处理即可,springboot 提供了比较方便的错误处理方式。

首先呢我们新建一个springboot项目,并且新建一个百分百会出错的controller

package com.maoxs.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/web")
public class TestController {
@RequestMapping("/show")
public String show() throws Exception {
int i = 1 / 0;
return "成功";
}
}

下面来看错误的处理


ErrorController

package com.maoxs.controller;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}

@RequestMapping
@ResponseBody
public String doHandleError() {
return "出错了ErrorController";
}
}

然后哪启动项目用postman测试

可以看到 出错返回了


ControllerAdvice

package com.maoxs.controller;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
@ResponseBody
public class MyExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(HttpServletRequest req, Exception e) throws Exception {
e.printStackTrace();
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
throw e;
}
return "出错了ExceptionHandler";
}
}

然后就可以了依然用postman进行测试

依然达到效果。

不过呢做个说明,这个控制器不能识别是不是ajax,但是可以巧妙的通过异常类来区分,

只需要更改@ExceptionHandler(value = 自定义异常.class)即可。


BasicErrorController

BasicErrorController,这个是SpringBoot的默认错误处理,也是一种全局处理方式。咱们可以模仿这种处理方式自定义自己的全局错误处理 下面定义了一个自己的BasicErrorController,可以根据自己的需求自定义errorHtml()和error()的返回值。

package com.maoxs.controller;

import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Controller
public class MyBasicErrorController extends BasicErrorController {
public MyBasicErrorController(ServerProperties serverProperties) {
super(new DefaultErrorAttributes(), serverProperties.getError());
}

@Override
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
//请求的状态
HttpStatus status = getStatus(request);
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.TEXT_HTML));
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
//指定自定义的视图
return (modelAndView == null ? new ModelAndView("error/error", model) : modelAndView);
}

@Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
//输出自定义的Json格式
Map<String, Object> map = new HashMap<>();
map.put("status", false);
map.put("msg", "出错了出错了");
return new ResponseEntity<>(map, status);
}
}

切记要加controller 否则不会被扫描到注册

然后进行测试先试试页面好使不

没问题在试试 ajax调用


也没问题


自定义错误页面

在spring2.x后 自定义错误页面变的更简单只需要实现ErrorViewResolver即可

package com.maoxs.controller;

import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Controller
public class MyErrorViewResolver implements ErrorViewResolver {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
if (status.value() == 400) {
return new ModelAndView("error/400");
}
return new ModelAndView("error/500");
}
}


映射Spring MVC之外的错误页面

添加如下配置即可

@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return new MyErrorPageRegistrar();
}

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "具体你的path"));
registry.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "具体你的path"));
}
}

具体呢各种方法有各种方法的用途,我个人比较喜欢第继承BasicErrorController更灵活的处理还可以扩展。

ControllerAdvice 处理有一定的局限性只有进入 Controller 层的错误,才会由 @ControllerAdvice 处理。

本博文是基于springboot2.x 如果有什么不对的请在下方留言。