# 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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。