前言 关于如何处理异常,我觉得这篇文章:Spring Boot统一异常处理最佳实践 说的挺好,有两个原则:
不使用随意返回各种数据类型, 要统一返回值规范.
不在业务代码中捕获任何异常, 全部交由 @ControllerAdvice 来处理.
1.自定义全局异常 这里以定义一个404错误异常为例,默认的springboot ,如果没有相应的路由,会抛出一个错误页,比如上面的图示。但是我想要返回一个自定义的错误页,或者是返回一个json字符串怎么办呢?如果想返回自定义的错误页,其实在resources文件夹下新建一个error.html就可以了,就可以覆盖默认的错误页了。如果想返回一个字符串,需要新建一个GlobalExceptionHandler类,加上 @RestControllerAdvice 注解,然后在配置文件中增加
1 2 3 4 5 6 7 8 9 10 spring.mvc.throw-exception-if-no-handler-found=true spring.resources.add-mappings=false spring: web: resources: add-mappings: false mvc: throw-exception-if-no-handler-found: true
GlobalExceptionHandler类中的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.proheng.gis.boot;import org.omg.CORBA.portable.ResponseHandler;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestControllerAdvice;import org.springframework.web.servlet.NoHandlerFoundException;@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler({Exception.class}) public String globalExceptionHandler (Exception e) { return "服务器错误" ; } @ExceptionHandler({NoHandlerFoundException.class}) @ResponseBody public String noHandlerFoundException (Exception e) { return "路由不存在" ; } }
2.继承ErrorController 如果不想写覆盖配置文件,那么就要继承ErrorController接口,并实现error和getErrorPath方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 package com.phkj.config;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.web.servlet.error.ErrorController;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import org.springframework.web.servlet.NoHandlerFoundException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import java.util.HashMap;import java.util.Map;@Controller @RestControllerAdvice public class GlobalExceptionHandler implements ErrorController { private final Logger logger= LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler({Exception.class}) @ResponseBody public String globalExceptionHandler (Exception e) { logger.error("全局错误" ,e); return "服务器错误" ; } @ExceptionHandler({NoHandlerFoundException.class}) @ResponseBody @ResponseStatus(HttpStatus.NOT_FOUND) public String noHandlerFoundException (Exception e) { logger.error("路由不存在" ,e); return "路由不存在" ; } @Override public String getErrorPath () { return "/error" ; } @RequestMapping(value = {"/error"}) @ResponseBody public Object error (HttpServletRequest request) { Map<String, Object> body = new HashMap <>(); body.put("error" , "not found" ); body.put("code" , "404" ); return body; } }
3.servlet中的404错误 我遇到的一个问题是,假如我在application.properties文件中配置了context-path
1 #server.servlet.context-path=/phkj
那么无论我怎么努力使用上面的方法,我都无法捕获到404错误。应用程序已经在运行了,但是总是进入不到springboot的处理流程中,直接就返回了404错误,这个问题估计是servlet的问题暂时还没有解决。
4.自定义全局异常后,无法进行视图映射 问题描述 在配置文件中配置了:spring.resources.add-mappings=false 之后,虽然能正常的拦截全局的异常了,但是在resources目录下的login.html等视图,也无法返回了,总是提示: No handler found for /login.html,比如我的一个方法,想返回login登录页,就没有办法返回了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.phkj.ctrl;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controller @RequestMapping("/") public class LinkCtrl { @RequestMapping("/login2") public String login () { return "login" ; } }
尝试添加Thymeleaf模板引擎 (1) 添加依赖
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-thymeleaf</artifactId > </dependency >
(2) 编写配置文件application.properties
1 2 3 4 5 6 spring.thymeleaf.prefix=classpath:/template/ spring.thymeleaf.check-template-location=true spring.thymeleaf.suffix=.html spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.mode=HTML5 spring.thymeleaf.cache=false
(3) 编写控制类
1 2 3 4 5 6 7 8 9 10 11 import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controller @RequestMapping("/") public class LinkCtrl { @RequestMapping("/login2") public String login () { return "login" ; } }
(4) 静态资源 对于静态资源要添加相应的静态资源映射,实现WebMvcConfigurer接口并重写addResourceHandlers方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration public class WebMvcCon implements WebMvcConfigurer { @Override public void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**" ).addResourceLocations("classpath:/META-INF/resources/" , "classpath:/static" ,"/static" , "/public" ); } }