Spring 全局请求处理:根据请求类型返回 JSON 或 HTML

在现代 Web 应用开发中,前后端分离的架构越来越普遍。为了更好地支持这种架构,Spring 框架提供了强大的功能来处理不同类型的请求,并根据请求的类型返回相应的响应格式,如 JSON 或 HTML。本文将介绍如何使用 Spring 的全局请求处理机制,根据请求类型动态返回 JSON 或 HTML 响应。

1. 配置 Thymeleaf 模板引擎

首先,我们需要配置 Thymeleaf 模板引擎,以便在需要时返回 HTML 页面。以下是 Thymeleaf 的基本配置:

spring:
  thymeleaf:
    cache: false  # 关闭缓存以方便开发
    mode: HTML5    # 使用 HTML5 模式
    encoding: UTF-8  # 设置字符编码
    prefix: classpath:/templates/  # 设置模板文件的前缀路径

2. 判断请求是否为 AJAX 请求

在处理请求时,我们需要判断请求是否为 AJAX 请求。如果是 AJAX 请求,我们通常希望返回 JSON 格式的数据;否则,返回 HTML 页面。以下是一个简单的判断方法:

public static boolean isAjaxRequest(HttpServletRequest request) {
    // 检查请求头中是否包含 "x-requested-with",通常 AJAX 请求会包含此头信息
    return request.getHeader("x-requested-with") != null;
}

3. 全局异常处理

为了统一处理应用中的异常,我们可以使用 @ControllerAdvice 注解来定义一个全局异常处理器。该处理器会根据请求类型返回不同的响应格式。

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.http.HttpStatus;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;

/**
 * 全局异常处理器
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    private static final String ERROR_PAGE = "error";  // 错误页面名称

    /**
     * 处理全局异常
     * @param httpServletRequest 请求对象
     * @param httpServletResponse 响应对象
     * @param e 异常对象
     * @return 根据请求类型返回 JSON 或 HTML 响应
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object handleException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Exception e) throws UnsupportedEncodingException {
        if (isAjaxRequest(httpServletRequest)) {
            // 如果是 AJAX 请求,返回 JSON 格式的错误信息
            return json(e);
        }
        // 否则返回 HTML 错误页面
        return view(e);
    }

    /**
     * 返回 JSON 格式的错误信息
     * @param e 异常对象
     * @return 自定义的响应对象
     */
    private ResponseX json(Exception e) {
        return new ResponseX();  // 这里返回项目中自定义的统一响应对象即可
    }

    /**
     * 返回 HTML 错误页面
     * @param e 异常对象
     * @return ModelAndView 对象
     */
    public ModelAndView view(Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setStatus(HttpStatus.BAD_REQUEST);  // 设置响应状态码
        modelAndView.setViewName(ERROR_PAGE);  // 设置视图名称
        modelAndView.addObject("msg", "错误信息");  // 添加错误信息
        modelAndView.addObject("code", "错误代码");  // 添加错误代码
        return modelAndView;
    }
}

4. 错误页面模板

当异常处理器返回 HTML 页面时,我们需要定义一个错误页面模板。以下是一个简单的 Thymeleaf 模板示例:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <head th:insert="fragments/header"/>
    <title>错误页面</title>
</head>
<body>
  <span th:text="${code}"></span> - <span th:text="${msg}"></span>
</body>
</html>

5. 避免使用拦截器处理异常

虽然拦截器在处理请求时非常有用,但它并不适合处理 Controller 中的异常。拦截器主要用于处理请求的前后逻辑,而异常处理通常需要在 Controller 层进行。以下是 Spring 中 DispatcherServlet 处理异常的代码片段:

private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, Exception ex) throws Exception {
    if (mappedHandler != null) {
        mappedHandler.triggerAfterCompletion(request, response, ex);
    }

    throw ex;  // 抛出异常,由异常处理器处理
}

通过使用 Spring 的 @ControllerAdvice 注解和 Thymeleaf 模板引擎,我们可以轻松地实现根据请求类型返回 JSON 或 HTML 响应的功能。这种机制不仅提高了代码的可维护性,还使得应用能够更好地适应前后端分离的架构。希望本文能帮助你在实际项目中更好地处理全局请求和异常。

标签: Java

相关文章

Java中线程池遇到父子任务示例及避坑

在Java中使用线程池可以有效地管理和调度线程,提高系统的并发处理能力。然而,当涉及到父子任务时,可能会遇到一些常见的Bug,特别是在子线程中查询数据并行处理时。本文将通过示例代码展示这些常见问...

java中异步任务的实现详解

在Java中实现异步任务是一种提高应用程序性能和响应性的常用技术。异步编程允许某些任务在等待其他任务完成时继续执行,从而避免了阻塞。本文将介绍几种在Java中实现异步任务的方法,并讨论它们的解决...

解密 ClassFinal 加密的 Java Jar包

ClassFinal 是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;可避免源码泄漏或字节码被反编译。要点...

图片Base64编码

CSR生成

图片无损放大

图片占位符

Excel拆分文件