构建健壮的Spring MVC应用:JSON响应与异常处理

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 构建健壮的Spring MVC应用:JSON响应与异常处理

1. 引言

探讨Spring MVC中关键的JSON数据返回和异常处理机制。

2. JSON

2.1 了解JSON数据格式


JSON(JavaScript Object Notation)作为一种数据交换格式具有许多特点和优势,这些特点使其成为广泛应用于Web和应用程序开发的理想选择。下面详细解释了JSON的特点和优势:

1. 轻量级和可读性


  • JSON是一种轻量级的文本格式,其数据结构以键-值对(key-value pairs)的形式表示,易于理解和阅读。
  • 与XML等其他数据格式相比,JSON更加简洁,不包含繁琐的标签和属性,使数据在传输和存储时更为紧凑。


2. 易于编写和解析


  • JSON数据的编写和解析在多种编程语言中都有成熟的支持和库,因此开发人员可以轻松地生成和解析JSON数据。
  • 多数现代编程语言都提供了内置的JSON解析器和生成器,使得操作JSON数据变得非常简单。


3. 自描述性


  • JSON数据包含字段名和相应的值,使得数据的结构和含义变得明确。
  • 数据结构本身包含在数据中,不需要额外的元数据或模式定义。



4. 支持多种数据类型

  • JSON支持多种基本数据类型,包括字符串、数字、布尔值、数组和对象(嵌套的键-值对结构)。
  • 这种灵活性允许开发人员表示各种复杂的数据结构。


5. 平台无关性

  • JSON是一种独立于平台的数据格式,可在各种操作系统和编程语言之间自由交换。
  • 这种特性使得不同技术栈的应用程序能够轻松地共享和解释JSON数据。


6. 易于集成

  • JSON适用于Web服务、API和数据交换,因此它是构建分布式系统和跨平台应用程序的理想选择。
  • 多数Web浏览器都原生支持JSON,使其成为前后端通信的常用数据格式。



7. 社区支持和标准化

  • JSON已成为Web应用程序中的事实标准,得到了广泛的社区支持。
  • 它的标准规范由RFC 8259定义,这进一步巩固了其在数据交换中的地位。


总的来说,JSON作为一种数据交换格式具有轻量级、可读性强、易于编写和解析、自描述、跨平台、灵活支持多种数据类型等优势。这些特点使得JSON在Web开发、API设计、数据交换以及分布式系统中都广泛应用,并且在不同领域的应用中表现出色。


2.2 Spring MVC中的JSON

导入依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.3</version>
</dependency> 


配置spring-mvc.xml

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
          <ref bean="mappingJackson2HttpMessageConverter"/>
        </list>
    </property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件-->
    <property name="supportedMediaTypes">
        <list>
            <value>text/html;charset=UTF-8</value>
            <value>text/json;charset=UTF-8</value>
            <value>application/json;charset=UTF-8</value>
        </list>
    </property>
</bean>


使用@ResponseBody注解

package com.liao.controller;
import com.liao.biz.UserBiz;
import com.liao.model.User;
import com.liao.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/user/json")
public class JsonController {
    @Autowired
    private UserBiz userBiz;
    @ResponseBody
    @RequestMapping("/list")
    public List<User> list(HttpServletRequest req, User user){
        PageBean pageBean = new PageBean();
        pageBean.setRequest(req);
        List<User> lst = this.userBiz.listPager(user, pageBean);
        System.out.println(1 / 0);
        return lst;
    }
    @ResponseBody
    @RequestMapping("/load")
    public User load(HttpServletRequest req, User user){
        if(user.getId() != null){
            List<User> lst = this.userBiz.listPager(user, null);
            return lst.get(0);
        }
        return null;
    }
    @ResponseBody
    @RequestMapping("/mapList")
    public List<Map> mapList(HttpServletRequest req, User user){
        PageBean pageBean = new PageBean();
        pageBean.setRequest(req);
        List<Map> lst = this.userBiz.mapListPager(user, pageBean);
        return lst;
    }
    @ResponseBody
    @RequestMapping("/mapLoad")
    public Map mapLoad(HttpServletRequest req, User user){
        if(user.getId() != null){
            List<Map> lst = this.userBiz.mapListPager(user, null);
            return lst.get(0);
        }
        return null;
    }
    @ResponseBody
    @RequestMapping("/all")
    public Map all(HttpServletRequest req, User user){
        PageBean pageBean = new PageBean();
        pageBean.setRequest(req);
        List<User> lst = this.userBiz.listPager(user, pageBean);
        Map map = new HashMap();
        map.put("lst",lst);
        map.put("pageBean",pageBean);
        return map;
    }
    @ResponseBody//
    @RequestMapping("/jsonStr")
    public String jsonStr(HttpServletRequest req, User user){
        return "userEdit";
    }
}

3. 高效处理异常

3.1 异常处理的必要性


Web应用程序需要有效的异常处理机制,因为异常是在应用程序运行过程中不可避免的情况,可以发生各种错误和异常情况,包括但不限于以下原因:


运行时错误: 应用程序可能会遇到运行时错误,例如空指针异常、数据库连接失败、文件不存在等。这些错误通常无法在编译时预测,但需要在运行时进行处理。


外部输入不可控: Web应用程序通常受到来自外部用户或其他系统的输入。用户可能会提供不正确或恶意的输入数据,这可能导致应用程序出现异常。有效的异常处理可以防止这些异常影响应用程序的稳定性和安全性。


资源不足或不可用: 在运行过程中,应用程序可能会遇到资源不足的情况,如数据库连接池用尽、磁盘空间耗尽等。这些情况需要适当的异常处理以避免应用程序崩溃。


网络通信问题: Web应用程序通常需要与其他系统或服务进行通信,这可能会导致网络故障或超时。有效的异常处理可以帮助应用程序优雅地处理这些问题。


业务逻辑异常: 有时应用程序需要捕获和处理与业务逻辑相关的异常情况,例如用户试图执行无权限操作、购物车中的商品数量超出库存等。


以下是为什么需要有效的异常处理机制的一些理由:


稳定性: 有效的异常处理可以帮助应用程序保持稳定性,避免崩溃或不可预测的行为。它可以使应用程序在出现异常情况时恢复正常状态或提供适当的错误信息。


安全性: 适当的异常处理可以增强应用程序的安全性,防止攻击者利用异常情况来获得敏感信息或执行恶意操作。


用户友好性: 异常处理应该提供有意义的错误消息,以便最终用户能够理解问题并采取适当的措施。这有助于提供更好的用户体验。


日志和监控: 通过异常处理,应用程序可以记录异常情况,以便开发人员能够诊断和解决问题。此外,它还可以用于监控应用程序的运行状况。


总之,有效的异常处理机制是确保Web应用程序稳定、安全且用户友好的关键组成部分。通过捕获、处理和记录异常,开发人员可以更好地管理和维护应用程序。


3.2.SpringMVC异常分类


使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;

实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;

使用@ControllerAdvice + @ExceptionHandler

综合案例

异常处理方式一

SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。



spring-mvc.xml

<!-- springmvc提供的简单异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!-- 定义默认的异常处理页面 -->
    <property name="defaultErrorView" value="error"/>
    <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception --> 
    <property name="exceptionAttribute" value="ex"/>
    <!-- 定义需要特殊处理的异常,这是重要点 --> 
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.RuntimeException">error</prop>
        </props>
      <!-- 还可以定义其他的自定义异常 -->
    </property>
</bean> 

前端异常页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>异常+界面</title>
</head>
<body>
错误信息界面。。。。。。
${ex}
</body>
</html>


a9cdd7c3d13349779fccacc3ac1302c8.png


异常处理方式二

创建一个名为GlobalException的自定义异常类

GlobalException

1.package com.liao.exception;
public class GlobalException extends RuntimeException {
    public GlobalException() {
    }
    public GlobalException(String message) {
        super(message);
    }
    public GlobalException(String message, Throwable cause) {
        super(message, cause);
    }
    public GlobalException(Throwable cause) {
        super(cause);
    }
    public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}


GlobalExceptionHandler

GlobalExceptionHandler实现HandlerExceptionResolver接口

package com.liao.component;
import com.liao.exception.GlobalException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");//error.jsp
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            mv.addObject("ex",globalException.getMessage());
            mv.addObject("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            mv.addObject("ex",runtimeException.getMessage());
            mv.addObject("msg","运行时异常....");
        }
        return mv;
    }
}


测试:

异常处理方式三

@ControllerAdvice + @ExceptionHandler

package com.liao.component;
import com.liao.exception.GlobalException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionResolver {
//    跳转错误页面
//    @ExceptionHandler
//    public ModelAndView handler(Exception e){
//        ModelAndView mv = new ModelAndView();
//        mv.setViewName("error");
//        if (e instanceof GlobalException){
//            GlobalException globalException = (GlobalException) e;
//            mv.addObject("ex",globalException.getMessage());
//            mv.addObject("msg","全局异常....");
//        }else if (e instanceof RuntimeException){
//            RuntimeException runtimeException = (RuntimeException) e;
//            mv.addObject("ex",runtimeException.getMessage());
//            mv.addObject("msg","运行时异常....");
//        }
//        return mv;
//    }
// 返回错误json数据
    @ResponseBody
    @ExceptionHandler
    public Map handler(Exception e){
        Map map = new HashMap();
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            map.put("ex",globalException.getMessage());
            map.put("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            map.put("ex",runtimeException.getMessage());
            map.put("msg","运行时异常....");
        }else {
            map.put("ex",e.getMessage());
            map.put("msg","其它异常....");
        }
        return map;
    }
}


目录
相关文章
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
46 4
|
1月前
|
Java API 数据库
如何使用Spring Boot构建RESTful API,以在线图书管理系统为例
【10月更文挑战第9天】本文介绍了如何使用Spring Boot构建RESTful API,以在线图书管理系统为例,从项目搭建、实体类定义、数据访问层创建、业务逻辑处理到RESTful API的实现,详细展示了每个步骤。通过Spring Boot的简洁配置和强大功能,开发者可以高效地开发出功能完备、易于维护的Web应用。
60 3
|
22天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
97 62
|
20天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
29天前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
1月前
|
JSON 前端开发 Java
Spring MVC——获取参数和响应
本文介绍了如何在Spring框架中通过不同的注解和方法获取URL参数、上传文件、处理cookie和session、以及响应不同类型的数据。具体内容包括使用`@PathVariable`获取URL中的参数,使用`MultipartFile`上传文件,通过`HttpServletRequest`和`@CookieValue`获取cookie,通过`HttpSession`和`@SessionAttribute`获取session,以及如何返回静态页面、HTML代码片段、JSON数据,并设置HTTP状态码和响应头。
50 1
Spring MVC——获取参数和响应
|
20天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
38 2
|
1月前
|
人工智能 开发框架 Java
总计 30 万奖金,Spring AI Alibaba 应用框架挑战赛开赛
Spring AI Alibaba 应用框架挑战赛邀请广大开发者参与开源项目的共建,助力项目快速发展,掌握 AI 应用开发模式。大赛分为《支持 Spring AI Alibaba 应用可视化调试与追踪本地工具》和《基于 Flow 的 AI 编排机制设计与实现》两个赛道,总计 30 万奖金。
|
29天前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
109 6
|
28天前
|
存储 Java 数据管理
强大!用 @Audited 注解增强 Spring Boot 应用,打造健壮的数据审计功能
本文深入介绍了如何在Spring Boot应用中使用`@Audited`注解和`spring-data-envers`实现数据审计功能,涵盖从添加依赖、配置实体类到查询审计数据的具体步骤,助力开发人员构建更加透明、合规的应用系统。
下一篇
无影云桌面