您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# SpringBoot异常与重定向实现详解
## 一、异常处理基础概念
### 1.1 什么是异常处理
异常处理是编程中用于处理程序运行时出现的非正常情况的一种机制。在Spring Boot应用中,异常处理尤为重要,因为Web应用需要向用户提供友好的错误提示,而不是暴露堆栈信息。
Spring Boot提供了多种异常处理方式:
- 局部异常处理(Controller级别)
- 全局异常处理(应用级别)
- 默认错误页面机制
- 自定义错误属性配置
### 1.2 异常分类
在Java中,异常主要分为两类:
1. **受检异常(Checked Exception)**:必须被捕获或声明抛出
2. **非受检异常(Unchecked Exception)**:包括RuntimeException及其子类
Spring框架中常见的异常:
- `DataAccessException`:数据访问异常
- `ServletException`:Servlet相关异常
- `NoHandlerFoundException`:404处理异常
- `MethodArgumentNotValidException`:参数校验异常
## 二、Spring Boot异常处理机制
### 2.1 默认异常处理
Spring Boot默认提供了`/error`映射,当应用抛出异常时:
1. 对于浏览器客户端,返回一个"whitelabel"错误页面
2. 对于其他客户端,返回JSON响应
```java
{
"timestamp": "2023-05-20T10:30:15.123+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/api/resource"
}
可以在src/main/resources/templates/error/
目录下添加自定义错误页面:
404.html
:404错误专用页面5xx.html
:5xx系列错误通用页面error.html
:通用错误页面(优先级最低)最常用的全局异常处理方式是使用@ControllerAdvice
注解:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception e) {
ModelAndView mav = new ModelAndView("error");
mav.addObject("errorMsg", e.getMessage());
return mav;
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFound(UserNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(e.getMessage());
}
}
在单个Controller内部处理异常:
@RestController
@RequestMapping("/users")
public class UserController {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFound(UserNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body("用户不存在: " + e.getUserId());
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
// 业务逻辑
}
}
在Spring MVC中,重定向主要有两种方式:
redirect:
前缀RedirectView
对象@GetMapping("/old")
public String redirectOld() {
return "redirect:/new";
}
@GetMapping("/old2")
public RedirectView redirectOld2() {
RedirectView redirectView = new RedirectView();
redirectView.setUrl("/new");
return redirectView;
}
重定向时传递参数的几种方式:
@GetMapping("/search")
public String search(@RequestParam String query) {
return "redirect:/results?q=" + URLEncoder.encode(query, StandardCharsets.UTF_8);
}
@PostMapping("/login")
public String login(User user, RedirectAttributes attributes) {
attributes.addFlashAttribute("message", "登录成功!");
return "redirect:/dashboard";
}
在异常处理中实现重定向:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UnauthorizedException.class)
public String handleUnauthorized(UnauthorizedException e,
RedirectAttributes attributes) {
attributes.addFlashAttribute("error", "请先登录");
return "redirect:/login";
}
}
处理重定向过程中可能出现的异常:
@GetMapping("/secure")
public String securePage() {
try {
// 安全检查
return "secure-page";
} catch (SecurityException e) {
throw new UnauthorizedException("访问被拒绝");
}
}
对于RESTful API,通常返回JSON格式的错误信息:
@ControllerAdvice
@RestController
public class RestExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(
MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(x -> x.getField() + ": " + x.getDefaultMessage())
.collect(Collectors.toList());
ErrorResponse response = new ErrorResponse(
"参数校验失败",
HttpStatus.BAD_REQUEST.value(),
errors);
return ResponseEntity.badRequest().body(response);
}
}
完全接管Spring Boot的错误处理:
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomErrorController implements ErrorController {
@RequestMapping
public ResponseEntity<ErrorResponse> handleError(HttpServletRequest request) {
HttpStatus status = getStatus(request);
ErrorResponse response = new ErrorResponse(
status.getReasonPhrase(),
status.value(),
null);
return new ResponseEntity<>(response, status);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer code = (Integer) request.getAttribute(
RequestDispatcher.ERROR_STATUS_CODE);
return code != null ? HttpStatus.valueOf(code) : HttpStatus.INTERNAL_SERVER_ERROR;
}
}
处理异步请求(如AJAX)的异常:
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<ErrorResponse> handleAsyncException(Exception ex) {
ErrorResponse response = new ErrorResponse(
ex.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR.value(),
null);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(response);
}
结合Spring的国际化支持:
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(
MethodArgumentNotValidException ex,
Locale locale) {
String message = messageSource.getMessage(
"validation.error",
null,
locale);
// 其他处理逻辑
}
常见安全问题及解决方案:
private boolean isValidRedirect(String url) {
return url.startsWith("/") || allowedDomains.contains(getDomain(url));
}
合理的异常日志记录:
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex) {
if (ex instanceof BusinessException) {
log.warn("业务异常: {}", ex.getMessage());
} else {
log.error("系统异常", ex);
}
// 返回错误响应
}
使用MockMvc测试异常处理:
@Test
void testUserNotFound() throws Exception {
mockMvc.perform(get("/users/999"))
.andExpect(status().isNotFound())
.andExpect(jsonPath("$.message").value("用户不存在"));
}
验证重定向行为:
@Test
void testRedirect() throws Exception {
mockMvc.perform(get("/old"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/new"));
}
启用调试日志:
logging.level.org.springframework.web=DEBUG
使用拦截器:
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
if (ex != null) {
log.error("请求处理异常", ex);
}
}
完整示例:登录流程中的异常与重定向
@PostMapping("/login")
public String login(@Valid LoginForm form,
BindingResult result,
RedirectAttributes attributes,
HttpSession session) {
if (result.hasErrors()) {
attributes.addFlashAttribute(
"org.springframework.validation.BindingResult.form", result);
attributes.addFlashAttribute("form", form);
return "redirect:/login";
}
try {
User user = authService.authenticate(form);
session.setAttribute("currentUser", user);
return "redirect:/dashboard";
} catch (AuthException e) {
attributes.addFlashAttribute("error", "用户名或密码错误");
return "redirect:/login";
}
}
通过本文的全面介绍,相信您已经掌握了Spring Boot中异常处理与重定向的各种实现方式和最佳实践。在实际项目中,应根据具体需求选择合适的技术方案,并注意安全性和性能优化。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。