作用

  1. 当程序出现异常时,跳转到指定异常页面,而不是服务器错误页面
  2. 当通过接口请求时,如果参数不对,可以抛出异常信息给前端
  3. 减少模版代码,使代码更简洁

接口校验类

自定义接口校验类,用于校验参数。

public class ApiAssert {
	
	public static void isNull(Object object, String message) {
	    if (object != null) {
	      throw new ApiException(message);
	    }
	  }

	  public static void notNull(Object object, String message) {
	    if (object == null) {
	      throw new ApiException(message);
	    }
	  }

	  public static void isTrue(boolean expression, String message) {
	    if (!expression) {
	      throw new ApiException(message);
	    }
	  }

	  public static void notTrue(boolean expression, String message) {
	    if (expression) {
	      throw new ApiException(message);
	    }
	  }

	  public static void isEmpty(String txt, String message) {
	    if(!StringUtils.isEmpty(txt)) {
	      throw new ApiException(message);
	    }
	  }

	  public static void notEmpty(String txt, String message) {
	    if(StringUtils.isEmpty(txt)) {
	      throw new ApiException(message);
	    }
	  }
}

接口异常类

自定义接口异常类,如果参数不对,则抛出这个异常

public class ApiException extends RuntimeException {

	private int code;
	private String message;

	public ApiException(String message) {
		this.code = 201;
		this.message = message;
	}

	public ApiException(int code, String message) {
		this.code = code;
		this.message = message;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

}

全局异常处理类

自定义一个全局异常处理类,加上@ControllerAdvice注解并加入容器中

@ControllerAdvice
@Component
public class GlobalExceptionHandler {
	
	/**
	 * 错误页面统一处理
	 * @param request
	 * @param e
	 * @return
	 * @throws Exception
	 */
	@ExceptionHandler(value = Exception.class)
	public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) throws Exception {
	    e.printStackTrace();
	    ModelAndView mav = new ModelAndView();
	    mav.addObject("exception", e.getMessage());
	    mav.setViewName("error/error");
	    return mav;
	  }
	
	/**
	 * 接口错误统一处理
	 * @param e
	 * @return
	 * @throws ApiException
	 */
	@ExceptionHandler(value = ApiException.class)
	@ResponseBody
	public Map<Integer,String> jsonErrorHandler(ApiException e) throws ApiException{
		Map<Integer,String> map = new HashMap<>();
		map.put(201, e.getMessage());
		return map;
	}
}

ControllerAdvice, 类注解, 作用于 整个 Spring 工程. ControllerAdvice 注解定义了一个全局的异常处理器

ExceptionHandler, 方法注解, 作用于 Controller 级别. ExceptionHandler 注解为一个 Controler 定义一个异常处理器

GlobalExceptionHandler类加入容器

<!-- 全局异常处理 -->
	<context:component-scan base-package="cn.roothub.handler" />

异常页面

新建一个error文件,里面在新建一个error.jsp页面,用于跳转。

<div class="panel-body">
      <h1>: (</h1>
      <p>${exception}</p>
    </div>

示例

普通请求

@RequestMapping(value = "/topic/{id}", method = RequestMethod.GET)
private String detail(@PathVariable Integer id, Model model,@RequestParam(value = "p", defaultValue = "1") Integer p,HttpServletRequest request) {
		Topic topic = rootTopicService.findByTopicId(id);
		if(topic == null) {
			throw new RuntimeException("话题不存在");
		}

用户发起查看话题的请求,参数是id,后台通过id查询数据库,得到一个Topic对象。如果此时Topic对象为空,则抛出RuntimeException异常,并携带异常信息。Controller层抛出异常后,会被我们自定义的全局异常处理类GlobalExceptionHandler捕获,并进入defaultErrorHandler方法,跳转到error错误页面。

我们来访问一个不存在的话题试试

image

异常抛出了,跳转到我们指定的异常页面并携带了异常信息!

接口请求

@RequestMapping(value = "/topic/{id}", method = RequestMethod.GET)
@ResponseBody
private String detail(@PathVariable Integer id, Model model,@RequestParam(value = "p", defaultValue = "1") Integer p,HttpServletRequest request) {
		Topic topic = rootTopicService.findByTopicId(id);
		ApiAssert.notNull(topic, "话题消失了~");

继续访问一个不存在的话题试试

image

异常抛出了,并输出了异常信息!

原文链接:https://miansen.wang/2018/11/01/1/