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

简介: 构建健壮的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;
    }
}


目录
相关文章
|
2月前
|
JSON 程序员 数据格式
深入探索 “JSON for Modern C++“:安装、构建与应用
深入探索 “JSON for Modern C++“:安装、构建与应用
41 0
|
2月前
|
缓存 前端开发 Java
Spring MVC 面试题及答案整理,最新面试题
Spring MVC 面试题及答案整理,最新面试题
96 0
|
2月前
|
安全 Java 数据安全/隐私保护
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
67 1
|
2天前
|
监控 Java Sentinel
Spring Cloud Sentinel:概念与实战应用
【4月更文挑战第28天】在分布式微服务架构中,确保系统的稳定性和可靠性至关重要。Spring Cloud Sentinel 为微服务提供流量控制、熔断降级和系统负载保护,有效预防服务雪崩。本篇博客深入探讨 Spring Cloud Sentinel 的核心概念,并通过实际案例展示其在项目中的应用。
10 0
|
3天前
|
JSON fastjson Java
|
4天前
|
XML Java 数据格式
手写spring第六章-实现应用上下文,完成bean的扩展机制
手写spring第六章-实现应用上下文,完成bean的扩展机制
9 0
|
6天前
|
消息中间件 Java 中间件
第十六章 Spring cloud stream应用
第十六章 Spring cloud stream应用
11 0
|
9天前
|
JSON 运维 Kubernetes
云效产品使用报错问题之流水线中配置了AppStack,构建时下载的制品内容为json字符串,如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
18天前
|
数据采集 前端开发 Java
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
23 3
|
18天前
|
存储 前端开发 Java
会话锦囊:揭示Spring MVC如何巧妙使用@SessionAttributes
会话锦囊:揭示Spring MVC如何巧妙使用@SessionAttributes
14 1