全局异常处理
# 全局异常处理
在Web开发中,异常处理是保证系统稳定性和用户体验的重要部分。若依框架通过全局异常处理器来统一管理各种异常,从而避免了在每个业务模块中重复编写异常处理代码。本文将详细介绍如何在若依框架中实现全局异常处理,并涵盖常见的异常场景、注意事项和扩展方法。
# 一、统一返回实体定义
为了统一处理异常和返回结果,若依框架定义了一个 AjaxResult
类,用于封装操作结果。该类继承自 HashMap
,可以灵活地添加自定义字段。
package com.ruoyi.common.core.domain;
import java.util.HashMap;
/**
* 操作消息提醒
*
* @author ruoyi
*/
public class AjaxResult extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/**
* 返回错误消息
*
* @param msg 错误消息内容
* @return 错误消息封装对象
*/
public static AjaxResult error(String msg)
{
AjaxResult json = new AjaxResult();
json.put("msg", msg);
json.put("code", 500); // 错误状态码
return json;
}
/**
* 返回成功消息
*
* @param msg 成功消息内容
* @return 成功消息封装对象
*/
public static AjaxResult success(String msg)
{
AjaxResult json = new AjaxResult();
json.put("msg", msg);
json.put("code", 0); // 成功状态码
return json;
}
}
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
# 二、自定义异常定义
在实际业务中,可能会需要定义一些自定义异常来处理特定的业务逻辑。例如,用户未登录时抛出登录异常 LoginException
。
package com.ruoyi.common.exception;
/**
* 登录异常
*
* @author ruoyi
*/
public class LoginException extends RuntimeException
{
private static final long serialVersionUID = 1L;
protected final String message;
public LoginException(String message)
{
this.message = message;
}
@Override
public String getMessage()
{
return message;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 三、全局异常处理器的实现
通过使用 @ControllerAdvice
和 @ExceptionHandler
注解,可以捕获全局范围内的异常,并进行统一处理。若依框架的全局异常处理器 GlobalExceptionHandler
是一个很好的示例。
package com.ruoyi.framework.web.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.LoginException;
/**
* 全局异常处理器
*
* @author ruoyi
*/
@RestControllerAdvice // 自动将返回的数据封装为JSON格式
public class GlobalExceptionHandler
{
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理登录异常
*
* @param e 登录异常对象
* @return 处理后的AjaxResult封装对象
*/
@ExceptionHandler(LoginException.class)
public AjaxResult loginException(LoginException e)
{
log.error(e.getMessage(), e); // 记录错误日志
return AjaxResult.error(e.getMessage()); // 返回错误信息
}
}
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
注意:
- 使用
@RestControllerAdvice
注解可以确保所有异常处理方法返回的结果都是 JSON 格式。- 通过
@ExceptionHandler
注解,可以定义具体的异常处理逻辑。
# 四、异常处理示例
为了演示全局异常处理器的工作流程,我们可以在一个控制器中模拟抛出异常。
@Controller
public class SysIndexController
{
/**
* 首页方法
*/
@GetMapping("/index")
public String index(ModelMap mmap)
{
// 模拟用户未登录,抛出业务逻辑异常
SysUser user = ShiroUtils.getSysUser();
if (StringUtils.isNull(user))
{
throw new LoginException("用户未登录,无法访问请求。"); // 抛出自定义登录异常
}
mmap.put("user", user);
return "index";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
当用户未登录时,访问 /index
会抛出 LoginException
异常,根据全局异常处理器的配置,系统会捕获该异常,并返回一个 AjaxResult
封装的 JSON 数据。
输出示例:
{
"msg": "用户未登录,无法访问请求。",
"code": 500
}
2
3
4
# 五、针对不同请求类型的异常处理
在某些情况下,同一个异常处理方法需要返回不同类型的响应。例如,对于 AJAX 请求返回 JSON 数据,而对于普通页面请求则返回 HTML 页面。这可以通过检查请求类型来实现。
@ExceptionHandler(LoginException.class)
public Object loginException(HttpServletRequest request, LoginException e)
{
log.error(e.getMessage(), e);
// 判断请求是否为AJAX请求
if (ServletUtils.isAjaxRequest(request))
{
return AjaxResult.error(e.getMessage()); // 返回JSON数据
}
else
{
return new ModelAndView("/error/500"); // 返回500错误页面
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 六、注意事项与扩展
# 1. 使用 @RestControllerAdvice
注解
如果你希望所有异常处理方法都返回 JSON,可以使用 @RestControllerAdvice
注解。这会使得返回的数据自动封装为 JSON,而不需要在每个方法上添加 @ResponseBody
注解。
# 2. 无法捕获异常的原因
如果你发现某些异常无法被全局异常处理器捕获,可以检查以下几点:
- 异常是否已被业务代码中的
try-catch
块捕获并处理。 - 异常是否是在
Controller
之外抛出的,例如在拦截器或过滤器中。
# 3. 扩展异常处理器
你可以根据需要扩展全局异常处理器,添加对更多自定义异常或框架异常的处理。例如,处理数据库连接异常、数据完整性异常等。
# 七、总结
全局异常处理器的引入极大地简化了异常处理逻辑,使得控制器中的业务代码更加简洁。通过合理使用 @ControllerAdvice
和 @ExceptionHandler
,可以有效地管理和响应各种异常,提升系统的稳定性和用户体验。
- 统一处理: 全局异常处理器让异常处理逻辑集中管理,避免代码重复。
- 灵活扩展: 可以根据业务需求灵活扩展异常处理器,处理不同类型的异常。
- 自动化返回: 使用
@RestControllerAdvice
简化了 JSON 数据的返回处理。