• springboot 2.x处理404、500等异常


    404错误

    404错误是不经过Controller的,所以使用@ControllerAdvice或@RestControllerAdvice无法获取到404错误
    

    springboot2处理404错误的两种方式

    第一种:直接配置

    #出现错误时, 直接抛出异常
    spring.mvc.throw-exception-if-no-handler-found=true
    

    这种方式不太适用实际开发,比如和swagger集成时,访问/swagger-ui.html会出现404异常

    第二种:继承ErrorController来处理错误

    import org.springframework.boot.web.servlet.error.ErrorController;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Controller
    public class MyErrorController implements ErrorController {
    
        @RequestMapping("/error")
        public String handleError(HttpServletRequest request){
            //获取statusCode:401,404,500
            Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
            if(statusCode == 500){
                return "/error/500";
            }else if(statusCode == 404){
                //对应的是/error/404.html、/error/404.jsp等,文件位于/templates下面
                return "/error/404";
            }else if(statusCode == 403){
                return "/403";
            }else{
                return "/500";
            }
    
        }
    
    
        @Override
        public String getErrorPath() {
            return "/error";
        }
    }
    
    
    import com.bettn.common.util.Result;
    import com.bettn.common.util.WebUtils;
    import org.apache.shiro.ShiroException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.NoHandlerFoundException;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * 全局异常捕获处理
     */
    @RestControllerAdvice
    public class ExceptionControllerAdvice {
        private static final Logger logger= LoggerFactory.getLogger(ExceptionControllerAdvice.class);
    
    
    
        // 捕捉shiro的异常
        @ExceptionHandler(ShiroException.class)
        public Result handle401() {
            return new Result(401,"您没有权限访问!",null);
        }
    
    
        // 捕捉其他所有异常
        @ExceptionHandler(Exception.class)
        public Object globalException(HttpServletRequest request, HandlerMethod handlerMethod, Throwable ex) {
            if(WebUtils.isAjax(handlerMethod)){
                return new Result(getStatus(request).value(), "访问出错,无法访问: " + ex.getMessage(), null);
            }else {
                ModelAndView modelAndView = new ModelAndView();
                modelAndView.setViewName("/error/500"); //这里需要在templates文件夹下新建一个/error/500.html文件用作错误页面
                modelAndView.addObject("errorMsg",ex.getMessage());
                return modelAndView;
            }
    
        }
    
        /**
         * 判断是否是Ajax请求
         *
         * @param request
         * @return
         */
        public boolean isAjax(HttpServletRequest request) {
            return (request.getHeader("X-Requested-With") != null &&
                    "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString()));
        }
    //    @ExceptionHandler(Exception.class)
    //    public Result globalException(HttpServletRequest request, Throwable ex) {
    //        return new Result(getStatus(request).value(),"访问出错,无法访问: " + ex.getMessage(),null);
    //    }
    
    
        /**
         * 获取响应状态码
         * @param request
         * @return
         */
        private HttpStatus getStatus(HttpServletRequest request) {
            Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
            if (statusCode == null) {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
            return HttpStatus.valueOf(statusCode);
        }
    
        /**
         * 捕捉404异常,这个方法只在配置
         * spring.mvc.throw-exception-if-no-handler-found=true来后起作用
         * 
         */
        @ResponseStatus(HttpStatus.NOT_FOUND)
        @ExceptionHandler(NoHandlerFoundException.class)
        public Result handle(HttpServletRequest request,NoHandlerFoundException e) {
            System.out.println(12);
            return new Result(404,"没有【"+request.getMethod()+"】"+request.getRequestURI()+"方法可以访问",null);
        }
    }
    

    这个异常类与ExceptionControllerAdvice连用,ExceptionControllerAdvice类除了不能处理404异常以外,其他异常都可以处理,其中
    globalException异常这个方法会捕获500错误,导致MyErrorController无法捕获到500错误,从而跳转到500页面,也就是说MyErrorController在这个项目中
    只能捕获404异常

    500异常捕获

    500异常分为ajax和直接跳转500页面
    

    具体的异常捕获,代码如何下:

    
    // 捕捉其他所有异常
    @ExceptionHandler(Exception.class)
    public Object globalException(HttpServletRequest request, HandlerMethod handlerMethod, Throwable ex) {
        if(WebUtils.isAjax(handlerMethod)){
            return new Result(getStatus(request).value(), "访问出错,无法访问: " + ex.getMessage(), null);
        }else {
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("/error/500"); //这里需要在templates文件夹下新建一个/error/500.html文件用作错误页面
            modelAndView.addObject("errorMsg",ex.getMessage());
            return modelAndView;
        }
    
    }
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.core.annotation.AnnotationUtils;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.method.HandlerMethod;
    public class WebUtils extends org.springframework.web.util.WebUtils {
    	/**
    	 * 判断是否ajax请求
    	 * spring ajax 返回含有 ResponseBody 或者 RestController注解
    	 * @param handlerMethod HandlerMethod
    	 * @return 是否ajax请求
    	 */
    	public static boolean isAjax(HandlerMethod handlerMethod) {
    		ResponseBody responseBody = handlerMethod.getMethodAnnotation(ResponseBody.class);
    		if (null != responseBody) {
    			return true;
    		}
    		// 获取类上面的Annotation,可能包含组合注解,故采用spring的工具类
    		Class<?> beanType = handlerMethod.getBeanType();
    		responseBody = AnnotationUtils.getAnnotation(beanType, ResponseBody.class);
    		if (null != responseBody) {
    			return true;
    		}
    		return false;
    	}
    
    	public static String getCookieValue(HttpServletRequest request, String cookieName) {
    		Cookie cookie=getCookie(request, cookieName);
    		return cookie==null?null:cookie.getValue();
    	}
    
    	public static void removeCookie(HttpServletResponse response, String cookieName) {
    		setCookie(response, cookieName, null, 0);
    		
    	}
    
    	public static void setCookie(HttpServletResponse response, String cookieName, String cookieValue,
    			int defaultMaxAge) {
    		Cookie cookie=new Cookie(cookieName,cookieValue);
    		cookie.setHttpOnly(true);
    		cookie.setPath("/");
    		cookie.setMaxAge(defaultMaxAge);
    		response.addCookie(cookie);
    	}
    
    }
    
    

    TIP

    404、500页面需要放在/templates下,且确认配置了视图,如jsp、thymeleaf等,否则也会出现找不到页面,例如集成thymeleaf

    依赖

    <!-- thymeleaf模板引擎和shiro框架的整合,这个是与shiro集成的,一般不整合shiro就不需要这个依赖 -->
    <dependency>
        <groupId>com.github.theborakompanioni</groupId>
        <artifactId>thymeleaf-extras-shiro</artifactId>
        <version>${thymeleaf.extras.shiro.version}</version>
    </dependency>
    <!-- SpringBoot集成thymeleaf模板 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    

    配置

    spring:
      # 模板引擎
      thymeleaf:
        mode: HTML5
        encoding: utf-8
        # 禁用缓存
        cache: false
    

    404、500页面地址(目录结构)

    src/main/resources/templates/error/404.html
    src/main/resources/templates/error/500.html

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>500</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
    
    <!--
    直接使用${el}无法解析出el的值
    ${errorMsg}
    -->
    
    <h3>糟糕! 服务器出错啦~~(>_<)~~</h3>
    <div>
        异常信息如下:<br/>
        <p th:text="${errorMsg}"></p>
    </div>
    </body>
    </html>
    

    参考:https://www.jianshu.com/p/8d41243e7fba

  • 相关阅读:
    java线程读取文件,可以同时读写 202006031002
    JS,JQuery bug202005282020
    js,jquery缩小加载的图片202005131907
    spring boot/spring cloud + mybatis + mysql bug 20200513
    html2020042901,table元素之间的间距
    ie8-ie11浏览器bug2020042801
    css的bug2020042801
    xml读取解析bug20200423
    Poi读取word(doc)文档的文本或图片
    NOI2020专题
  • 原文地址:https://www.cnblogs.com/hzhh123/p/10881356.html
Copyright © 2020-2023  润新知