Struts2、Spring MVC4 框架下的ajax统一异常处理

简介: 本文算是struts2 异常处理3板斧、spring mvc4:异常处理 后续篇章,普通页面出错后可以跳到统一的错误处理页面,但是ajax就不行了,ajax的本意就是不让当前页面发生跳转,仅局部刷新,从而改善用户体验,基本思路是:把异常转换成json数据返回,这样ajax的回调函数,就能解析出错误原因。

本文算是struts2 异常处理3板斧spring mvc4:异常处理 后续篇章,普通页面出错后可以跳到统一的错误处理页面,但是ajax就不行了,ajax的本意就是不让当前页面发生跳转,仅局部刷新,从而改善用户体验,基本思路是:把异常转换成json数据返回,这样ajax的回调函数,就能解析出错误原因。

 

一、如何区分ajax请求与普通请求

打开firefox的调试工具观察一下:

普通的页面请求

jquery发起的ajax请求

对比一下,可以发现jquery发生的ajax请求,Request Headers里多出了x-requested-with,用它就可以判断是否ajax请求。

 

二、struts2框架

a) 先定义一个ajax通用异常

 1 package com.cnblogs.yjmyzz.exception;
 2 
 3 public class AjaxException extends Exception {    
 4 
 5     private static final long serialVersionUID = -8503861588580421151L;
 6 
 7     public AjaxException(String message) {
 8         super(message);
 9     }
10 
11 }
View Code

b) 然后修改异常拦截器

 1 package com.cnblogs.yjmyzz.interceptor;
 2 import javax.servlet.http.HttpServletRequest;
 3 
 4 import org.apache.logging.log4j.*;
 5 import org.apache.struts2.ServletActionContext;
 6 import org.springframework.util.StringUtils;
 7 import com.cnblogs.yjmyzz.exception.AjaxException;
 8 import com.opensymphony.xwork2.*;
 9 import com.opensymphony.xwork2.interceptor.*;
10 
11 public class ExceptionInterceptor extends AbstractInterceptor {
12 
13     private static final long serialVersionUID = -6358803554282730952L;
14     Logger logger = LogManager.getLogger();
15 
16     @Override
17     public String intercept(ActionInvocation ai) throws Exception {
18         String result = null;
19         try {
20             result = ai.invoke();
21         } catch (Exception e) {
22             logger.error(ai.toString(), e);
23             ai.getStack().push(new ExceptionHolder(e));
24             result = "error";
25 
26             HttpServletRequest request = ServletActionContext.getRequest();
27             String xRequestedWith = request.getHeader("X-Requested-With");
28             if (!StringUtils.isEmpty(xRequestedWith)) {
29                 // ajax请求
30                 // 转换成ajax异常,并放入stack中
31                 ai.getStack().push(
32                         new ExceptionHolder(new AjaxException(e.getMessage())));
33                 result = "ajax-error";
34             }
35         }
36         return result;
37     }
38 
39 }
View Code

c) 修改struts.xml文件

 1     <package name="base-default" extends="struts-default">
 2         <global-results>
 3             <result name="ajax-error">/WEB-INF/common/ajax-error.jsp</result>
 4             <result name="error">/WEB-INF/common/error.jsp</result>
 5         </global-results>
 6         <global-exception-mappings>
 7             <exception-mapping exception="com.cnblogs.yjmyzz.exception.AjaxException"
 8                 result="ajax-error" />
 9             <exception-mapping exception="java.lang.Exception"
10                 result="error" />
11         </global-exception-mappings>
12     </package>
View Code

即:返回ajax-error,异常类型为AjaxException,则交给/WEB-INF/common/ajax-error.jsp处理

d) ajax-error.jsp页面

1 <%@ page contentType="application/json;charset=UTF-8" language="java"%><%@ taglib prefix="s" uri="/struts-tags"%>{"error":"<s:property value="exception" />"}
View Code

即:如果出错,最终返回的是json串,类似:{"error":"com.cnblogs.yjmyzz.exception.AjaxException: / by zero"}

e) 然后调用ajax的地方

 1             $.ajax({
 2                 type:"GET",
 3                 url:"${pageContext.request.contextPath}/rest/orders/x",               
 4                 success: function(data, textStatus, jqXHR){
 5                     if (data.error!=undefined){
 6                         alert("错误:" + data.error);
 7                         return false;
 8                     }
 9                     //正常处理
10                     alert("ajax请求成功!");
11                 },
12                 error: function(jqXHR, textStatus, errorThrown){
13                     alert('error: ' + textStatus);
14                 }
15             });
View Code

如果服务端出异常,则ajax调用完成后,会弹出异常信息,否则按正常流程处理

 

三、Spring MVC4

a) 先修改Controller基类里的异常处理方法

 1     @ExceptionHandler
 2     public String exp(HttpServletRequest request, Exception ex) {
 3         String resultViewName = "errors/error";
 4 
 5         // 记录日志
 6         logger.error(ex.getMessage(), ex);
 7 
 8         // 根据不同错误转向不同页面
 9         if (ex instanceof BusinessException) {
10             resultViewName = "errors/biz-error";
11         } else {
12             // 异常转换
13             ex = new Exception("系统太累了,需要休息!");
14         }
15         request.setAttribute("ex", ex);
16 
17         String xRequestedWith = request.getHeader("X-Requested-With");
18         if (!StringUtils.isEmpty(xRequestedWith)) {
19             // ajax请求
20             resultViewName = "errors/ajax-error";
21 
22         }
23 
24         return resultViewName;
25     }
View Code

大致意思是,如果发现是ajax请求,则有异常,则交给"errors/ajax-error"视图处理

b) ajax-error.jsp页面

1 <%@ page contentType="application/json;charset=UTF-8" language="java"%><%Exception e = (Exception) request.getAttribute("ex");%>{"error":"<%=e.getClass().getSimpleName()%>","detail":"<%=e.getMessage()%>"}
View Code

c) 调用ajax的页面

 1             $.ajax({
 2                 type:"GET",
 3                 url:"${pageContext.request.contextPath}/common-exception",               
 4                 success: function(d, textStatus, jqXHR){
 5                     if (d.error!=undefined){
 6                         alert("错误:" + d.detail);
 7                         return false;
 8                     }
 9                     //其它正常处理
10                     alert("ajax请求成功!");
11                 },
12                 error: function(jqXHR, textStatus, errorThrown){
13                     alert('error: ' + textStatus);
14                 }
15             });
View Code

如果服务端返回异常,ajax得到的反馈内容大概是:{"error":"Exception","detail":"系统太累了,需要休息!"}

目录
相关文章
|
13天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
22天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
32 0
|
17天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
39 1
Spring 框架:Java 开发者的春天
|
9天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
25 2
|
9天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
53 1
|
17天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
23天前
|
人工智能 开发框架 Java
总计 30 万奖金,Spring AI Alibaba 应用框架挑战赛开赛
Spring AI Alibaba 应用框架挑战赛邀请广大开发者参与开源项目的共建,助力项目快速发展,掌握 AI 应用开发模式。大赛分为《支持 Spring AI Alibaba 应用可视化调试与追踪本地工具》和《基于 Flow 的 AI 编排机制设计与实现》两个赛道,总计 30 万奖金。
|
Java Spring
spring框架之AOP模块(面向切面),附带通知类型---超详细介绍
spring框架之AOP模块(面向切面),附带通知类型---超详细介绍
116 0
|
缓存 监控 Java
Spring框架之AOP(面向切面编程)
Spring框架之AOP(面向切面编程)
55 0
|
4月前
|
分布式计算 Java MaxCompute
详解 Java 限流接口实现问题之在Spring框架中使用AOP来实现基于注解的限流问题如何解决
详解 Java 限流接口实现问题之在Spring框架中使用AOP来实现基于注解的限流问题如何解决
下一篇
无影云桌面