目标
- 使用异常映射机制将整个项目的异常和错误提示进行统一管理。
思路
注意:
- springmvc 提供了基于 xml和注解两种异常映射机制。
<mvc:view-controller>
是在xml文件中配置的 ,@RequestMapping
注解。
配置方式
基于 xml的
springmvc 全局配置文件
<!--配置基于xml 异常处理映射-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
id="simpleMappingExceptionResolver">
<!--配置异常类型和具体页面的对应关系-->
<property name="exceptionMappings">
<props>
<!--<prop key="异常">页面</prop>
key属性指定异常全类名
标签体中写对应的视图【这个值要拼写前后缀得到具体的路径】-->
<prop key="java.lang.Exception">system-error</prop>
</props>
</property>
</bean>
页面
<%--从域中取出 exceptiono对象,在进一步访问 message属性就能够显示错误信息。--%>
${pageContext.exception.message}
基于注解的
准备
- 判断当前请求时 普通请求还是 ajax请求 工具类
import javax.servlet.http.HttpServletRequest;
/**
* @author zhaokuii11@163.com
* @create 2021-12-01 20:59
* @Description 判断请求类型、ajax还是 普通的
*/
public class CrowdUtil {
/**
* 判断当前请求是 ajax还是 普通请求
* 判断依据:
* Accept : application/json; charset=utf-8
* X-requested-with: XMLHttpRequest
* 只要有一个就可以
*
* @param request 请求对象
* @return Boolean true ajax请求、false 普通请求
*/
public static boolean judgeRequestType(HttpServletRequest request) {
//1. 获取请求消息头
String accept = request.getHeader("Accept");
String xRequestedwith = request.getHeader("X-requested-with");
//2. 判断
if (accept != null && accept.contains("application/json") ||
xRequestedwith != null && xRequestedwith.contains("XMLHttpRequest")) {
return true;
}
return false;
}
}
ajax 工具类
/**
* @author zhaokuii11@163.com
* @create 2021-12-01 20:16
* @Description 统一整个项目中 Ajax请求返回的结果【未来也可以用户分布式框架各个模块间调用时返回统一类型】
*/
public class ResultEntity<T> {
public static final String SUCCESS = "success";
public static final String FAILED = "failed";
/**
* 用来封装当前请去处理的结果是成功还是失败
*/
private String result;
/**
* 请去处理失败时返回的错误信息
*/
private String message;
/**
* 要返回的数据
*/
private T data;
/**
* 请求处理成功且不需要返回数据使用的工具方法
* 【增删改的】
*
* @param <Type>
* @return
*/
public static <Type> ResultEntity<Type> successWithoutData() {
return new ResultEntity<Type>(SUCCESS, null, null);
}
/**
* 请求处理成功且需要返回数据的方法
* 【查询的】
*
* @param data 要返回的数据
* @param <Type>
* @return
*/
public static <Type> ResultEntity<Type> successWithData(Type data) {
return new ResultEntity<Type>(SUCCESS, null, data);
}
/**
* 请求处理失败使用的工具方法
* 【失败的】
*
* @param message 失败的错误消息
* @param <Type>
* @return
*/
public static <Type> ResultEntity<Type> failed(String message) {
return new ResultEntity<Type>(FAILED, message, null);
}
public ResultEntity() {
}
public ResultEntity(String result, String message, T data) {
this.result = result;
this.message = message;
this.data = data;
}
@Override
public String toString() {
return "ResultEntity{" +
"result='" + result + '\'' +
", message='" + message + '\'' +
", data=" + data +
'}';
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
编写
import com.aiguigu.crowd.util.CrowdUtil;
import com.aiguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author zhaokuii11@163.com
* @create 2021-12-01 21:14
* @Description
*/
//@ControllerAdvice 表示当前类是一个基于注解的异常处理类
@ControllerAdvice
public class CrowdExceptionResolver {
// @ExceptionHandler 将一个具体的异常类型和一个方法关联起来【里面是一个数组】
@ExceptionHandler(value = NullPointerException.class)
public ModelAndView resolveNullPointException(
//实际捕获的德类型
NullPointerException exception,
//当前请求对象
HttpServletRequest request,
//当前响应对象
HttpServletResponse response) throws IOException {
//1. 判断当前请去
boolean requestType = CrowdUtil.judgeRequestType(request);
//2. 如果 Ajax请求
if (requestType) {
//3. 创建 ResultEntity 对象
ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
//4. 消息转为 json对象,创建 gson对象
Gson gson = new Gson();
//5. 将 json字符串作为响应体返回给浏览器
String json = gson.toJson(resultEntity);
//6. 将 json字符串作为响应体返回给浏览器
response.getWriter().print(json);
//7. 由于上面通过原生的 response对象返回了响应,所以不提供 modelAndView对象
return null;
}
//8. 如果不是 Ajax请去则创建 ModelAndView对象
ModelAndView view = new ModelAndView();
//9. 将 exception对象存入模型
view.addObject("exception", exception);
//10. 设置对应的视图
view.setViewName("system-error");
//11. 返回
return view;
}
/**
* 抽取公共代码
*
* @param viewName 发生异常要去的页面
* @param exception 发生的异常
* @param request
* @param response
* @return
* @throws IOException
*/
private ModelAndView commonResolve(
//要去的视图
String viewName,
//实际捕获的德类型
Exception exception,
//当前请求对象
HttpServletRequest request,
//当前响应对象
HttpServletResponse response) throws IOException {
//1. 判断当前请去
boolean requestType = CrowdUtil.judgeRequestType(request);
//2. 如果 Ajax请求
if (requestType) {
//3. 创建 ResultEntity 对象
ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
//4. 消息转为 json对象,创建 gson对象
Gson gson = new Gson();
//5. 将 json字符串作为响应体返回给浏览器
String json = gson.toJson(resultEntity);
//6. 将 json字符串作为响应体返回给浏览器
response.getWriter().print(json);
//7. 由于上面通过原生的 response对象返回了响应,所以不提供 modelAndView对象
return null;
}
//8. 如果不是 Ajax请去则创建 ModelAndView对象
ModelAndView view = new ModelAndView();
//9. 将 exception对象存入模型
view.addObject("exception", exception);
//10. 设置对应的视图
view.setViewName(viewName);
//11. 返回
return view;
}
/**
* 优化
*
* @param exception
* @param request
* @param response
* @return
* @throws IOException
*/
@ExceptionHandler(value = ArithmeticException.class)
public ModelAndView resolveArithmeticException(
//实际捕获的德类型
NullPointerException exception,
//当前请求对象
HttpServletRequest request,
//当前响应对象
HttpServletResponse response) throws IOException {
return commonResolve("system-error", exception, request, response);
}
}