Exception Handling Techniques in Spring MVC

使用 GPT-4o-mini 回答Java Q&A Hub

問題:

Exception Handling in Spring MVC

答案:

Exception handling in Spring MVC is a crucial aspect of building robust web applications. It allows developers to manage errors gracefully and provide meaningful feedback to users. Spring MVC provides several ways to handle exceptions, including:

1. Using @ControllerAdvice

@ControllerAdvice is a specialized annotation that allows you to handle exceptions globally across all controllers. You can define a class annotated with @ControllerAdvice and use @ExceptionHandler methods to handle specific exceptions.

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView handleResourceNotFound(ResourceNotFoundException ex) {
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("message", ex.getMessage());
        return modelAndView;
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ModelAndView handleGenericException(Exception ex) {
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("message", "An unexpected error occurred.");
        return modelAndView;
    }
}

2. Using @ExceptionHandler in Controllers

You can also define exception handling methods directly within your controller classes using the @ExceptionHandler annotation.

import org.springframework.web.bind.annotation.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MyController {

    @RequestMapping("/someEndpoint")
    public String someMethod() {
        // Some logic that may throw an exception
        throw new ResourceNotFoundException("Resource not found");
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    public ModelAndView handleResourceNotFound(ResourceNotFoundException ex) {
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("message", ex.getMessage());
        return modelAndView;
    }
}

3. Using @ResponseStatus

You can annotate your custom exception classes with @ResponseStatus to specify the HTTP status code that should be returned when the exception is thrown.

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

4. Custom Error Pages

You can configure custom error pages in your web.xml or using Spring Boot's application properties. For example, in application.properties:

server.error.whitelabel.enabled=false
server.error.path=/error

5. Using ResponseEntityExceptionHandler

If you want to handle exceptions in a more RESTful way, you can extend ResponseEntityExceptionHandler and override its methods to customize the response.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<Object> handleResourceNotFound(ResourceNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleGenericException(Exception ex) {
        return new ResponseEntity<>("An unexpected error occurred.", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Conclusion

Spring MVC provides a flexible and powerful way to handle exceptions. By using @ControllerAdvice, @ExceptionHandler, and custom exception classes, you can create a robust error handling mechanism that improves the user experience and makes your application easier to maintain.