SpringMVC 请求和响应

在构建高效且稳健的 Web 应用时,SpringMVC 框架的请求和响应机制宛如中枢神经系统,对整个应用的流畅运行起着决定性作用。从请求的接收、参数的绑定,到响应结果的生成与返回,每一个环节都蕴含着丰富的细节和强大的功能。接下来,让我们逐步深入剖析 SpringMVC 请求和响应的各个关键层面。

一、RequestMapping 注解:请求映射的核心纽带

建立请求与处理方法的关联

RequestMapping注解在 SpringMVC 体系中占据着举足轻重的地位,其核心使命是在请求 URL 和处理方法之间搭建起精准的对应桥梁。它具备极为灵活的应用方式,既能够标注在类上,也能作用于方法。

当作用于类时,它如同为整个控制器类划定了一个 "势力范围",定义了第一级的访问目录。例如,在RoleController类上标注@RequestMapping(path = "/role"),这就意味着该类内部所有处理方法的请求路径,都将以/role作为起始部分,类似于为这个类的所有功能设定了一个统一的命名空间。

而当RequestMapping注解用于方法时,它进一步细化了请求路径,作为第二级的访问目录。以RoleController类中的save方法为例,@RequestMapping(path = "/save", method = {RequestMethod.GET}),完整的请求路径就成为了/role/save,并且通过method属性明确限定了该方法仅接受GET请求方式。这就好比在一个大型商场中,类级别注解确定了某个区域,而方法级别注解则具体指向了该区域内的某一家店铺,同时还规定了进入这家店铺的特定方式(请求方法)。

这里需要注意一个细节,路径在书写时可以省略开头的/,此时表示从应用的根目录开始。不过,为了保证路径的清晰性和规范性,在实际开发中,强烈建议始终明确地使用/来分隔路径的各个部分,避免因路径格式不统一而引发潜在的问题。

注解属性详解

  1. path 与 valuepathvalue属性在功能上是完全等同的,它们都承担着指定请求路径 URL 的重任。在代码编写过程中,开发者可以根据个人偏好自由选择使用其中之一。例如,@RequestMapping(path = "/delete")@RequestMapping(value = "/delete")这两种写法,在效果上没有任何差异,都能准确地将请求映射到/delete这个路径上。这种设计为开发者提供了更多的灵活性,使得代码风格能够更好地符合团队或个人的习惯。
  2. methodmethod属性则专注于指定处理方法所允许的请求方式。通过设置该属性,如@RequestMapping(path = "/save", method = {RequestMethod.GET}),我们能够清晰地界定save方法仅处理GET请求。在实际的 Web 应用中,不同的业务操作往往对应着不同的请求方式,比如数据查询操作通常使用GET请求,而数据的创建、修改等操作则更适合采用POST请求。通过method属性对请求方式进行严格约束,不仅能够确保接口的安全性,还能使业务逻辑更加清晰、准确,有效避免因错误的请求方式导致的意外行为。

二、RequestMapping 的请求参数绑定:数据传递的顺畅通道

在 Web 应用的交互过程中,表单提交是用户向服务器传递数据的一种常见且重要的方式。SpringMVC 的请求参数绑定机制巧妙地解决了如何将表单提交的数据准确无误地传递给控制器方法参数的问题,极大地简化了数据处理流程。

绑定机制揭秘

表单提交的数据遵循典型的k=v(键值对)格式,例如username=haha&password=123。SpringMVC 在接收到这样的请求后,会依据特定的规则将这些请求参数与控制器方法中的参数进行绑定。其核心要求是提交表单的name属性值与控制器方法参数的名称必须严格一致,并且区分大小写。这就好比在一个钥匙与锁的系统中,表单name就是钥匙,而控制器方法参数就是对应的锁,只有两者完全匹配,才能成功开启数据传递的通道。

支持的数据类型广泛

  1. 基本数据类型和字符串类型 :对于这类简单数据类型的参数绑定,只要表单的name与方法参数名精确匹配,SpringMVC 就能自动完成绑定操作。以UserControllersave方法为例,@RequestMapping("/save") public String save(String username, Integer age),当表单中存在name分别为usernameage的输入框时,用户提交表单后,对应的数据值会精准地传递给save方法的usernameage参数,就像将物品准确无误地放入对应的容器中。
  2. 实体类型(JavaBean) :当需要将表单数据封装到一个 JavaBean 对象中时,同样要求表单的name与 JavaBean 中的属性名称保持一致。若 JavaBean 类中包含其他引用类型,情况会稍微复杂一些,此时表单的name属性需要编写成对象.属性的形式。例如,假设User类中包含一个Account对象,且Account类有一个money属性,那么在表单中就需要设置name="account.money",这样才能确保数据正确地绑定到User对象的account属性的money字段上。在UserControllersave2方法中,@RequestMapping("/save2") public String save2(User user),通过这种方式,表单数据能够完整且准确地填充到User对象中,实现了复杂数据结构的自动封装。
  3. 集合数据类型(List、map 集合等) :对于集合属性数据的封装,在 JSP 页面有着特定的编写方式。以List集合为例,假设User类中有一个List<Account> accounts属性,在 JSP 页面中,可以通过list[0].属性list[1].属性等形式来设置表单的name。例如,<input type="text" name="accounts[0].money"/>,这种写法能够让 SpringMVC 在接收到表单数据时,将对应的值正确地封装到User对象的accounts集合属性中,在UserControllersave3方法中得以体现。这一机制为处理包含集合数据的复杂业务场景提供了强大的支持,使得开发者能够轻松应对各种数据结构的处理需求。

与原生 Servlet API 对象的交互

在某些特殊的业务场景下,开发者可能需要直接操作原生的 Servlet API 对象,如HttpServletRequestHttpServletResponse。在 SpringMVC 的控制器方法中,使用这两个对象非常简便,只需在方法参数中直接声明它们即可。例如,在UserControllersave6方法中,@RequestMapping(value = "/save6.do", method = {RequestMethod.POST}) public String save6(HttpServletRequest request, HttpServletResponse response),通过这种方式,开发者可以在方法内部便捷地获取请求参数(如request.getParameter("username"))、操作HttpSession对象(request.getSession())以及对响应进行灵活处理(如设置响应头、输出响应内容等)。这一特性为处理一些复杂的业务逻辑以及与底层 Servlet 容器进行深度交互提供了极大的便利,使得开发者在面对各种复杂需求时能够游刃有余。

三、不常用但功能强大的注解:RequestParam

尽管在日常开发中,基于RequestMapping的常规参数绑定方式已经能够满足大多数场景的需求,但RequestParam注解在一些特定的业务场景下却展现出了独特的优势和灵活性。

精准的参数赋值控制

RequestParam注解的核心作用是将请求中的指定名称的参数精准地传递给控制器中的形参进行赋值,为参数绑定过程提供了更为精细的控制手段。

注解属性解析

  1. valuevalue属性用于明确指定请求参数中的名称。例如在DeptControllersave方法中,@RequestMapping("/save") public String save(@RequestParam(value = "username", required = false) String name),这里的value="username"表明,该注解会将请求中名为username的参数值赋给name形参。通过这种方式,开发者可以根据实际业务需求,灵活地指定请求参数与控制器形参之间的映射关系,即使请求参数的名称与形参名称不一致,也能实现准确的数据传递。
  2. requiredrequired属性用于确定请求参数中是否必须提供该参数,其默认值为true,即表示该参数在请求中是必须存在的。在上述例子中,required = false的设置意味着请求中可以不包含username参数。当请求中没有该参数时,name形参将被赋值为null。这一属性在处理一些可选参数的业务场景中具有极高的实用价值,比如在一个搜索接口中,某些搜索条件可能是可选的,通过设置required = false,可以使接口更加灵活,能够适应不同用户的查询需求,同时也增强了系统的容错性。

四、数据处理及跳转:多样化的结果呈现方式

在 SpringMVC 应用中,处理完请求后,如何将结果有效地呈现给用户是一个关键环节。SpringMVC 提供了多种灵活的方式来实现结果的跳转和数据的展示。

ModelAndView:灵活的数据与视图组合

通过设置ModelAndView对象,我们可以根据视图的名称,并借助视图解析器跳转到指定的页面。首先,需要在配置文件中定义视图解析器,例如:

xml

复制代码
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
    <property name="prefix" value="/html/" />
    <property name="suffix" value=".html" />
    <property name="templateMode" value="HTML5"/>
</bean>

在对应的控制器类中,可以这样使用ModelAndView

java

复制代码
@RequestMapping("/save3")
public ModelAndView save3() {
    System.out.println("执行了...");
    // 创建mv对象
    ModelAndView mv = new ModelAndView();
    // 把一些数据,存储到mv对象中
    mv.addObject("msg", "用户名或者密码已经存在");
    // 设置逻辑视图的名称
    mv.setViewName("suc");
    return mv;
}

在视图页面(如suc.html)中,可以通过相应的模板语法(这里假设使用 Thymeleaf)来获取并展示数据:

html

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 th:text="${msg}"></h1>
</body>
</html>

这种方式将数据和视图紧密结合,开发者可以方便地在控制器中设置数据,并指定要跳转的视图,视图解析器会根据配置将逻辑视图名称解析为实际的视图资源,实现数据的动态展示。

ServletAPI:直接操作响应的底层方式

借助 ServletAPI,我们可以实现更加底层和直接的响应控制,且不需要依赖视图解析器。

  1. 通过 HttpServletResponse 进行输出 :在控制器方法中,可以直接使用HttpServletResponsegetWriter()方法来向客户端输出内容。例如:

java

复制代码
@RequestMapping("/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
    rsp.getWriter().println("Hello,Spring BY servlet API");
}

这种方式适用于一些简单的文本输出场景,如返回纯文本格式的提示信息等。

  1. 通过 HttpServletResponse 实现重定向 :使用HttpServletResponsesendRedirect()方法可以实现页面的重定向。例如:

java

复制代码
@RequestMapping("/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
    rsp.sendRedirect("/SpringMVCDemo/html/suc.html");
}

通过这种方式,服务器会向客户端发送一个重定向响应,客户端接收到后会自动跳转到指定的 URL。

  1. 通过 HttpServletResponse 实现转发 :利用HttpServletRequestgetRequestDispatcher()方法结合forward()方法,可以实现请求的转发。例如:

java

复制代码
@RequestMapping("/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
    //转发
    req.setAttribute("msg", "hello");
    req.getRequestDispatcher("/html/suc.html").forward(req, rsp);
}

在转发过程中,请求和响应对象会被传递到目标资源,目标资源可以获取到之前设置的请求属性,从而实现数据的共享和页面的跳转。

SpringMVC:简洁高效的转发和重定向

通过 SpringMVC 自身提供的语法,我们可以简洁地实现转发和重定向操作,并且无需依赖视图解析器(在测试前,需要将视图解析器注释掉)。

java

复制代码
@RequestMapping(path = "/role")
public class RoleController {
    @RequestMapping("/test5")
    public String test5() {
        return "forward:/html/B.html";
    }

    @RequestMapping("/test6")
    public String test6() {
        return "redirect:/html/B.html";
    }
}

使用forward关键字表示请求转发,redirect关键字表示重定向。这种方式简洁明了,能够快速实现页面的跳转,在一些不需要复杂视图解析和数据传递的场景中非常实用。

五、ResponseBody 响应 json 数据:前后端数据交互的利器

在当今前后端分离的开发模式下,JSON 数据格式因其简洁性和通用性,成为前后端数据交互的首选格式。SpringMVC 通过@ResponseBody注解,能够轻松实现将控制器方法的返回值转换为 JSON 格式并响应给前端。

json 与 JavaBean 的转换依赖

在将 Java 对象转换为 JSON 以及将 JSON 数据绑定到 Java 对象的过程中,需要借助 Jackson 的相关 jar 包。在项目的依赖配置文件(如pom.xml)中,添加如下依赖:

xml

复制代码
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.0</version>
</dependency>

这些依赖包提供了强大的 JSON 处理功能,能够自动将 Java 对象转换为符合 JSON 格式规范的字符串,并在请求时将 JSON 数据绑定到对应的 Java 对象上。

实际应用示例

在控制器中,使用@ResponseBody注解非常简单。例如:

java

复制代码
@RequestMapping("/save6")
public @ResponseBody User save6(User user) {
    System.out.println(user);
    // 模拟,调用业务层代码
    user.setUsername("hello");
    user.setAge(100);
    // 把user对象转换成json,字符串,再响应。使用@ResposeBody注解 response.getWriter().print()
    return user;
}

当客户端发送请求到/save6时,SpringMVC 会自动将请求参数绑定到User对象上,然后执行方法逻辑。方法执行完毕后,由于@ResponseBody注解的作用,返回的User对象会被 Jackson 库自动转换为 JSON 格式,并写入 HTTP 响应体中返回给客户端。客户端接收到 JSON 数据后,可以方便地进行解析和处理,实现了前后端高效、便捷的数据交互。

需要注意的是,在 SpringMVC 中,如果要实现页面跳转,通常不建议使用 ajax,因为 ajax 主要用于异步获取数据,而页面跳转涉及到整个页面的重新加载和导航。相反,如果需要返回 JSON 数据给前端进行异步处理,使用 ajax 配合@ResponseBody注解则是非常合适的选择,能够充分发挥前后端分离架构的优势,提升用户体验。

六、SpringMVC 实现文件上传:强大的文件处理能力

在许多 Web 应用中,文件上传是一项常见的功能需求。SpringMVC 提供了完善的支持,使得文件上传的实现变得相对简单。

准备工作:导入依赖与配置解析器

首先,需要导入文件上传所需的 jar 包,在pom.xml中添加如下依赖:

xml

复制代码
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

这些依赖包提供了文件上传的核心功能。接着,在 SpringMVC 的配置文件(springmvc.xml)中配置文件上传解析器:

xml

复制代码
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--设置上传文件的总大小 8M = 8 * 1024 * 1024 -->
    <property name="maxUploadSize" value="8388608" />
</bean>

这里配置了文件上传的最大大小,以防止因上传过大文件导致系统资源耗尽或性能问题。

文件上传的具体实现

  1. 编写文件上传的 HTML 页面 :在 HTML 页面中,创建一个表单,并设置enctype="multipart/form-data",这是文件上传表单必须的属性,用于指定表单数据的编码类型。例如:

html

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传页面</title>
</head>
<body>
    <h2>文件上传示例</h2>
    <form id="uploadForm" action="/upload" method="post" enctype="multipart/form-data">
        <label for="fileInput">选择文件:</label>
        <input type="file" id="fileInput" name="file" required>
        <br>
        <input type="submit" value="上传文件">
    </form>
</body>
</html>

六、SpringMVC 实现文件上传:强大的文件处理能力(续)

文件上传的深入优化与拓展

  1. 文件类型校验 :在实际应用中,仅允许用户上传特定类型的文件是非常必要的,这有助于保障系统的安全性和数据的一致性。可以在控制器方法中对上传的文件类型进行校验。例如,在FileControllerupload方法中,可以通过获取文件的后缀名来判断文件类型:

java

复制代码
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
    // 获取文件的原始名称
    String originalFileName = file.getOriginalFilename();
    // 获取文件后缀名
    String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1).toLowerCase();
    // 定义允许上传的文件类型列表
    List<String> allowedExtensions = Arrays.asList("jpg", "png", "pdf", "docx");
    if (!allowedExtensions.contains(fileExtension)) {
        return "{\"data\":\"不允许上传该类型的文件,请上传jpg、png、pdf或docx文件\"}";
    }
    // 后续的文件保存逻辑不变
    String rootPath = request.getSession().getServletContext().getRealPath("WEB - INF/upload");
    File newFile = new File(rootPath + File.separator + originalFileName);
    if (!newFile.getParentFile().exists()) {
        newFile.getParentFile().mkdirs();
    }
    file.transferTo(newFile);
    return "{\"data\":\"success\"}";
}

通过这种方式,能够有效阻止用户上传恶意或不符合业务需求的文件类型,提升系统的安全性。

  1. 文件大小限制的精细化管理:虽然在配置文件中已经设置了文件上传的最大总大小,但在某些场景下,可能需要对单个文件的大小也进行限制。可以在控制器方法中结合配置文件中的最大文件大小限制,对上传文件进行更为细致的检查:

java

复制代码
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
    // 获取配置文件中的最大文件大小(假设在配置类中已经将其读取到一个变量中)
    long maxFileSize = applicationProperties.getMaxFileSize();
    if (file.getSize() > maxFileSize) {
        return "{\"data\":\"上传文件大小超过限制,请上传小于" + maxFileSize / (1024 * 1024) + "MB的文件\"}";
    }
    // 后续的文件类型校验和文件保存逻辑不变
    String originalFileName = file.getOriginalFilename();
    String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1).toLowerCase();
    List<String> allowedExtensions = Arrays.asList("jpg", "png", "pdf", "docx");
    if (!allowedExtensions.contains(fileExtension)) {
        return "{\"data\":\"不允许上传该类型的文件,请上传jpg、png、pdf或docx文件\"}";
    }
    String rootPath = request.getSession().getServletContext().getRealPath("WEB - INF/upload");
    File newFile = new File(rootPath + File.separator + originalFileName);
    if (!newFile.getParentFile().exists()) {
        newFile.getParentFile().mkdirs();
    }
    file.transferTo(newFile);
    return "{\"data\":\"success\"}";
}

这样,当用户上传的文件超过单个文件大小限制时,系统能够及时给出友好的提示,避免因文件过大导致的系统性能问题或上传失败。

  1. 多文件上传的实现与优化 :在一些业务场景中,用户可能需要一次性上传多个文件。SpringMVC 同样提供了对多文件上传的支持。在前端页面中,可以通过设置input标签的multiple属性来实现多文件选择:

html

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF - 8">
    <title>Title</title>
</head>
<body>
<h3>多文件上传</h3>
<form id="addForm" action="/SpringMvc/file/uploadMultiple" method="post" enctype="multipart/form - data">
    选择文件: <input type="file" name="files" multiple>
    <input type="submit" value="上传">
</form>
</body>
</html>

在后端控制器中,需要将方法参数定义为List<MultipartFile>类型,以接收多个上传的文件:

java

复制代码
@Controller
@RequestMapping("/file")
public class FileController {
    @RequestMapping(value = "/uploadMultiple", method = RequestMethod.POST)
    @ResponseBody
    public String uploadMultiple(@RequestParam("files") List<MultipartFile> files, HttpServletRequest request) throws IOException {
        for (MultipartFile file : files) {
            // 对每个文件进行处理,包括类型校验、大小校验和保存
            String originalFileName = file.getOriginalFilename();
            String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1).toLowerCase();
            List<String> allowedExtensions = Arrays.asList("jpg", "png", "pdf", "docx");
            if (!allowedExtensions.contains(fileExtension)) {
                return "{\"data\":\"不允许上传该类型的文件,请上传jpg、png、pdf或docx文件\"}";
            }
            long maxFileSize = applicationProperties.getMaxFileSize();
            if (file.getSize() > maxFileSize) {
                return "{\"data\":\"上传文件大小超过限制,请上传小于" + maxFileSize / (1024 * 1024) + "MB的文件\"}";
            }
            String rootPath = request.getSession().getServletContext().getRealPath("WEB - INF/upload");
            File newFile = new File(rootPath + File.separator + originalFileName);
            if (!newFile.getParentFile().exists()) {
                newFile.getParentFile().mkdirs();
            }
            file.transferTo(newFile);
        }
        return "{\"data\":\"success\"}";
    }
}

在多文件上传的处理过程中,同样需要对每个文件进行严格的类型和大小校验,以确保上传的文件符合系统要求。通过这种方式,能够极大地提升用户体验,方便用户一次性上传多个相关文件。

七、SpringMVC 的异常处理:保障系统稳定运行的防线

自定义异常处理器的深度应用与拓展

  1. 异常信息的日志记录 :在自定义异常处理器SysExceptionResolver中,除了将异常信息返回给用户,还可以将异常信息记录到日志文件中,以便后续排查问题。通过使用日志框架(如 Log4j 或 SLF4J),可以在resolveException方法中添加日志记录逻辑:

java

复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//...
public class SysExceptionResolver implements HandlerExceptionResolver {
    private static final Logger logger = LoggerFactory.getLogger(SysExceptionResolver.class);
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse, Object o, Exception e) {
        e.printStackTrace();
        SysException exception = null;
        if (e instanceof SysException) {
            exception = (SysException) e;
        } else {
            exception = new SysException("系统正在维护,请联系管理员");
        }
        // 记录异常信息到日志
        logger.error("发生异常", e);
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg", exception.getMessage());
        mv.setViewName("404");
        return mv;
    }
}

通过这种方式,当系统发生异常时,不仅能够及时向用户反馈友好的错误提示,还能在日志文件中留下详细的异常信息,包括异常类型、堆栈跟踪等,为开发人员快速定位和解决问题提供有力支持。

  1. 根据异常类型返回不同的响应 :在实际应用中,不同类型的异常可能需要返回不同的响应给客户端,以满足多样化的业务需求。可以在SysExceptionResolver中根据异常类型进行更细致的处理:

java

复制代码
public class SysExceptionResolver implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse, Object o, Exception e) {
        e.printStackTrace();
        ModelAndView mv = new ModelAndView();
        if (e instanceof SysException) {
            SysException sysException = (SysException) e;
            mv.addObject("errorMsg", sysException.getMessage());
            mv.setViewName("sysError");
        } else if (e instanceof DataAccessException) {
            // 数据库访问异常
            mv.addObject("errorMsg", "数据库访问出现问题,请稍后重试");
            mv.setViewName("dbError");
        } else if (e instanceof AuthenticationException) {
            // 认证异常
            mv.addObject("errorMsg", "用户认证失败,请重新登录");
            mv.setViewName("authError");
        } else {
            // 其他未知异常
            mv.addObject("errorMsg", "系统发生未知错误,请联系管理员");
            mv.setViewName("unknownError");
        }
        return mv;
    }
}

通过这种方式,针对不同类型的异常,系统能够返回更具针对性的错误页面或提示信息,使用户能够更清楚地了解问题所在,同时也有助于开发人员更快速地诊断和解决异常。

  1. 全局异常处理与局部异常处理的结合:虽然全局异常处理器能够捕获并处理整个应用程序中的异常,但在某些情况下,可能需要在特定的控制器或方法中进行局部的异常处理,以满足特殊的业务逻辑需求。例如,在某个控制器方法中,可能希望对特定的业务异常进行单独处理,同时将其他异常交给全局异常处理器处理:

java

复制代码
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/save")
    public String save(User user) {
        try {
            // 业务逻辑,可能会抛出特定的业务异常
            if (user.getUsername() == null || user.getUsername().isEmpty()) {
                throw new BusinessException("用户名不能为空");
            }
            // 保存用户的业务代码
            userService.saveUser(user);
            return "suc";
        } catch (BusinessException be) {
            // 局部异常处理,针对业务异常进行特定处理
            ModelAndView mv = new ModelAndView();
            mv.addObject("errorMsg", be.getMessage());
            mv.setViewName("businessError");
            return mv;
        } catch (Exception e) {
            // 其他异常交给全局异常处理器处理
            throw e;
        }
    }
}

在这个例子中,save方法对BusinessException进行了局部处理,返回特定的错误视图businessError。而对于其他类型的异常,通过重新抛出异常,使其能够被全局异常处理器捕获并处理。这种全局异常处理与局部异常处理相结合的方式,能够使异常处理机制更加灵活和完善,更好地适应复杂的业务场景。

SpringMVC 的请求和响应机制涵盖了丰富的功能和细节,从请求映射、参数绑定、结果跳转、文件上传到异常处理,每个环节都紧密协作,为构建高效、稳定、安全的 Web 应用提供了坚实的基础。通过深入理解和灵活运用这些特性,开发者能够打造出更加优质的 Web 应用程序,满足不断变化的业务需求。

相关推荐
爱嘿嘿的小黑6 分钟前
docker 常用命令
前端
dangfulin9 分钟前
CSS——变换、过度与动画
前端·css
南屿欣风20 分钟前
解决 Gin Web 应用中 Air 热部署无效的问题
前端·gin
猿大师办公助手23 分钟前
Web网页内嵌福昕OFD版式办公套件实现在线预览编辑PDF、OFD文档
前端·pdf·word
超级无敌新新手小白1 小时前
Java----用正则表达式爬取数据
java·爬虫
王达舒19941 小时前
Spring Boot中定时任务Cron表达式的终极指南
java·spring boot·后端
幼儿园技术家1 小时前
什么是RESTful 或 GraphQL?
前端
王强你强1 小时前
Spring Boot 启动参数终极解析:如何优雅地控制你的应用?
java·spring boot·后端
Lonwayne1 小时前
当编程语言有了人格
java·javascript·c++·python·php
Sʜᴀᴅᴏᴡ . ₪3361 小时前
未授权rce漏洞
服务器·安全